/**
  * Checks whether the given URL is blacklisted by checking its address and port number against the black/white lists.
  * The behaviour of this function can be classified as strict, as it returns true for URLs which are invalid or
  * could not be parsed, as well as those valid URLs which were found in the blacklist.
  *
  * @param string $urlstring the URL to check.
  * @return bool true if the URL is blacklisted or invalid and false if the URL is not blacklisted.
  */
 public function url_is_blocked($urlstring)
 {
     // If no config data is present, then all hosts/ports are allowed.
     if (!$this->is_enabled()) {
         return false;
     }
     // Try to parse the URL to get the 'host' and 'port' components.
     try {
         $url = new \moodle_url($urlstring);
         $parsed['scheme'] = $url->get_scheme();
         $parsed['host'] = $url->get_host();
         $parsed['port'] = $url->get_port();
     } catch (\moodle_exception $e) {
         // Moodle exception is thrown if the $urlstring is invalid. Treat as blocked.
         return true;
     }
     // The port will be empty unless explicitly set in the $url (uncommon), so try to infer it from the supported schemes.
     if (!$parsed['port'] && $parsed['scheme'] && isset($this->transportschemes[$parsed['scheme']])) {
         $parsed['port'] = $this->transportschemes[$parsed['scheme']];
     }
     if ($parsed['port'] && $parsed['host']) {
         // Check the host and port against the blacklist/whitelist entries.
         return $this->host_is_blocked($parsed['host']) || $this->port_is_blocked($parsed['port']);
     }
     return true;
 }
 public function test_moodle_url_get_scheme()
 {
     // Should return the scheme only.
     $url = new moodle_url('http://www.example.org:447/my/file/is/here.txt?really=1');
     $this->assertSame('http', $url->get_scheme());
     // Should work for secure URLs.
     $url = new moodle_url('https://www.example.org:447/my/file/is/here.txt?really=1');
     $this->assertSame('https', $url->get_scheme());
     // Should return an empty string if no scheme is specified.
     $url = new moodle_url('www.example.org:447/my/file/is/here.txt?really=1');
     $this->assertSame('', $url->get_scheme());
 }
Example #3
0
/**
 * Processes the tool provider's response to the ContentItemSelectionRequest and builds the configuration data from the
 * selected content item. This configuration data can be then used when adding a tool into the course.
 *
 * @param int $typeid The tool type ID.
 * @param string $messagetype The value for the lti_message_type parameter.
 * @param string $ltiversion The value for the lti_version parameter.
 * @param string $consumerkey The consumer key.
 * @param string $contentitemsjson The JSON string for the content_items parameter.
 * @return stdClass The array of module information objects.
 * @throws moodle_exception
 * @throws lti\OAuthException
 */
function lti_tool_configuration_from_content_item($typeid, $messagetype, $ltiversion, $consumerkey, $contentitemsjson)
{
    $tool = lti_get_type($typeid);
    // Validate parameters.
    if (!$tool) {
        throw new moodle_exception('errortooltypenotfound', 'mod_lti');
    }
    // Check lti_message_type. Show debugging if it's not set to ContentItemSelection.
    // No need to throw exceptions for now since lti_message_type does not seem to be used in this processing at the moment.
    if ($messagetype !== 'ContentItemSelection') {
        debugging("lti_message_type is invalid: {$messagetype}. It should be set to 'ContentItemSelection'.", DEBUG_DEVELOPER);
    }
    $typeconfig = lti_get_type_config($typeid);
    if (isset($tool->toolproxyid)) {
        $islti2 = true;
        $toolproxy = lti_get_tool_proxy($tool->toolproxyid);
        $key = $toolproxy->guid;
        $secret = $toolproxy->secret;
    } else {
        $islti2 = false;
        $toolproxy = null;
        if (!empty($typeconfig['resourcekey'])) {
            $key = $typeconfig['resourcekey'];
        } else {
            $key = '';
        }
        if (!empty($typeconfig['password'])) {
            $secret = $typeconfig['password'];
        } else {
            $secret = '';
        }
    }
    // Check LTI versions from our side and the response's side. Show debugging if they don't match.
    // No need to throw exceptions for now since LTI version does not seem to be used in this processing at the moment.
    $expectedversion = LTI_VERSION_1;
    if ($islti2) {
        $expectedversion = LTI_VERSION_2;
    }
    if ($ltiversion !== $expectedversion) {
        debugging("lti_version from response does not match the tool's configuration. Tool: {$expectedversion}," . " Response: {$ltiversion}", DEBUG_DEVELOPER);
    }
    if ($consumerkey !== $key) {
        throw new moodle_exception('errorincorrectconsumerkey', 'mod_lti');
    }
    $store = new lti\TrivialOAuthDataStore();
    $store->add_consumer($key, $secret);
    $server = new lti\OAuthServer($store);
    $method = new lti\OAuthSignatureMethod_HMAC_SHA1();
    $server->add_signature_method($method);
    $request = lti\OAuthRequest::from_request();
    try {
        $server->verify_request($request);
    } catch (lti\OAuthException $e) {
        throw new lti\OAuthException("OAuth signature failed: " . $e->getMessage());
    }
    $items = json_decode($contentitemsjson);
    if (empty($items)) {
        throw new moodle_exception('errorinvaliddata', 'mod_lti', '', $contentitemsjson);
    }
    if ($items->{'@context'} !== 'http://purl.imsglobal.org/ctx/lti/v1/ContentItem') {
        throw new moodle_exception('errorinvalidmediatype', 'mod_lti', '', $items->{'@context'});
    }
    if (!isset($items->{'@graph'}) || !is_array($items->{'@graph'}) || count($items->{'@graph'}) > 1) {
        throw new moodle_exception('errorinvalidresponseformat', 'mod_lti');
    }
    $config = null;
    if (!empty($items->{'@graph'})) {
        $item = $items->{'@graph'}[0];
        $config = new stdClass();
        $config->name = '';
        if (isset($item->title)) {
            $config->name = $item->title;
        }
        if (empty($config->name)) {
            $config->name = $tool->name;
        }
        if (isset($item->text)) {
            $config->introeditor = ['text' => $item->text, 'format' => FORMAT_PLAIN];
        }
        if (isset($item->icon->{'@id'})) {
            $iconurl = new moodle_url($item->icon->{'@id'});
            // Assign item's icon URL to secureicon or icon depending on its scheme.
            if (strtolower($iconurl->get_scheme()) === 'https') {
                $config->secureicon = $iconurl->out(false);
            } else {
                $config->icon = $iconurl->out(false);
            }
        }
        if (isset($item->url)) {
            $url = new moodle_url($item->url);
            // Assign item URL to securetoolurl or toolurl depending on its scheme.
            if (strtolower($url->get_scheme()) === 'https') {
                $config->securetoolurl = $url->out(false);
            } else {
                $config->toolurl = $url->out(false);
            }
            $config->typeid = 0;
        } else {
            $config->typeid = $typeid;
        }
        $config->instructorchoicesendname = LTI_SETTING_NEVER;
        $config->instructorchoicesendemailaddr = LTI_SETTING_NEVER;
        $config->instructorchoiceacceptgrades = LTI_SETTING_NEVER;
        $config->launchcontainer = LTI_LAUNCH_CONTAINER_DEFAULT;
        if (isset($item->placementAdvice->presentationDocumentTarget)) {
            if ($item->placementAdvice->presentationDocumentTarget === 'window') {
                $config->launchcontainer = LTI_LAUNCH_CONTAINER_WINDOW;
            } else {
                if ($item->placementAdvice->presentationDocumentTarget === 'frame') {
                    $config->launchcontainer = LTI_LAUNCH_CONTAINER_EMBED_NO_BLOCKS;
                } else {
                    if ($item->placementAdvice->presentationDocumentTarget === 'iframe') {
                        $config->launchcontainer = LTI_LAUNCH_CONTAINER_EMBED;
                    }
                }
            }
        }
        if (isset($item->custom)) {
            $customparameters = [];
            foreach ($item->custom as $key => $value) {
                $customparameters[] = "{$key}={$value}";
            }
            $config->instructorcustomparameters = implode("\n", $customparameters);
        }
    }
    return $config;
}