Exemple #1
0
 /**
  * Send a JSON Body to a URL after looking up the key and secret
  */
 public static function jsonSend($method, $postBody, $content_type, $service_url, &$debug_log = false)
 {
     $key_key = self::sessionGet('key_key');
     $secret = self::sessionGet('secret');
     $retval = LTI::sendJSONBody($method, $postBody, $content_type, $service_url, $key_key, $secret, $debug_log);
     return $retval;
 }
Exemple #2
0
    public function renderSingle()
    {
        global $CFG;
        $module = $this->module;
        echo '<div style="float:right; padding-left: 5px; vertical-align: text-top;"><ul class="pager">' . "\n";
        $disabled = $this->position == 1 ? ' disabled' : '';
        if ($this->position == 1) {
            echo '<li class="previous disabled"><a href="#" onclick="return false;">&larr; Previous</a></li>' . "\n";
        } else {
            $prev = 'index=' . ($this->position - 1);
            if (isset($this->lessons->modules[$this->position - 2]->anchor)) {
                $prev = 'anchor=' . $this->lessons->modules[$this->position - 2]->anchor;
            }
            echo '<li class="previous"><a href="lessons.php?' . $prev . '">&larr; Previous</a></li>' . "\n";
        }
        echo '<li><a href="lessons.php">All (' . $this->position . ' / ' . count($this->lessons->modules) . ')</a></li>';
        if ($this->position >= count($this->lessons->modules)) {
            echo '<li class="next disabled"><a href="#" onclick="return false;">&rarr; Next</a></li>' . "\n";
        } else {
            $next = 'index=' . ($this->position + 1);
            if (isset($this->lessons->modules[$this->position]->anchor)) {
                $next = 'anchor=' . $this->lessons->modules[$this->position]->anchor;
            }
            echo '<li class="next"><a href="lessons.php?' . $next . '">&rarr; Next</a></li>' . "\n";
        }
        echo "</ul></div>\n";
        echo '<h1>' . $module->title . "</h1>\n";
        if (isset($module->videos)) {
            $videos = $module->videos;
            echo '<ul class="bxslider">' . "\n";
            foreach ($videos as $video) {
                echo '<li><iframe src="https://www.youtube.com/embed/' . $video->youtube . '" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowfullscreen ' . ' alt="' . htmlentities($video->title) . '"></iframe>' . "\n";
            }
            echo "</ul>\n";
        }
        if (isset($module->description)) {
            echo '<p>' . $module->description . "</p>\n";
        }
        echo "<ul>\n";
        if (isset($module->slides)) {
            echo '<li><a href="' . $module->slides . '" target="_blank">Slides</a></li>' . "\n";
        }
        if (isset($module->chapters)) {
            echo '<li>Chapters: ' . $module->chapters . '</a></li>' . "\n";
        }
        if (isset($module->assignment)) {
            echo '<li><a href="' . $module->assignment . '" target="_blank">Assignment Specification</a></li>' . "\n";
        }
        if (isset($module->solution)) {
            echo '<li><a href="' . $module->solution . '" target="_blank">Assignment Solution</a></li>' . "\n";
        }
        if (isset($module->references)) {
            if (count($module->references) > 0) {
                echo "<li>References:<ul>\n";
                foreach ($module->references as $reference) {
                    echo '<li><a href="' . $reference->href . '" target="_blank">' . $reference->title . "</a></li>\n";
                }
                echo "</ul></li>\n";
            } else {
                echo '<li>Reference: <a href="' . $module->references->href . '" target="_blank">' . $module->references->title . "</a></li>\n";
            }
        }
        if (isset($module->lti) && isset($_SESSION['secret'])) {
            $ltis = $module->lti;
            if (count($ltis) > 1) {
                echo "<li>Tools:<ul> <!-- start of ltis -->\n";
            }
            $count = 0;
            foreach ($ltis as $lti) {
                $key = isset($_SESSION['oauth_consumer_key']) ? $_SESSION['oauth_consumer_key'] : false;
                $secret = isset($_SESSION['secret']) ? $_SESSION['secret'] : false;
                if (isset($lti->resource_link_id)) {
                    $resource_link_id = $lti->resource_link_id;
                } else {
                    $resource_link_id = 'resource:';
                    if ($this->anchor != null) {
                        $resource_link_id .= $this->anchor . ':';
                    }
                    if ($this->position != null) {
                        $resource_link_id .= $this->position . ':';
                    }
                    if ($count > 0) {
                        $resource_link_id .= '_' . $count;
                    }
                    $resource_link_id .= md5($CFG->context_title);
                }
                $count++;
                $resource_link_title = isset($lti->title) ? $lti->title : $module->title;
                $parms = array('lti_message_type' => 'basic-lti-launch-request', 'resource_link_id' => $resource_link_id, 'resource_link_title' => $resource_link_title, 'tool_consumer_info_product_family_code' => 'tsugi', 'tool_consumer_info_version' => '1.1', 'context_id' => $_SESSION['context_key'], 'context_label' => $CFG->context_title, 'context_title' => $CFG->context_title, 'user_id' => $_SESSION['user_key'], 'lis_person_name_full' => $_SESSION['displayname'], 'lis_person_contact_email_primary' => $_SESSION['email'], 'roles' => 'Learner');
                if (isset($_SESSION['avatar'])) {
                    $parms['user_image'] = $_SESSION['avatar'];
                }
                if (isset($lti->custom)) {
                    foreach ($lti->custom as $custom) {
                        if (isset($custom->value)) {
                            $parms['custom_' . $custom->key] = $custom->value;
                        }
                        if (isset($custom->json)) {
                            $parms['custom_' . $custom->key] = json_encode($custom->json);
                        }
                    }
                }
                $return_url = $CFG->getCurrentUrl();
                if ($this->anchor) {
                    $return_url .= '?anchor=' . urlencode($this->anchor);
                } elseif ($this->position) {
                    $return_url .= '?index=' . urlencode($this->position);
                }
                $parms['launch_presentation_return_url'] = $return_url;
                if (isset($_SESSION['tsugi_top_nav'])) {
                    $parms['ext_tsugi_top_nav'] = $_SESSION['tsugi_top_nav'];
                }
                $form_id = "tsugi_form_id_" . bin2Hex(openssl_random_pseudo_bytes(4));
                $parms['ext_lti_form_id'] = $form_id;
                $endpoint = $lti->launch;
                $parms = LTI::signParameters($parms, $endpoint, "POST", $key, $secret, "Finish Launch", $CFG->product_instance_guid, $CFG->servicename);
                $content = LTI::postLaunchHTML($parms, $endpoint, false, '_pause');
                $title = isset($lti->title) ? $lti->title : "Autograder";
                echo '<li><a href="#" onclick="document.' . $form_id . '.submit();return false">' . htmlentities($title) . '</a></li>' . "\n";
                echo "<!-- Start of content -->\n";
                print $content;
                echo "<!-- End of content -->\n";
            }
            if (count($ltis) > 1) {
                echo "</li></ul><!-- end of ltis -->\n";
            }
        }
        if (!isset($module->discuss)) {
            $module->discuss = true;
        }
        if (!isset($module->anchor)) {
            $module->anchor = $this->position;
        }
        // For now do not add disqus to each page.
        if (false && isset($CFG->disqushost) && isset($_SESSION['id']) && $module->discuss) {
            ?>
<hr/>
<div id="disqus_thread" style="margin-top: 30px;"></div>
<script>

/**
 *  RECOMMENDED CONFIGURATION VARIABLES: EDIT AND UNCOMMENT THE SECTION BELOW TO INSERT DYNAMIC VALUES FROM YOUR PLATFORM OR CMS.
 *  LEARN WHY DEFINING THESE VARIABLES IS IMPORTANT: https://disqus.com/admin/universalcode/#configuration-variables */
var disqus_config = function () {
    this.page.url = '<?php 
            echo $CFG->disqushost;
            ?>
';  // Replace PAGE_URL with your page's canonical URL variable
    this.page.identifier = '<?php 
            echo $module->anchor;
            ?>
'; // Replace PAGE_IDENTIFIER with your page's unique identifier variable
};
(function() { // DON'T EDIT BELOW THIS LINE
    var d = document, s = d.createElement('script');
    s.src = '//php-intro.disqus.com/embed.js';
    s.setAttribute('data-timestamp', +new Date());
    (d.head || d.body).appendChild(s);
})();
</script>
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<?php 
        }
    }
if (strlen($oauth_consumer_key) < 1 || strlen($oauth_consumer_secret) < 1) {
    echo sprintf($response, uniqid(), 'failure', "Missing key/secret B64={$b64dec} B64key={$oauth_consumer_key} secret={$oauth_consumer_secret}", $message_ref, $operation, "");
    exit;
}
$header_key = LTI::getOAuthKeyFromHeaders();
if (strlen($header_key) < 1) {
    echo sprintf($response, uniqid(), 'failure', "Empty header key. Note that some proxy configurations do not pass the Authorization header.", $message_ref, $operation, "");
    exit;
} else {
    if ($header_key != $oauth_consumer_key) {
        echo sprintf($response, uniqid(), 'failure', "B64key={$oauth_consumer_key} HDR={$header_key}", $message_ref, $operation, "");
        exit;
    }
}
try {
    $body = LTI::handleOAuthBodyPOST($oauth_consumer_key, $oauth_consumer_secret);
    $xml = new SimpleXMLElement($body);
    $imsx_header = $xml->imsx_POXHeader->children();
    $parms = $imsx_header->children();
    $message_ref = (string) $parms->imsx_messageIdentifier;
    $imsx_body = $xml->imsx_POXBody->children();
    $operation = $imsx_body->getName();
    $parms = $imsx_body->children();
} catch (Exception $e) {
    global $LastOAuthBodyBaseString;
    global $LastOAuthBodyHashInfo;
    $retval = sprintf($response, uniqid(), 'failure', $e->getMessage() . " B64key={$oauth_consumer_key} HDRkey={$header_key} secret={$oauth_consumer_secret}", uniqid(), $operation, "") . "<!--\n" . "Base String:\n" . $LastOAuthBodyBaseString . "\n" . "Hash Info:\n" . $LastOAuthBodyHashInfo . "\n-->\n";
    echo $retval;
    exit;
}
$sourcedid = (string) $parms->resultRecord->sourcedGUID->sourcedId;
Exemple #4
0
 /**
  * Send a grade and update our local copy
  *
  * Call the right LTI service to send a new grade up to the server.
  * update our local cached copy of the server_grade and the date
  * retrieved. This routine pulls the key and secret from the LTIX
  * session to avoid crossing cross tennant boundaries.
  *
  * @param $grade A new grade - floating point number between 0.0 and 1.0
  * @param $row An optional array with the data that has the result_id, sourcedid,
  * and service (url) if this is not present, the data is pulled from the LTI
  * session for the current user/link combination.
  * @param $debug_log An (optional) array (by reference) that returns the
  * steps that were taken.
  * Each entry is an array with the [0] element a message and an optional [1]
  * element as some detail (i.e. like a POST body)
  *
  * @return mixed If this works it returns true.  If not, you get
  * a string with an error.
  *
  */
 public function gradeSend($grade, $row = false, &$debug_log = false)
 {
     global $CFG, $USER;
     global $LastPOXGradeResponse;
     $LastPOXGradeResponse = false;
     $PDOX = LTIX::getConnection();
     // Secret and key from session to avoid crossing tenant boundaries
     $key_key = LTIX::sessionGet('key_key');
     $secret = LTIX::sessionGet('secret');
     if ($row !== false) {
         $result_url = isset($row['result_url']) ? $row['result_url'] : false;
         $sourcedid = isset($row['sourcedid']) ? $row['sourcedid'] : false;
         $service = isset($row['service']) ? $row['service'] : false;
         // Fall back to session if it is missing
         if ($service === false) {
             $service = LTIX::sessionGet('service');
         }
         $result_id = isset($row['result_id']) ? $row['result_id'] : false;
     } else {
         $result_url = LTIX::sessionGet('result_url');
         $sourcedid = LTIX::sessionGet('sourcedid');
         $service = LTIX::sessionGet('service');
         $result_id = LTIX::sessionGet('result_id');
     }
     // Update result in the database and in the LTI session area and
     // our local copy
     $_SESSION['lti']['grade'] = $grade;
     $this->grade = $grade;
     // Update the local copy of the grade in the lti_result table
     if ($PDOX !== false && $result_id !== false) {
         $stmt = $PDOX->queryReturnError("UPDATE {$CFG->dbprefix}lti_result SET grade = :grade,\n                    updated_at = NOW() WHERE result_id = :RID", array(':grade' => $grade, ':RID' => $result_id));
         if ($stmt->success) {
             $msg = "Grade updated result_id=" . $result_id . " grade={$grade}";
         } else {
             $msg = "Grade NOT updated result_id=" . $result_id . " grade={$grade}";
         }
         error_log($msg);
         if (is_array($debug_log)) {
             $debug_log[] = array($msg);
         }
     }
     if ($key_key == false || $secret === false || $sourcedid === false || $service === false || !isset($USER)) {
         error_log("Result::gradeSend stored data locally");
         return false;
     }
     // TODO: Fix this
     $comment = "";
     if (strlen($result_url) > 0) {
         $status = LTI::sendJSONGrade($grade, $comment, $result_url, $key_key, $secret, $debug_log);
     } else {
         $status = LTI::sendPOXGrade($grade, $sourcedid, $service, $key_key, $secret, $debug_log);
     }
     if ($status === true) {
         $msg = 'Grade sent ' . $grade . ' to ' . $sourcedid . ' by ' . $USER->id;
         if (is_array($debug_log)) {
             $debug_log[] = array($msg);
         }
         error_log($msg);
     } else {
         $msg = 'Grade failure ' . $grade . ' to ' . $sourcedid . ' by ' . $USER->id;
         if (is_array($debug_log)) {
             $debug_log[] = array($msg);
         }
         error_log($msg);
         return $status;
     }
     return $status;
 }
Exemple #5
0
    // a race condition between competing INSERTs for the same key_id
} else {
    $key_sha256 = lti_sha256($oauth_consumer_key);
    $retval = $PDOX->queryDie("INSERT INTO {$CFG->dbprefix}lti_key \n            (key_sha256, key_key, user_id, secret, consumer_profile)\n        VALUES\n            (:SHA, :KEY, :UID, :SECRET, :PROFILE)\n        ON DUPLICATE KEY\n            UPDATE secret = :SECRET, consumer_profile = :PROFILE\n        ", array(":SHA" => $key_sha256, ":KEY" => $oauth_consumer_key, ":UID" => $_SESSION['id'], ":SECRET" => $shared_secret, ":PROFILE" => $tc_profile_json));
    if (!$retval->success) {
        log_return_die("Unable to INSERT Registration key {$oauth_consumer_key} " . $retval->errorImplode);
    }
    $return_url_lti_message = "LTI2 Key {$oauth_consumer_key} inserted";
}
echo_log("{$return_url_lti_message} \n");
if ($last_http_response == 201 || $last_http_response == 200) {
    if (strpos($launch_presentation_return_url, '?') > 0) {
        $launch_presentation_return_url .= '&';
    } else {
        $launch_presentation_return_url .= '?';
    }
    $launch_presentation_return_url .= "status=success";
    $launch_presentation_return_url .= "&lti_message=" . urlencode($return_url_lti_message);
    $launch_presentation_return_url .= "&tool_proxy_guid=" . urlencode($tc_tool_proxy_guid);
    echo '<p><a href="' . $launch_presentation_return_url . '">Continue to launch_presentation_url</a></p>' . "\n";
    exit;
}
echo "Registration failed, http code=" . $last_http_response . "\n";
// Check to see if they slid us the base string...
if ($responseObject != null && isset($responseObject->base_string)) {
    $base_string = $responseObject->base_string;
    if (strlen($base_string) > 0 && strlen($LastOAuthBodyBaseString) > 0 && $base_string != $LastOAuthBodyBaseString) {
        $compare = LTI::compareBaseStrings($LastOAuthBodyBaseString, $base_string);
        $OUTPUT->togglePre("Compare Base Strings (ours first)", htmlent_utf8($compare));
    }
}
Exemple #6
0
    echo "<br/>\n";
}
echo "</fieldset>\n";
echo "</div>\n";
echo "</form>\n";
$parms = $lmsdata;
// Cleanup parms before we sign
foreach ($parms as $k => $val) {
    if (strlen(trim($parms[$k])) < 1) {
        unset($parms[$k]);
    }
}
// Add oauth_callback to be compliant with the 1.0A spec
$parms["oauth_callback"] = "about:blank";
if ($outcomes) {
    $parms["lis_outcome_service_url"] = $outcomes;
}
$parms['launch_presentation_css_url'] = $cssurl;
if (isset($_POST['launch']) || isset($_POST['debug'])) {
    // Switch to direct launches instead of going through lti.php
    $endpoint = str_replace("lti.php", $_POST['custom_assn'], $endpoint);
    $parms = LTI::signParameters($parms, $endpoint, "POST", $key, $secret, "Finish Launch", $tool_consumer_instance_guid, $tool_consumer_instance_description);
    $content = LTI::postLaunchHTML($parms, $endpoint, isset($_POST['debug']), "width=\"100%\" height=\"900\" scrolling=\"auto\" frameborder=\"1\" transparency");
    echo "<hr>\n";
    print $content;
}
?>
      </div>
    </div> <!-- /container -->
<?php 
$OUTPUT->footer();
Exemple #7
0
        $script = isset($REGISTER_LTI2['script']) ? $REGISTER_LTI2['script'] : "index.php";
        $path = $CFG->wwwroot . '/' . str_replace("register.php", $script, $path);
        // Title is for the href and text is for display
        $json = LTI::getLtiLinkJSON($path, $title, $title, false, $fa_icon);
        $retval = json_encode($json);
        $parms = array();
        $parms["lti_message_type"] = "ContentItemSelection";
        $parms["lti_version"] = "LTI-1p0";
        $parms["content_items"] = $retval;
        $data = LTIX::postGet('data');
        if ($data) {
            $parms['data'] = $data;
        }
        $parms = LTIX::signParameters($parms, $result_url, "POST", "Install Tool");
        $endform = '<a href="index.php" class="btn btn-warning">Back to Store</a>';
        $content = LTI::postLaunchHTML($parms, $result_url, true, false, $endform);
        echo $content;
    } else {
        echo '<div style="border: 2px, solid, red;" class="card">';
        if ($fa_icon) {
            echo '<a href="index.php?install=' . urlencode($tool) . '">';
            echo '<i class="fa ' . $fa_icon . ' fa-2x" style="color: #1894C7; float:right; margin: 2px"></i>';
            echo '</a>';
        }
        echo '<p><strong>' . htmlent_utf8($title) . "</strong></p>";
        echo '<p>' . htmlent_utf8($text) . "</p>\n";
        echo '<center><a href="index.php?install=' . urlencode($tool) . '" class="btn btn-default" role="button">Details</a></center>';
        echo "</div>\n";
    }
    $toolcount++;
}
Exemple #8
0
 /**
  * Send settings to the LMS using the simple JSON approach
  */
 public static function settingsSend($settings, $settings_url, &$debug_log = false)
 {
     global $CFG, $PDOX, $LINK, $USER;
     global $LastPOXGradeResponse;
     $LastPOXGradeResponse = false;
     $key_key = self::sessionGet('key_key');
     $secret = self::sessionGet('secret');
     $retval = LTI::sendJSONSettings($settings, $settings_url, $key_key, $secret, $debug_log);
     return $retval;
 }
Exemple #9
0
} else {
    if (function_exists('http_response_code')) {
        http_response_code(400);
    }
    error_log("Method not allowed in commit: {$method}");
    die("Transaction not found");
}
$row = $PDOX->rowDie("SELECT secret\n        FROM {$CFG->dbprefix}lti_key\n        WHERE ack = :ACK AND key_sha256 = :SHA LIMIT 1", array(":SHA" => $key_sha256, ":ACK" => $commit));
if ($row == false) {
    if (function_exists('http_response_code')) {
        http_response_code(404);
    }
    error_log("Transaction {$commit} not found {$oauth_consumer_key}");
    die("Transaction not found");
}
$retval = LTI::verifyKeyAndSecret($oauth_consumer_key, $row['secret']);
if ($retval !== true) {
    if (function_exists('http_response_code')) {
        http_response_code(404);
    }
    error_log("LTI Failure:" . $retval[0] . "\n" . $retval[1]);
    die("LTI Failure:" . $retval[0] . "\n" . $retval[1]);
}
if ($method == "PUT") {
    $stmt = $PDOX->queryDie("UPDATE {$CFG->dbprefix}lti_key\n            SET secret = new_secret,\n\t        new_secret = NULL, ack = NULL\n            WHERE new_secret IS NOT NULL AND \n            ack = :ACK AND key_sha256 = :SHA", array(":SHA" => $key_sha256, ":ACK" => $commit));
    $count = $stmt->rowCount();
    error_log("Committed Key={$oauth_consumer_key} rows updated={$count}");
} else {
    $stmt = $PDOX->queryDie("UPDATE {$CFG->dbprefix}lti_key\n            SET new_secret = NULL\n            WHERE ack = :ACK AND key_sha256 = :SHA", array(":SHA" => $key_sha256, ":ACK" => $commit));
    $count = $stmt->rowCount();
    error_log("Roll-Back Key={$oauth_consumer_key} rows updated={$count}");
Exemple #10
0
 /**
  * getLaunchContent - Get the launch data for am LTI ContentItem launch
  */
 public static function getLaunchContent($endpoint, $debug = false)
 {
     $info = LTIX::getKeySecretForLaunch($endpoint);
     if ($info === false) {
         return '<p style="color:red">Unable to load key/secret for ' . htmlentities($endpoint) . "</p>\n";
     }
     $key = $info['key'];
     $secret = $info['secret'];
     $parms = LTIX::getLaunchData();
     $parms = LTI::signParameters($parms, $endpoint, "POST", $key, $secret, "Button");
     $content = LTI::postLaunchHTML($parms, $endpoint, false);
     return $content;
 }
Exemple #11
0
 /**
  * ltiLinkUrl - Returns true if we can return LTI Links for this launch
  *
  * @return string The content_item_return_url or false
  */
 public static function ltiLinkUrl($postdata = false)
 {
     return LTI::ltiLinkUrl(self::postArray());
 }