diff options
Diffstat (limited to 'modules-available/dozmod/api.inc.php')
| -rw-r--r-- | modules-available/dozmod/api.inc.php | 250 |
1 files changed, 150 insertions, 100 deletions
diff --git a/modules-available/dozmod/api.inc.php b/modules-available/dozmod/api.inc.php index b37c668c..17ead3c1 100644 --- a/modules-available/dozmod/api.inc.php +++ b/modules-available/dozmod/api.inc.php @@ -5,70 +5,69 @@ * * Required Configuration: * CONFIG_DOZMOD_EXPIRE: Expiration time in seconds for the cache -* CONFIG_DOZMOD: URL to the dozmod server +* CONFIG_DOZMOD_URL: URL to the dozmod server * **/ if (!Module::isAvailable('locations')) { - die('require locations module'); + die('require locations module'); } -define('LIST_URL', CONFIG_DOZMOD . '/vmchooser/list'); -define('VMX_URL', CONFIG_DOZMOD . '/vmchooser/lecture'); -$availableRessources = ['vmx', 'test', 'netrules']; +define('LIST_URL', CONFIG_DOZMOD_URL . '/vmchooser/list'); +define('VMX_URL', CONFIG_DOZMOD_URL . '/vmchooser/lecture'); +$availableRessources = ['list', 'vmx', 'test', 'netrules']; /* BEGIN: A simple caching mechanism ---------------------------- */ function cache_hash($obj) { - return md5(serialize($obj)); + return md5(serialize($obj)); } function cache_key_to_filename($key) { - return "/tmp/bwlp-slxadmin-cache-$key"; // TODO: hash + return "/tmp/bwlp-slxadmin-cache-$key"; } function cache_put($key, $value) { - $filename = cache_key_to_filename($key); - file_put_contents($filename, $value); + $filename = cache_key_to_filename($key); + file_put_contents($filename, $value); } function cache_has($key) { - $filename = cache_key_to_filename($key); - $mtime = filemtime($filename); + $filename = cache_key_to_filename($key); + $mtime = @filemtime($filename); - if (!$mtime) { - return false; // cache miss - } - if (time() - $mtime > CONFIG_DOZMOD_EXPIRE) { - return false; - } else { - return true; - } + if ($mtime === false) { + return false; // cache miss + } + if (time() - $mtime > CONFIG_DOZMOD_EXPIRE) { + return false; + } else { + return true; + } } - function cache_get($key) { - $filename = cache_key_to_filename($key); - return file_get_contents($filename); + $filename = cache_key_to_filename($key); + return file_get_contents($filename); } /* good for large binary files */ function cache_get_passthru($key) { - $filename = cache_key_to_filename($key); - $fp = fopen($filename, "r"); - if ($fp) { - fpassthru($fp); - } else { - Util::traceError("cannot open file"); - } + $filename = cache_key_to_filename($key); + $fp = fopen($filename, "r"); + if ($fp) { + fpassthru($fp); + exit; + } + error_log('Cannot passthrough cache file ' . $filename); } /* END: Cache ---------------------------------------------------- */ @@ -81,106 +80,157 @@ function cache_get_passthru($key) **/ -function println($str) { echo "$str\n"; } - -/* return an array of lecutre uuids. -* Parameter: an array with location Ids -* */ -function _getLecturesForLocations($locationIds) +/** + * Takes raw lecture list xml, returns array of uuids. + * + * @param string $responseXML XML from dozmod server + * @return array list of UUIDs, false on error + */ +function xmlToLectureIds($responseXML) { + $xml = new SimpleXMLElement($responseXML); + if (!isset($xml->eintrag)) + return []; - /* if in any of the locations there is an exam active, consider the client - to be in "exam-mode" and only offer him exams (no lectures) */ - $examMode = false; - - if (Module::isAvailable('exams')) { - $examMode = Exams::isInExamMode($locationIds); - } - $ids = implode('%20', $locationIds); - $url = LIST_URL . "?locations=$ids" . ($examMode ? '&exams' : ''); - $responseXML = Download::asString($url, 60, $code); - $xml = new SimpleXMLElement($responseXML); - - $uuids = []; - foreach ($xml->eintrag as $e) { - $uuids[] = strval($e->uuid['param'][0]); - } - return $uuids; + $uuids = []; + foreach ($xml->eintrag as $e) { + $uuids[] = strval($e->uuid['param'][0]); + } + return $uuids; } /** Caching wrapper around _getLecturesForLocations() */ -function getLecturesForLocations($locationIds) +function getListForLocations($locationIds, $raw) +{ + /* if in any of the locations there is an exam active, consider the client + to be in "exam-mode" and only offer him exams (no lectures) */ + $key = 'lectures_' . cache_hash($locationIds); + $examMode = false; + if (Module::isAvailable('exams')) { + $examMode = Exams::isInExamMode($locationIds); + if ($examMode) { + $key .= '_exams'; + } + } + $rawKey = $key . '_raw'; + if ($raw) { + Header('Content-Type: text/xml; charset=utf-8'); + if (cache_has($rawKey)) { + cache_get_passthru($rawKey); + } + } elseif (cache_has($key)) { + return unserialize(cache_get($key)); + } + // Not in cache + $url = LIST_URL . "?locations=" . implode('%20', $locationIds); + if ($examMode) { + $url .= '&exams'; + } + $value = Download::asString($url, 60, $code); + if ($value === false) + return false; + cache_put($rawKey, $value); + $list = xmlToLectureIds($value); + cache_put($key, serialize($list)); + if ($raw) { + die($value); + } + return $list; +} + +function getLectureUuidsForLocations($locationIds) +{ + return getListForLocations($locationIds, false); +} + +function outputLectureXmlForLocation($locationIds) { - $key = 'lectures_' . cache_hash($locationIds); - if (cache_has($key)) { - return unserialize(cache_get($key)); - } else { - $value = _getLecturesForLocations($locationIds); - cache_put($key, serialize($value)); - return $value; - } + return getListForLocations($locationIds, true); } function _getVMX($lecture_uuid) { - $url = VMX_URL . '/' . $lecture_uuid; - $response = Download::asString($url, 60, $code); - return $response; + $url = VMX_URL . '/' . $lecture_uuid; + $response = Download::asString($url, 60, $code); + return $response; } /** Caching wrapper around _getVMX() **/ -function getVMX($lecture_uuid) +function outputVMX($lecture_uuid) +{ + $key = 'vmx_' . $lecture_uuid; + if (cache_has($key)) { + cache_get_passthru($key); + } else { + $value = _getVMX($lecture_uuid); + if ($value === false) + return false; + cache_put($key, $value); + die($value); + } +} + +function fatalDozmodUnreachable() { - $key = 'vmx_' . $lecture_uuid; - if (cache_has($key)) { - cache_get_passthru($key); - } else { - $value = _getVMX($lecture_uuid); - cache_put($key, $value); - return $value; - } + Header('HTTP/1.1 504 Gateway Timeout'); + die('Resource not available'); } - -// -----------------------------------------------------------------------------// -$ip = $_SERVER['REMOTE_ADDR']; -if (substr($ip, 0, 7) === '::ffff:') { - $ip = substr($ip, 7); +function readLectureParam() +{ + global $location_ids; + $lecture = Request::get('lecture', false, 'string'); + if ($lecture === false) { + Header('HTTP/1.1 400 Bad Request'); + die('Missing lecture UUID'); + } + $lectures = getLectureUuidsForLocations($location_ids); + if ($lectures === false) { + fatalDozmodUnreachable(); + } + /* check that the user requests a lecture that he is allowed to have */ + if (!in_array($lecture, $lectures)) { + Header('HTTP/1.1 403 Forbidden'); + die("You don't have permission to access this lecture"); + } + return $lecture; } + +// -----------------------------------------------------------------------------// /* request data, don't trust */ -$resource = Request::get('resource', false, 'string'); -$lecture = Request::get('lecture', false, 'string'); +$resource = Request::get('resource', false, 'string'); if ($resource === false) { - Util::traceError("you have to specify the 'resource' parameter"); + Util::traceError("you have to specify the 'resource' parameter"); } -if ($lecture === false) { - Util::traceError("you have to specify the 'lecture' parameter"); + +if (!in_array($resource, $availableRessources)) { + Util::traceError("unknown resource: $resource"); +} + +$ip = $_SERVER['REMOTE_ADDR']; +if (substr($ip, 0, 7) === '::ffff:') { + $ip = substr($ip, 7); } + /* lookup location id(s) */ $location_ids = Location::getFromIp($ip); $location_ids = Location::getLocationRootChain($location_ids); -/* lookup lecture uuids */ -$lectures = getLecturesForLocations($location_ids); - -/* validate request -------------------------------------------- */ -/* check resources */ -if (!in_array($resource, $availableRessources)) { - Util::traceError("unknown resource: $resource"); +if ($resource === 'vmx') { + $lecture = readLectureParam(); + outputVMX($lecture); + // outputVMX does not return on success + fatalDozmodUnreachable(); } -/* check that the user requests a lecture that he is allowed to have */ -if (!in_array($lecture, $lectures)) { - Util::traceError("client is not allowed to access this lecture: $lecture"); +if ($resource === 'list') { + outputLectureXmlForLocation($location_ids); + // Won't return on success... + fatalDozmodUnreachable(); } -if ($resource === 'vmx') { - echo getVMX($lecture); -} else if ($resource === 'test') { - echo "Here's your special test data!"; -} else { - echo "I don't know how to give you that resource"; -} +Header('HTTP/1.1 400 Bad Request'); +die("I don't know how to give you that resource"); |
