Esempio n. 1
0
 public static function send($to, $subject, $message, $id, $token)
 {
     global $CFG;
     if (!isset($CFG->maildomain) || $CFG->maildomain === false) {
         return;
     }
     if (isset($CFG->maileol) && isset($CFG->wwwroot) && isset($CFG->maildomain)) {
         // All good
     } else {
         die_with_error_log("Incomplete mail configuration in mailSend");
     }
     if (strlen($to) < 1 || strlen($subject) < 1 || strlen($id) < 1 || strlen($token) < 1) {
         return false;
     }
     $EOL = $CFG->maileol;
     $maildomain = $CFG->maildomain;
     $manage = $CFG->wwwroot . "/profile.php";
     $unsubscribe_url = Output::getUtilUrl("/unsubscribe.php?id={$id}&token={$token}");
     $msg = $message;
     if (substr($msg, -1) != "\n") {
         $msg .= "\n";
     }
     // $msg .= "\nYou can manage your mail preferences at $manage \n";
     // TODO: Make unsubscribe work
     // echo $msg;
     $headers = "From: no-reply@{$maildomain}" . $EOL . "Return-Path: <bounced-{$id}-{$token}@{$maildomain}>" . $EOL . "List-Unsubscribe: <{$unsubscribe_url}>" . $EOL . 'X-Mailer: PHP/' . phpversion();
     error_log("Mail to: {$to} {$subject}");
     // echo $headers;
     return mail($to, $subject, $msg, $headers);
 }
Esempio n. 2
0
 public function __construct($name = 'lessons.json')
 {
     global $CFG;
     $json_str = file_get_contents($name);
     $lessons = json_decode($json_str);
     $this->resource_links = array();
     if ($lessons === null) {
         echo "<pre>\n";
         echo "Problem parsing lessons.json: ";
         echo json_last_error_msg();
         echo "\n";
         echo $json_str;
         die;
     }
     // Demand that every module have required elments
     foreach ($lessons->modules as $module) {
         if (!isset($module->title)) {
             die_with_error_log('All modules in a lesson must have a title');
         }
         if (!isset($module->anchor)) {
             die_with_error_log('All modules must have an anchor: ' . $module->title);
         }
     }
     // Demand that every module have required elments
     foreach ($lessons->badges as $badge) {
         if (!isset($badge->title)) {
             die_with_error_log('All badges in a lesson must have a title');
         }
         if (!isset($badge->assignments)) {
             die_with_error_log('All badges must have assignments: ' . $badge->title);
         }
     }
     // Filter modules based on login
     if (!isset($_SESSION['id'])) {
         $filtered_modules = array();
         $filtered = false;
         foreach ($lessons->modules as $module) {
             if (isset($module->login) && $module->login) {
                 $filtered = true;
                 continue;
             }
             $filtered_modules[] = $module;
         }
         if ($filtered) {
             $lessons->modules = $filtered_modules;
         }
     }
     $this->lessons = $lessons;
     // Pretty up the data structure
     for ($i = 0; $i < count($this->lessons->modules); $i++) {
         if (isset($this->lessons->modules[$i]->videos)) {
             self::adjustArray($this->lessons->modules[$i]->videos);
         }
         if (isset($this->lessons->modules[$i]->references)) {
             self::adjustArray($this->lessons->modules[$i]->references);
         }
         if (isset($this->lessons->modules[$i]->lti)) {
             self::adjustArray($this->lessons->modules[$i]->lti);
         }
         // Non arrays
         if (isset($this->lessons->modules[$i]->slides)) {
             self::makeAbsolute($this->lessons->modules[$i]->slides);
         }
         if (isset($this->lessons->modules[$i]->assignment)) {
             self::makeAbsolute($this->lessons->modules[$i]->assignment);
         }
         if (isset($this->lessons->modules[$i]->solution)) {
             self::makeAbsolute($this->lessons->modules[$i]->solution);
         }
     }
     // Patch badges
     if (isset($this->lessons->badges)) {
         for ($i = 0; $i < count($this->lessons->badges); $i++) {
             if (!isset($this->lessons->badges[$i]->threshold)) {
                 $this->lessons->badges[$i]->threshold = 1.0;
             }
         }
     }
     // Make sure resource links are unique and remember them
     foreach ($this->lessons->modules as $module) {
         if (isset($module->lti)) {
             $ltis = $module->lti;
             if (!is_array($ltis)) {
                 $ltis = array($ltis);
             }
             foreach ($ltis as $lti) {
                 if (!isset($lti->title)) {
                     die_with_error_log('Missing lti title in module:' . $module->title);
                 }
                 if (!isset($lti->resource_link_id)) {
                     die_with_error_log('Missing resource link in Lessons ' . $lti->title);
                 }
                 if (isset($this->resource_links[$lti->resource_link_id])) {
                     die_with_error_log('Duplicate resource link in Lessons ' . $lti->resource_link_id);
                 }
                 $this->resource_links[$lti->resource_link_id] = $module->anchor;
             }
         }
     }
     $anchor = isset($_GET['anchor']) ? $_GET['anchor'] : null;
     $index = isset($_GET['index']) ? $_GET['index'] : null;
     // Search for the selected anchor or index position
     $count = 0;
     $module = false;
     if ($anchor || $index) {
         foreach ($lessons->modules as $mod) {
             $count++;
             if ($anchor !== null && isset($mod->anchor) && $anchor != $mod->anchor) {
                 continue;
             }
             if ($index !== null && $index != $count) {
                 continue;
             }
             if ($anchor == null && isset($module->anchor)) {
                 $anchor = $module->anchor;
             }
             $this->module = $mod;
             $this->position = $count;
             if ($mod->anchor) {
                 $this->anchor = $mod->anchor;
             }
         }
     }
     return true;
 }
Esempio n. 3
0
 function bodyStart($checkpost = true)
 {
     echo "\n</head>\n<body style=\"padding: 15px 15px 15px 15px;\">\n";
     if ($checkpost && count($_POST) > 0) {
         $dump = safe_var_dump($_POST);
         echo '<p style="color:red">Error - Unhandled POST request</p>';
         echo "\n<pre>\n";
         echo $dump;
         echo "\n</pre>\n";
         error_log($dump);
         die_with_error_log("Unhandled POST request");
     }
 }
Esempio n. 4
0
File: LTIX.php Progetto: na1iu/tsugi
 /**
  * Handle launch and/or set up the LTI session and global variables
  *
  * Make sure we have the values we need in the LTI session
  * This routine will not start a session if none exists.  It will
  * die is there if no session_name() (PHPSESSID) cookie or
  * parameter.  No need to create any fresh sessions here.
  * 
  * @param $needed (optional, mixed)  Indicates which of 
  * the data structures are * needed. If this is omitted, 
  * this assumes that CONTEXT, LINK, and USER data are required.  
  * If LTIX::NONE is present, then none of the three are rquired.
  * If some combination of the three are needed, this accepts
  * an array of the LTIX::CONTEXT, LTIX: LINK, and LTIX::USER
  * can be passed in.
  *
  */
 public static function requireData($needed = self::ALL)
 {
     global $CFG, $USER, $CONTEXT, $LINK;
     if ($needed == self::NONE) {
         $needed = array();
     }
     if ($needed == self::ALL) {
         $needed = array(self::CONTEXT, self::LINK, self::USER);
     }
     if (is_string($needed)) {
         $needed = array($needed);
     }
     // Check if we are processing an LTI launch.  If so, handle it
     self::launchCheck();
     // Check to see if the session already exists.
     $sess = session_name();
     if (ini_get('session.use_cookies') != '0') {
         if (!isset($_COOKIE[$sess])) {
             send403();
             die_with_error_log("Missing session cookie - please re-launch");
         }
     } else {
         // non-cookie session
         if (isset($_POST[$sess]) || isset($_GET[$sess])) {
             // We tried to set a session..
         } else {
             if ($_SERVER['REQUEST_METHOD'] == 'POST') {
                 send403();
                 die_with_error_log('Missing ' . $sess . ' from POST data');
             } else {
                 send403();
                 die_with_error_log('This tool should be launched from a learning system using LTI');
             }
         }
     }
     // Start a session if it has not been started..
     if (session_id() == "") {
         session_start();
         // Should reassociate
     }
     // This happens from time to time when someone closes and reopens a laptop
     // Or their computer goes to sleep and wakes back up hours later.
     // So it is just a warning - nothing much we can do except tell them.
     if (!isset($_SESSION['lti'])) {
         // $debug = safe_var_dump($_SESSION);
         // error_log($debug);
         send403();
         error_log('Session expired - please re-launch ' . session_id());
         die('Session expired - please re-launch');
         // with error_log
     }
     // Check the referrer...
     $trusted = checkReferer() || checkCSRF();
     // Check to see if we switched browsers or IP addresses
     // TODO: Change these to warnings once we get more data
     if (!$trusted && isset($_SESSION['HTTP_USER_AGENT'])) {
         if (!isset($_SERVER['HTTP_USER_AGENT']) || $_SESSION['HTTP_USER_AGENT'] != $_SERVER['HTTP_USER_AGENT']) {
             send403();
             die_with_error_log("Session has expired", " " . session_id() . " HTTP_USER_AGENT " . $_SESSION['HTTP_USER_AGENT'] . ' ::: ' . isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'Empty user agent', 'DIE:');
         }
     }
     // We only check the first three octets as some systems wander throught the addresses on
     // class C - Perhaps it is even NAT - who knows - but we forgive those on the same Class C
     if (!$trusted && isset($_SESSION['REMOTE_ADDR']) && isset($_SERVER['REMOTE_ADDR'])) {
         $sess_pieces = explode('.', $_SESSION['REMOTE_ADDR']);
         $serv_pieces = explode('.', $_SERVER['REMOTE_ADDR']);
         if (count($sess_pieces) == 4 && count($serv_pieces) == 4) {
             if ($sess_pieces[0] != $serv_pieces[0] || $sess_pieces[1] != $serv_pieces[1] || $sess_pieces[2] != $serv_pieces[2]) {
                 send403();
                 die_with_error_log('Session address has expired', " " . session_id() . " REMOTE_ADDR " . $_SESSION['REMOTE_ADDR'] . ' ' . $_SERVER['REMOTE_ADDR'], 'DIE:');
             }
         }
     }
     // Check to see if the user has navigated to a new place in the hierarchy
     if (isset($_SESSION['script_path']) && getScriptPath() != 'core/blob' && strpos(getScriptPath(), $_SESSION['script_path']) !== 0) {
         send403();
         die_with_error_log('Improper navigation detected', " " . session_id() . " script_path " . $_SESSION['script_path'] . ' /  ' . getScriptPath(), 'DIE:');
     }
     $LTI = $_SESSION['lti'];
     if (is_array($needed)) {
         foreach ($needed as $feature) {
             if (isset($LTI[$feature])) {
                 continue;
             }
             die_with_error_log("This tool requires an LTI launch parameter:" . $feature);
         }
     }
     // Check to see if the session needs to be extended due to this request
     checkHeartBeat();
     // Restart the number of continuous heartbeats
     $_SESSION['HEARTBEAT_COUNT'] = 0;
     // Populate the $USER $CONTEXT and $LINK objects
     if (isset($LTI['user_id']) && !is_object($USER)) {
         $USER = new \Tsugi\Core\User();
         $USER->id = $LTI['user_id'];
         if (isset($LTI['user_email'])) {
             $USER->email = $LTI['user_email'];
         }
         if (isset($LTI['user_displayname'])) {
             $USER->displayname = $LTI['user_displayname'];
             $pieces = explode(' ', $USER->displayname);
             if (count($pieces) > 0) {
                 $USER->firstname = $pieces[0];
             }
             if (count($pieces) > 1) {
                 $USER->lastname = $pieces[count($pieces) - 1];
             }
         }
         $USER->instructor = isset($LTI['role']) && $LTI['role'] != 0;
     }
     if (isset($LTI['context_id']) && !is_object($CONTEXT)) {
         $CONTEXT = new \Tsugi\Core\Context();
         $CONTEXT->id = $LTI['context_id'];
         if (isset($LTI['context_title'])) {
             $CONTEXT->title = $LTI['context_title'];
         }
     }
     if (isset($LTI['link_id']) && !is_object($LINK)) {
         $LINK = new \Tsugi\Core\Link();
         $LINK->id = $LTI['link_id'];
         if (isset($LTI['grade'])) {
             $LINK->grade = $LTI['grade'];
         }
         if (isset($LTI['link_title'])) {
             $LINK->title = $LTI['link_title'];
         }
         if (isset($LTI['result_id'])) {
             $LINK->result_id = $LTI['result_id'];
         }
     }
     // Return the LTI structure
     return $LTI;
 }
Esempio n. 5
0
} else {
    ini_set('session.use_cookies', '0');
    ini_set('session.use_only_cookies', 0);
    ini_set('session.use_trans_sid', 1);
}
if (!isset($CFG)) {
    die_with_error_log("Please configure this product using config.php");
}
if (!isset($CFG->staticroot)) {
    die_with_error_log('$CFG->staticroot not defined in config.php');
}
if (!isset($CFG->timezone)) {
    die_with_error_log('$CFG->timezone not defined in config.php');
}
if (strpos($CFG->dbprefix, ' ') !== false) {
    die_with_error_log('$CFG->dbprefix cannot have spaces in it');
}
if (!isset($CFG->ownername)) {
    $CFG->ownername = false;
}
if (!isset($CFG->owneremail)) {
    $CFG->owneremail = false;
}
if (!isset($CFG->providekeys)) {
    $CFG->providekeys = false;
}
// Set this to the temporary folder if not set - dev only
if (!isset($CFG->dataroot)) {
    $tmp = sys_get_temp_dir();
    if (strlen($tmp) > 1 && substr($tmp, -1) == '/') {
        $tmp = substr($tmp, 0, -1);
Esempio n. 6
0
Most systems are configured to use the default MySQL port of 3306 and if you
omit "port=" in the PDO string it assumes 3306.  If you are using MAMP
this is usually moved to port 8889.  If neither 3306 nor 8889 works you
probably have a bad host name.  Or talk to your system administrator.
</p>
';
        } else {
            echo "<p>There is a problem with your database connection.</p>\n";
        }
    }
    echo "<p>Database error detail: " . $msg . "</p>\n";
    echo "<p>Once you have fixed the problem, come back to this page and refresh\nto see if this message goes away.</p>";
    echo '<p>Installation instructions are avaiable at <a href="http://www.tsugi.org/"
target="_blank">tsugi.org</a>';
    echo "\n</div>\n";
    die_with_error_log("Database error " . $msg);
}
// Now check the plugins table to see if it exists
$p = $CFG->dbprefix;
$plugins = "{$p}lms_plugins";
$table_fields = $PDOX->metadata($plugins);
if ($table_fields === false) {
    echo '<div class="alert alert-danger" style="margin: 10px;">' . "\n";
    echo "<p>It appears that your database connection is working properly\nbut you have no tables in your database.  To create the initial tables\nneeded for this application, use the 'Admin' feature.  You will be prompted\nfor the administrator master password as configured in <code>config.php</code>\nin the <code>\$CFG->adminpw</code> setting.\n</p>\n";
    echo "\n</div>\n";
    // Now check to see if a database upgrade might be necessary
} else {
    $row = $PDOX->rowDie("SELECT MAX(version) AS version FROM {$plugins}");
    $actualdbversion = $row['version'];
    if ($actualdbversion < $CFG->dbversion) {
        echo '<div class="alert alert-danger" style="margin: 10px;">' . "\n";
Esempio n. 7
0
define('COOKIE_SESSION', true);
require_once "config.php";
require_once "pdo.php";
require_once 'lib/lms_lib.php';
require_once 'lib/lightopenid/openid.php';
session_start();
error_log('Session in login.php ' . session_id());
// First we make sure that there is a google.com key
$stmt = $PDOX->queryDie("SELECT key_id FROM {$CFG->dbprefix}lti_key\n        WHERE key_sha256 = :SHA LIMIT 1", array('SHA' => lti_sha256('google.com')));
$key_row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($key_row === false) {
    die_with_error_log('Error: No key defined for accounts from google.com');
}
$google_key_id = $key_row['key_id'] + 0;
if ($google_key_id < 1) {
    die_with_error_log('Error: No key for accounts from google.com');
}
$errormsg = false;
$success = false;
$doLogin = false;
$identity = false;
$firstName = false;
$lastName = false;
$userEmail = false;
if ($CFG->DEVELOPER && $CFG->OFFLINE) {
    $identity = 'http://notgoogle.com/1234567';
    $firstName = 'Fake';
    $lastName = 'Person';
    $userEmail = '*****@*****.**';
    $doLogin = true;
} else {
Esempio n. 8
0
define('COOKIE_SESSION', true);
require_once "../config.php";
require_once "../pdo.php";
require_once $CFG->dirroot . '/lib/lms_lib.php';
require_once 'tp_messages.php';
use Tsugi\Util\LTI;
use Tsugi\Util\Net;
session_start();
header('Content-Type: text/html; charset=utf-8');
if (!isset($_SESSION['lti2post'])) {
    die_with_error_log("Missing LTI 2.0 post data");
}
error_log("Session in lti2 " . session_id());
if (!isset($_SESSION['id'])) {
    if (isset($_REQUEST['login_done'])) {
        die_with_error_log("LTI 2 login failed.");
    }
    $_SESSION['login_return'] = addSession(getCurrentFileUrl(__FILE__) . "?login_done=true");
    header("Location: " . getLoginUrl());
    return;
}
// See if this person is allowed to register a tool
$row = $PDOX->rowDie("SELECT request_id, user_id, admin, state, lti\n        FROM {$CFG->dbprefix}key_request\n        WHERE user_id = :UID LIMIT 1", array(":UID" => $_SESSION['id']));
if ($row === false) {
    $_SESSION['error'] = 'You have not requested a key for this service.';
    header('Location: ' . $CFG->wwwroot);
    return;
}
if ($row['state'] == 0) {
    $_SESSION['error'] = 'Your key has not yet been approved. ' . $row['admin'];
    header('Location: ' . $CFG->wwwroot);
Esempio n. 9
0
// Parse the response object and update the shared_secret if needed
$responseObject = json_decode($response);
if ($responseObject != null) {
    $tc_tool_proxy_guid = $responseObject->tool_proxy_guid;
    if ($tc_tool_proxy_guid) {
        $oauth_consumer_key = $tc_tool_proxy_guid;
        echo '<p>Tool consumer returned tool_proxy_guid=' . $tc_tool_proxy_guid . " (using as oauth_consumer_key)</p>\n";
        if ($tool_proxy_guid && $tool_proxy_guid != $tc_tool_proxy_guid) {
            echo '<p style="color: red;">Error: Returned tool_proxy_guid did not match launch oauth_consumer_key/tool_proxy_guid=' . $tool_proxy_guid . "</p>\n";
        }
    } else {
        echo '<p style="color: red;">Error: Tool Consumer did not include tool_proxy_guid in its response.</p>' . "\n";
    }
    if ($oauth_splitsecret && $shared_secret) {
        if (!isset($responseObject->tc_half_shared_secret)) {
            die_with_error_log("<p>Error: Tool Consumer did not provide tc_half_shared_secret</p>\n");
        } else {
            $tc_half_shared_secret = $responseObject->tc_half_shared_secret;
            $shared_secret = $tc_half_shared_secret . $shared_secret;
            echo "<p>Split Secret: " . $shared_secret . "</p>\n";
        }
    }
}
// A big issue here is that TCs choose the proxy guid, and we need for
// the proxy guids (i.e. oauth_consumer_key) to be unique.  So we mark
// these with user_id and do not let a second TC slip in and take over
// an existing key.   So the next few lines of code are really critical.
// And we can neither use INSERT / UPDATE because we cannot add the user_id
// to the unique constraint.
if ($re_register) {
    $retval = $PDOX->queryDie("UPDATE {$CFG->dbprefix}lti_key SET updated_at = NOW(), ack = :ACK,\n            new_secret = :SECRET, new_consumer_profile = :PROFILE\n            WHERE key_sha256 = :SHA and user_id = :UID", array(":SECRET" => $shared_secret, ":PROFILE" => $tc_profile_json, ":UID" => $_SESSION['id'], ":SHA" => $key_sha256, ":ACK" => $ack));
Esempio n. 10
0
<?php

if (!isset($CFG)) {
    die_with_error_log('This software is not correctly configured, please copy config-dist.php to
    config.php and edit config.php according to the installation instructions.');
}
if (!defined('PHP_VERSION_ID')) {
    $version = explode('.', PHP_VERSION);
    define('PHP_VERSION_ID', $version[0] * 10000 + $version[1] * 100 + $version[2]);
}
if (PHP_VERSION_ID < 50300) {
    die_with_error_log("This software requires PHP 5.3.0 or later");
}
if (strpos(__FILE__, ' ') !== false) {
    die_with_error_log("This software requires that folder and file names have no spaces " . __FILE__);
}
Esempio n. 11
0
 /**
  * We are aborting this request.  If this is a launch, redirect back
  */
 private static function abort_with_error_log($msg, $extra = false, $prefix = "DIE:")
 {
     $return_url = isset($_POST['launch_presentation_return_url']) ? $_POST['launch_presentation_return_url'] : null;
     if ($return_url === null) {
         die_with_error_log($msg, $extra, $prefix);
     }
     $return_url .= strpos($return_url, '?') > 0 ? '&' : '?';
     $return_url .= 'lti_errormsg=' . urlencode($msg);
     if ($extra !== false) {
         $return_url .= '&detail=' . urlencode($extra);
     }
     header("Location: " . $return_url);
     error_log($prefix . ' ' . $msg . ' ' . $extra);
     exit;
 }
Esempio n. 12
0
    function bodyStart($checkpost = true)
    {
        // If we are in an iframe use different margins
        ?>
</head>
<body>
<script>
if (window!=window.top) {
    document.write('<div class="container_iframe">');
} else {
    document.write('<div class="container">');
}
</script>
<?php 
        if ($checkpost && count($_POST) > 0) {
            $dump = self::safe_var_dump($_POST);
            echo '<p style="color:red">Error - Unhandled POST request</p>';
            echo "\n<pre>\n";
            echo $dump;
            echo "\n</pre>\n";
            error_log($dump);
            die_with_error_log("Unhandled POST request");
        }
    }