static function render($agent, $liveAgent) { $config_maxage = $CONFIG['maxage']; // Get the calling URI if (isset($_COOKIE['R$'])) { p::$uri = $_COOKIE['R$']; setcookie('R$', '', 1, '/'); // Check the Referer header // T$ starts with 2 when the Referer's confidence is unknown // 1 when it is trusted if (isset($_SERVER['HTTP_REFERER']) && $_COOKIE['R$'] === $_SERVER['HTTP_REFERER']) { if (class_exists('SESSION', false)) { $_COOKIE['T$'] = '1'; s::regenerateId(); } else { self::$antiCsrfToken[0] = '1'; setcookie('T$', self::$antiCsrfToken, 0, $CONFIG['session.cookie_path'], $CONFIG['session.cookie_domain']); } } } else { p::$uri = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : p::$base; } if ($liveAgent) { // The output is both html and js, but iframe transport layer needs html p::$binaryMode = true; header('Content-Type: text/html'); echo '/*<script>/**/q="'; } else { echo 'w('; } p::openMeta($agent); try { if (isset($_GET['T$']) && !p::$antiCsrfMatch) { throw new e\PrivateResource(); } $a = new $agent($_GET); $group = p::closeGroupStage(); if ($is_cacheable = 'POST' !== $_SERVER['REQUEST_METHOD'] && !in_array('private', $group)) { $cagent = p::agentCache($agent, $a->get, 'js.ser', $group); $dagent = p::getContextualCachePath('jsdata.' . $agent, 'js.ser', $cagent); if ($liveAgent) { if (file_exists($dagent)) { if (filemtime($dagent) > $_SERVER['REQUEST_TIME']) { $data = unserialize(file_get_contents($dagent)); p::setMaxage($data['maxage']); p::setExpires($data['expires']); p::writeWatchTable($data['watch']); array_map('header', $data['headers']); p::closeMeta(); echo str_replace(array('\\', '"', '</'), array('\\\\', '\\"', '<\\/'), $data['rawdata']), '"//</script><script src="' . p::__BASE__() . 'js/QJsrsHandler"></script>'; return; } else { @(unlink($cagent) + unlink($dagent)); } } } else { if (file_exists($cagent)) { if (filemtime($cagent) > $_SERVER['REQUEST_TIME']) { $data = unserialize(file_get_contents($cagent)); p::setMaxage($data['maxage']); p::setExpires($data['expires']); p::writeWatchTable($data['watch']); array_map('header', $data['headers']); p::closeMeta(); echo $data['rawdata']; return; } else { @(unlink($cagent) + unlink($dagent)); } } } } ob_start(); ++p::$ob_level; try { $data = (object) $a->compose((object) array()); if (!p::$is_enabled) { p::closeMeta(); return; } $template = $a->getTemplate(); echo '{'; $comma = ''; foreach ($data as $key => $value) { $key = jsquote($key); is_string($key) || ($key = "'" . $key . "'"); echo $comma, $key, ':'; if ($value instanceof \loop) { self::writeAgent($value); } else { echo jsquote($value); } $comma = ','; } echo '}'; } catch (e\PrivateResource $data) { ob_end_clean(); --p::$ob_level; p::closeMeta(); throw $data; } $data = ob_get_clean(); --p::$ob_level; $a->metaCompose(); list($maxage, $group, $expires, $watch, $headers) = p::closeMeta(); } catch (e\PrivateResource $data) { if ($liveAgent) { echo 'false";(window.E||alert)("You must provide an auth token to get this liveAgent:\\n"+', jsquote($_SERVER['REQUEST_URI']), ')'; echo '//</script><script src="' . p::__BASE__() . 'js/QJsrsHandler"></script>'; } else { if ($data->getMessage()) { echo 'w.r(0,' . (int) (!DEBUG) . '));'; } else { echo ');window.E&&E("You must provide an auth token to get this agent:\\n"+', jsquote($_SERVER['REQUEST_URI']), ')'; } } exit; } if ($liveAgent) { echo str_replace(array('\\', '"', '</'), array('\\\\', '\\"', '<\\/'), $data), '"//</script><script src="' . p::__BASE__() . 'js/QJsrsHandler"></script>'; } else { echo $data; } if ('ontouch' === $expires && !($watch || $config_maxage == $maxage)) { $expires = 'auto'; } $expires = 'auto' === $expires && ($watch || $config_maxage == $maxage) ? 'ontouch' : 'onmaxage'; $is_cacheable = $is_cacheable && !in_array('private', $group) && ($maxage || 'ontouch' === $expires); if (!$liveAgent || $is_cacheable) { if ($is_cacheable) { ob_start(); } if ($config_maxage == $maxage && Superloader::$turbo) { $ctemplate = p::getContextualCachePath("templates/{$template}", 'txt'); $readHandle = true; if ($h = p::fopenX($ctemplate, $readHandle)) { p::openMeta('agent__template/' . $template, false); $template = new \ptlCompiler_js($template); echo $template = ',' . $template->compile() . ')'; fwrite($h, $template); flock($h, LOCK_UN); fclose($h); list(, , , $template) = p::closeMeta(); p::writeWatchTable($template, $ctemplate); } else { fpassthru($readHandle); flock($readHandle, LOCK_UN); fclose($readHandle); } $watch[] = 'public/templates/js'; } else { echo ',[1,', jsquote($template), ',0,0,0])'; } if ($is_cacheable) { $ob = true; $template = array('maxage' => $maxage, 'expires' => $expires, 'watch' => $watch, 'headers' => $headers, 'rawdata' => $data); $expires = 'ontouch' === $expires ? $config_maxage : $maxage; if ($h = p::fopenX($dagent)) { fwrite($h, serialize($template)); flock($h, LOCK_UN); fclose($h); touch($dagent, $_SERVER['REQUEST_TIME'] + $expires); p::writeWatchTable($watch, $dagent); } if ($h = p::fopenX($cagent)) { $ob = false; $template['rawdata'] .= $liveAgent ? ob_get_clean() : ob_get_flush(); fwrite($h, serialize($template)); flock($h, LOCK_UN); fclose($h); touch($cagent, $_SERVER['REQUEST_TIME'] + $expires); p::writeWatchTable($watch, $cagent); } if ($ob) { $liveAgent ? ob_end_clean() : ob_end_flush(); } } } }
static function readfile($file, $mime = true, $filename = true) { $h = patchworkPath($file); if (!$h || !file_exists($h) || is_dir($h)) { user_error(__METHOD__ . "(..): invalid file ({$file})"); return; } $file = $h; if (true === $mime) { $mime = strtolower(strrchr($file, '.')); $mime = isset(self::$contentType[$mime]) ? self::$contentType[$mime] : false; } $mime || ($mime = isset(p::$headers['content-type']) ? substr(p::$headers['content-type'], 14) : 'application/octet-stream'); $mime = strtolower($mime); $head = 'HEAD' == $_SERVER['REQUEST_METHOD']; $gzip = p::gzipAllowed($mime); $filter = $gzip || $head || !$CONFIG['xsendfile'] || in_array($mime, self::$ieSniffedTypes_edit) || in_array($mime, p::$ieSniffedTypes_download); header('Content-Type: ' . $mime); if ($filename) { $filename = basename(true === $filename ? $_SERVER['PATCHWORK_REQUEST'] : $filename); $size = false; if (!$filter) { // Force IE>=8 to respect attachment content disposition header('X-Download-Options: noopen'); } // It seems that IE assumes that filename is represented in its local system charset... // But we don't want to introduce "Vary: User-Agent" just because of this. if (('POST' === $_SERVER['REQUEST_METHOD'] || p::$private) && isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') && !strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') && preg_match('/[\\x80-\\xFF]/', $filename)) { if (stripos(p::$headers['content-type'], 'octet-stream') && preg_match('#(.*)(\\.[- -,/-~]+)$#D', $filename, $size)) { // Don't search any rational here, it's IE... header('Content-Disposition: attachment; filename=' . rawurlencode($size[1]) . str_replace('"', "''", $size[2])); } else { $filename = Patchwork\Utf8::toAscii($filename); } } $size || header('Content-Disposition: attachment; filename="' . str_replace('"', "''", $filename) . '"'); // If only RFC 2231 were in use... See http://greenbytes.de/tech/tc2231/ //header('Content-Disposition: attachment; filename*=utf-8''" . rawurlencode($filename)); } else { if (false !== strpos($mime, 'html')) { header('P3P: CP="' . $CONFIG['P3P'] . '"'); header('X-XSS-Protection: 1; mode=block'); } } $size = filesize($file); p::$ETag = $size . '-' . p::$LastModified . '-' . fileinode($file); p::$LastModified = filemtime($file); p::$binaryMode = true; p::disable(); class_exists('SESSION', false) && s::close(); class_exists('adapter_DB', false) && \adapter_DB::__free(); $gzip || ob_start(); $filter && ob_start(array(__CLASS__, 'ob_filterOutput'), 32768); // Transform relative URLs to absolute ones if ($gzip) { if (0 === strncasecmp($mime, 'text/css', 8)) { self::$filterRx = "@([\\s:]url\\(\\s*[\"']?)(?![/\\\\#\"']|[^\\)\n\r:/\"']+?:)@i"; ob_start(array(__CLASS__, 'filter'), 32768); } else { if (0 === strncasecmp($mime, 'text/html', 9) || 0 === strncasecmp($mime, 'text/x-component', 16)) { self::$filterRx = "@(<[^<>]+?\\s(?:href|src)\\s*=\\s*[\"']?)(?![/\\\\#\"']|[^\n\r:/\"']+?:)@i"; ob_start(array(__CLASS__, 'filter'), 32768); } } } if ($filter) { $h = fopen($file, 'rb'); echo $starting_data = fread($h, 256); // For p::ob_filterOutput to fix IE if ($gzip) { if ($head) { ob_end_clean(); } $data = ''; $starting_data = false; } else { ob_end_flush(); $data = ob_get_clean(); $size += strlen($data) - strlen($starting_data); $starting_data = $data == $starting_data; } } else { $starting_data = true; } if (!$head) { if ($starting_data && $CONFIG['xsendfile']) { header(sprintf($CONFIG['xsendfile'], $file)); } else { if ($range = $starting_data && !$gzip) { header('Accept-Ranges: bytes'); $range = isset($_SERVER['HTTP_RANGE']) ? p\HttpRange::negociate($size, p::$ETag, p::$LastModified) : false; } else { header('Accept-Ranges: none'); } set_time_limit(0); ignore_user_abort(false); if ($range) { unset(p::$headers['content-type']); p\HttpRange::sendChunks($range, $h, $mime, $size); } else { $gzip || header('Content-Length: ' . $size); echo $data; feof($h) || fpassthru($h); } } } $filter && fclose($h); }