$end) { header("HTTP/1.1 400 Bad Request"); echo "Start value is after end value"; exit(); } if ($end - $start > 60 * 60 * 24 * 90) { header("HTTP/1.1 400 Bad Request"); echo "Maximum range is 90 days"; exit(); } if ($maxItems > 100) { header("HTTP/1.1 400 Bad Request"); echo "Maximum number of items is 100"; exit(); } header("X-Debug-used-url: $url"); header("X-Debug-start: $start (" . date("Y-m-d", $start) . ")"); header("X-Debug-end: $end (" . date("Y-m-d", $end) . ")"); header("X-Debug-max-items: $maxItems"); require_once __DIR__ . "/../vendor/autoload.php"; if (!is_dir(CACHE_DIR)) { mkdir(CACHE_DIR, 0777, true); } $urlCacheFile = CACHE_DIR . "/url_" . md5($url); header( "X-Debug-Cache-File-data: " . json_encode([$url, $start, $end, $maxItems], JSON_UNESCAPED_SLASHES) ); if ( file_exists($completeCacheFile) && filemtime($completeCacheFile) > time() - CACHE_TTL ) { header("Content-Type: application/json"); header("X-Debug-Cache-Hit: complete"); readfile($completeCacheFile); //use fast response time to allow cache cleaning for 500ms $cacheCleanEnd = microtime(true) + 0.5; $cacheFiles = glob(CACHE_DIR . "/*"); do { $cacheFile = array_shift($cacheFiles); if (filemtime($cacheFile) < time() - CACHE_TTL) { unlink($cacheFile); } } while (microtime(true) <= $cacheCleanEnd && count($cacheFiles) > 0); exit(); } if ( !file_exists($urlCacheFile) || filemtime($urlCacheFile) < time() - CACHE_TTL ) { $dlStart = microtime(true); $size = 0; $fp_in = fopen($url, "r"); $fp_out = fopen($urlCacheFile, "w"); while ($fp_in && !feof($fp_in)) { $size += fwrite($fp_out, fread($fp_in, 1024 * 1024)); if ($size > MAX_FILE_SIZE) { header("HTTP/1.1 400 Bad Request"); echo "File is too big"; fclose($fp_in); fclose($fp_out); unlink($urlCacheFile); exit(); } } fclose($fp_in); fclose($fp_out); $dlEnd = microtime(true); $dlTime = round($dlEnd - $dlStart, 3); header("X-Debug-Download-Time: $dlTime s"); $prefixes = ["B", "KB", "MB", "GB", "TB", "PB"]; $prefix = array_shift($prefixes); while ($size > 1500) { $prefix = array_shift($prefixes); $size = $size / 1024; } $hsize = round($size, 3) . " " . $prefix; header("X-Debug-Download-Size: $hsize"); } else { header("X-Debug-Cache-Hit: url"); } $errors = false; try { $parseStart = microtime(true); $ical = new ICal($urlCacheFile, [ "defaultTimeZone" => "UTC", ]); $events = $ical->eventsFromRange( date("Y-m-d", strtotime("today")), date("Y-m-d", strtotime("today + 90 days")) ); $parseEnd = microtime(true); $parseTime = round($parseEnd - $parseStart, 3); header("X-Debug-Parse-Time: $parseTime s"); while (count($events) > $maxItems) { array_pop($events); } $events = array_map(function (Event $event) { $r = []; @$r["summary"] = $event->summary; @$r["description"] = $event->description; @$r["location"] = $event->location; @$r["start"] = $event->dtstart_array[2]; @$r["end"] = $event->dtend_array[2]; @$r["duration"] = $event->duration; @$r["url"] = $event->url; @$r["status"] = $event->status; return $r; }, $events); usort($events, function ($a, $b) { return $a["start"] - $b["start"]; }); } catch (\Exception $e) { header("HTTP/1.1 500 Internal Server Error"); echo "Error parsing ical file"; exit(); } $data = json_encode( $events, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT ); file_put_contents($completeCacheFile, $data); header("Content-Type: application/json"); echo $data; foreach (glob(CACHE_DIR . "/*") as $file) { if (filemtime($file) < time() - CACHE_TTL) { unlink($file); } }