Files
hustoj/web/include/courseware.inc.php
T

226 lines
6.9 KiB
PHP

<?php
/**
* File-based courseware: one .pptx file per lesson in the repo-root courseware/ directory.
*/
if (!function_exists('courseware_root')) {
function courseware_root() {
if (isset($GLOBALS['_courseware_root']) && $GLOBALS['_courseware_root'] !== '') {
$resolved = realpath($GLOBALS['_courseware_root']);
return $resolved === false ? '' : $resolved;
}
$resolved = realpath(__DIR__ . '/../../courseware');
return $resolved === false ? '' : $resolved;
}
}
if (!function_exists('courseware_is_slug')) {
function courseware_is_slug($slug) {
if (!is_string($slug) || $slug === '' || $slug === '.' || $slug === '..') {
return false;
}
if (strpos($slug, "\0") !== false) {
return false;
}
if (strpos($slug, '/') !== false || strpos($slug, '\\') !== false) {
return false;
}
return true;
}
}
if (!function_exists('courseware_is_pptx_name')) {
function courseware_is_pptx_name($name) {
if (!is_string($name) || strlen($name) < 6) {
return false;
}
if (strpos($name, "\0") !== false || strpos($name, '/') !== false || strpos($name, '\\') !== false) {
return false;
}
return strtolower(substr($name, -5)) === '.pptx';
}
}
if (!function_exists('courseware_inside_root')) {
function courseware_inside_root($path, $root) {
$root_norm = rtrim(str_replace('\\', '/', $root), '/');
$path_norm = rtrim(str_replace('\\', '/', $path), '/');
if ($root_norm === '' || $path_norm === '') {
return false;
}
$insensitive = (DIRECTORY_SEPARATOR === '\\');
if ($insensitive) {
if (strcasecmp($path_norm, $root_norm) === 0) {
return true;
}
$prefix = $root_norm . '/';
return strncasecmp($path_norm, $prefix, strlen($prefix)) === 0;
}
return $path_norm === $root_norm || strpos($path_norm, $root_norm . '/') === 0;
}
}
if (!function_exists('courseware_is_absolute_path')) {
function courseware_is_absolute_path($path) {
if (!is_string($path) || $path === '') {
return false;
}
if ($path[0] === '/' || $path[0] === '\\') {
return true;
}
return (bool) preg_match('#^[A-Za-z]:[\\\\/]#', $path);
}
}
if (!function_exists('courseware_scan_pptx_entries')) {
function courseware_scan_pptx_entries() {
$root = courseware_root();
$found = array();
if ($root === '' || !is_dir($root)) {
return $found;
}
$entries = @scandir($root);
if ($entries === false) {
return $found;
}
foreach ($entries as $name) {
if ($name === '.' || $name === '..') {
continue;
}
if (!courseware_is_pptx_name($name)) {
continue;
}
$slug = substr($name, 0, -5);
if (!courseware_is_slug($slug)) {
continue;
}
if (!isset($found[$slug])) {
$found[$slug] = $name;
}
}
return $found;
}
}
if (!function_exists('courseware_link_stays_inside')) {
function courseware_link_stays_inside($raw, $root) {
if (!is_link($raw)) {
return true;
}
$link = @readlink($raw);
if ($link === false || strpos($link, "\0") !== false) {
return false;
}
$target = courseware_is_absolute_path($link)
? $link
: (dirname($raw) . DIRECTORY_SEPARATOR . $link);
$resolved_link = realpath($target);
if ($resolved_link === false || !courseware_inside_root($resolved_link, $root)) {
return false;
}
return true;
}
}
if (!function_exists('courseware_resolve_pptx')) {
function courseware_resolve_pptx($slug) {
if (!courseware_is_slug($slug)) {
return null;
}
$root = courseware_root();
if ($root === '') {
return null;
}
$entries = courseware_scan_pptx_entries();
if (!isset($entries[$slug])) {
return null;
}
$name = $entries[$slug];
$raw = $root . DIRECTORY_SEPARATOR . $name;
if (!courseware_link_stays_inside($raw, $root)) {
return null;
}
$resolved = realpath($raw);
if ($resolved === false || !is_file($resolved)) {
return null;
}
if (!courseware_inside_root($resolved, $root)) {
return null;
}
if (!courseware_is_pptx_name(basename($resolved)) && !courseware_is_pptx_name($name)) {
return null;
}
return array(
'slug' => $slug,
'title' => $slug,
'filename' => $name,
'path' => $resolved,
);
}
}
if (!function_exists('courseware_build_deck')) {
function courseware_build_deck($slug) {
$found = courseware_resolve_pptx($slug);
if ($found === null) {
return null;
}
return array(
'slug' => $found['slug'],
'title' => $found['title'],
'filename' => $found['filename'],
'url' => 'courseware-file.php?deck=' . rawurlencode($found['slug']),
);
}
}
if (!function_exists('courseware_list_decks')) {
function courseware_list_decks() {
$decks = array();
$seen = array();
foreach (courseware_scan_pptx_entries() as $slug => $name) {
unset($name);
if (isset($seen[$slug])) {
continue;
}
$deck = courseware_build_deck($slug);
if ($deck !== null) {
$seen[$slug] = true;
$decks[] = $deck;
}
}
usort($decks, function ($a, $b) {
return strnatcasecmp($a['title'], $b['title']);
});
return $decks;
}
}
if (!function_exists('courseware_clamp_page')) {
function courseware_clamp_page($deck, $page) {
$page = intval($page);
if ($page < 1) {
return 1;
}
$count = (is_array($deck) && isset($deck['page_count'])) ? intval($deck['page_count']) : 0;
if ($count < 1) {
return $page;
}
if ($page > $count) {
return $count;
}
return $page;
}
}
if (!function_exists('courseware_content_disposition')) {
function courseware_content_disposition($filename) {
$safe = str_replace(array("\r", "\n", '"', '\\'), '_', strval($filename));
$ascii = preg_replace('/[^\x20-\x7E]/', '_', $safe);
if ($ascii === '' || $ascii === '_' || $ascii === '.pptx') {
$ascii = 'courseware.pptx';
}
return 'inline; filename="' . $ascii . '"; filename*=UTF-8\'\'' . rawurlencode($filename);
}
}