/** * Sends the desired HTTP response header in case of a "404". */ function skin_404_header() { global $Blog; // We have a 404 unresolved content error // How do we want do deal with it? switch ($resp_code = $Blog->get_setting('404_response')) { case '404': header_http_response('404 Not Found'); break; case '410': header_http_response('410 Gone'); break; case '301': case '302': case '303': // Redirect to home page: header_redirect($Blog->get('url'), intval($resp_code)); // THIS WILL EXIT! break; default: // Will result in a 200 OK } }
$current_User->check_perm('comment!' . $status, 'moderate', true, $edited_Comment); $redirect_to = param('redirect_to', 'url', NULL); $edited_Comment->set('status', $status); // Comment moderation is done, handle moderation "secret" $edited_Comment->handle_qm_secret(); $result_success = $edited_Comment->dbupdate(); if ($result_success !== false) { if ($status == 'published') { $edited_Comment->handle_notifications(false, $current_User->ID); } } } } if ($result_success === false) { // Some errors on deleting of the comment, Exit here header_http_response('500 ' . T_('Comment cannot be updated!'), 500); exit(0); } if ($moderation != NULL && in_array($request_from, array('items', 'comments'))) { // AJAX request goes from backoffice and ctrl = items or comments if (param('is_backoffice', 'integer', 0)) { // Set admin skin, used for buttons, @see button_class() global $current_User, $UserSettings, $is_admin_page, $adminskins_path; $admin_skin = $UserSettings->get('admin_skin', $current_User->ID); $is_admin_page = true; require_once $adminskins_path . $admin_skin . '/_adminUI.class.php'; $AdminUI = new AdminUI(); } $statuses = param('statuses', 'string', NULL); $item_ID = param('itemid', 'integer'); $currentpage = param('currentpage', 'integer', 1);
/** * Outputs Bad request Error message. When in debug mode it also prints a backtrace. * * This should be used when a bad user input is detected. * * @param string Message to output (HTML) */ function bad_request_die($additional_info = '') { global $debug, $baseurl; // Attempt to output an error header (will not work if the output buffer has already flushed once): // This should help preventing indexing robots from indexing the error :P if (!headers_sent()) { load_funcs('_core/_template.funcs.php'); headers_content_mightcache('text/html', 0); // Do NOT cache error messages! (Users would not see they fixed them) header_http_response('400 Bad Request'); } echo '<div style="background-color: #fdd; padding: 1ex; margin-bottom: 1ex;">'; echo '<h3 style="color:#f00;">' . T_('Bad Request!') . '</h3>'; echo '<p>' . T_('The parameters of your request are invalid.') . '</p>'; echo '<p>' . T_('If you have obtained this error by clicking on a link INSIDE of this site, please report the bad link to the administrator.') . '</p>'; echo '<p><a href="' . $baseurl . '">' . T_('Go back to home page') . '</a></p>'; echo '</div>'; if (!empty($additional_info)) { echo '<div style="background-color: #ddd; padding: 1ex; margin-bottom: 1ex;">'; if ($debug) { // Display additional info only in debug mode because it can reveal system info to hackers and greatly facilitate exploits echo '<h3>' . T_('Additional information about this error:') . '</h3>'; echo $additional_info; } else { echo '<p><i>Enable debugging to get additional information about this error.</i></p>' . get_manual_link('debugging', 'How to enable debug mode?'); } echo '</div>'; // Append the error text to AJAX log if it is AJAX request global $Ajaxlog; if (!empty($Ajaxlog)) { $Ajaxlog->add($additional_info, 'error'); $Ajaxlog->display(NULL, NULL, true, 'all', array('error' => array('class' => 'jslog_error', 'divClass' => false), 'note' => array('class' => 'jslog_note', 'divClass' => false)), 'ul', 'jslog'); } } if ($debug) { echo debug_get_backtrace(); } // Attempt to keep the html valid (but it doesn't really matter anyway) echo '</body></html>'; die(2); // Error code 2. Note: this will still call the shutdown function. }
$Item->set_from_Request('priority', 'new_priority', true); $Item->dbupdate(); break; case 'assigned': // Update task assigned user $new_assigned_ID = param('new_assigned_ID', 'integer', NULL); $new_assigned_login = param('new_assigned_login', 'string', NULL); if ($Item->assign_to($new_assigned_ID, $new_assigned_login)) { // An assigned user can be changed $Item->dbupdate(); } else { // Error on changing of an assigned user load_funcs('_core/_template.funcs.php'); headers_content_mightcache('text/html', 0, '#', false); // Do NOT cache error messages! (Users would not see they fixed them) header_http_response('400 Bad Request'); // This message is displayed after an input field echo T_('Username not found!'); die(2); // Error code 2. Note: this will still call the shutdown function. // EXIT here! } if (empty($Item->assigned_user_ID)) { $new_title = T_('No user'); } else { $is_admin_page = true; $UserCache =& get_UserCache(); $User =& $UserCache->get_by_ID($Item->assigned_user_ID); $new_title = $User->get_colored_login(array('mask' => '$avatar$ $login$')); } $new_value = $Item->assigned_user_ID;
/** * Sends HTTP header to redirect to the previous location (which * can be given as function parameter, GET parameter (redirect_to), * is taken from {@link Hit::$referer} or {@link $baseurl}). * * {@link $Debuglog} and {@link $Messages} get stored in {@link $Session}, so they * are available after the redirect. * * NOTE: This function {@link exit() exits} the php script execution. * * @todo fp> do NOT allow $redirect_to = NULL. This leads to spaghetti code and unpredictable behavior. * * @param string Destination URL to redirect to * @param boolean|integer is this a permanent redirect? if true, send a 301; otherwise a 303 OR response code 301,302,303 */ function header_redirect($redirect_to = NULL, $status = false) { /** * put your comment there... * * @var Hit */ global $Hit; global $baseurl, $Blog, $htsrv_url_sensitive; global $Session, $Debuglog, $Messages; global $http_response_code; // TODO: fp> get this out to the caller, make a helper func like get_returnto_url() if (empty($redirect_to)) { // see if there's a redirect_to request param given: $redirect_to = param('redirect_to', 'url', ''); if (empty($redirect_to)) { if (!empty($Hit->referer)) { $redirect_to = $Hit->referer; } elseif (isset($Blog) && is_object($Blog)) { $redirect_to = $Blog->get('url'); } else { $redirect_to = $baseurl; } } elseif ($redirect_to[0] == '/') { // relative URL, prepend current host: global $ReqHost; $redirect_to = $ReqHost . $redirect_to; } } // <fp if ($redirect_to[0] == '/') { // TODO: until all calls to header_redirect are cleaned up: global $ReqHost; $redirect_to = $ReqHost . $redirect_to; // debug_die( '$redirect_to must be an absolute URL' ); } if (strpos($redirect_to, $htsrv_url_sensitive) === 0 || strpos($redirect_to, $baseurl) === 0) { // Remove login and pwd parameters from URL, so that they do not trigger the login screen again: // Also remove "action" get param to avoid unwanted actions // blueyed> Removed the removing of "action" here, as it is used to trigger certain views. Instead, "confirm(ed)?" gets removed now // fp> which views please (important to list in order to remove asap) // dh> sorry, don't remember // TODO: fp> action should actually not be used to trigger views. This should be changed at some point. // TODO: fp> confirm should be normalized to confirmed $redirect_to = preg_replace('~(?<=\\?|&) (login|pwd|confirm(ed)?) = [^&]+ ~x', '', $redirect_to); } if (is_integer($status)) { $http_response_code = $status; } else { $http_response_code = $status ? 301 : 303; } $Debuglog->add('***** REDIRECT TO ' . $redirect_to . ' (status ' . $http_response_code . ') *****', 'request'); if (!empty($Session)) { // Session is required here // Transfer of Debuglog to next page: if ($Debuglog->count('all')) { // Save Debuglog into Session, so that it's available after redirect (gets loaded by Session constructor): $sess_Debuglogs = $Session->get('Debuglogs'); if (empty($sess_Debuglogs)) { $sess_Debuglogs = array(); } $sess_Debuglogs[] = $Debuglog; $Session->set('Debuglogs', $sess_Debuglogs, 60); // echo 'Passing Debuglog(s) to next page'; // pre_dump( $sess_Debuglogs ); } // Transfer of Messages to next page: if ($Messages->count()) { // Set Messages into user's session, so they get restored on the next page (after redirect): $Session->set('Messages', $Messages); // echo 'Passing Messages to next page'; } $Session->dbsave(); // If we don't save now, we run the risk that the redirect goes faster than the PHP script shutdown. } // see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html switch ($http_response_code) { case 301: // This should be a permanent move redirect! header_http_response('301 Moved Permanently'); break; case 303: // This should be a "follow up" redirect // Note: Also see http://de3.php.net/manual/en/function.header.php#50588 and the other comments around header_http_response('303 See Other'); break; case 302: default: header_http_response('302 Found'); } // debug_die($redirect_to); if (headers_sent($filename, $line)) { debug_die(sprintf('Headers have already been sent in %s on line %d.', basename($filename), $line) . '<br />Cannot <a href="' . htmlspecialchars($redirect_to) . '">redirect</a>.'); } header('Location: ' . $redirect_to, true, $http_response_code); // explictly setting the status is required for (fast)cgi exit(0); }
<?php /** * This page displays an error message when we cannot resolve the extra path. * * This happens when you request an invalid tracking code on track.php for example * * @package evocore */ if (!defined('EVO_MAIN_INIT')) { die('Please, do not access this page directly.'); } header_http_response('404 Not Found'); header('Content-Type: text/html; charset=utf-8'); // no translation $page_title = '404 Not Found'; // -------------------------- HTML HEADER INCLUDED HERE -------------------------- siteskin_include('_html_header.inc.php', array(), true); // force include even if site headers/footers are not enabled // -------------------------------- END OF HEADER -------------------------------- ?> <h1>404 Not Found</h1> <p>The page you requested doesn't seem to exist on <a href="<?php echo $baseurl; ?> ">this system</a>.</p> <?php // -------------------------- HTML FOOTER INCLUDED HERE -------------------------- siteskin_include('_html_footer.inc.php', array(), true); // force include even if site headers/footers are not enabled // -------------------------------- END OF FOOTER --------------------------------
/** * Retrieve and output cache for current URL. * * @return boolean true if we could retrieve */ function retrieve() { global $Debuglog; global $ReqURL; global $servertimenow; global $Timer; global $Settings; // What would be the cache file for the current URL? $af_cache_file = $this->get_af_filecache_path(); /* // fstat() is interesting because it gives the last access time... use that for purging... * Tblue> Note: Many server admins mount partitions with the "noatime" * option, which disables atime updates and thus speeds * up disk access - that means the atime is not reliable, * better use the mtime (modification time). if( $fh = @fopen( $af_cache_file, 'r', false ) ) { $fstat = fstat( $fh ); pre_dump( $fstat ); fclose( $fh ); } */ $Timer->resume('Read cache file'); $lines = @file($af_cache_file, false); $Timer->pause('Read cache file'); if ($this->cache_Blog != NULL) { $last_invalidation_timestamp = $this->cache_Blog->get_setting('last_invalidation_timestamp'); if ($last_invalidation_timestamp == 0) { $this->cache_Blog->set_setting('last_invalidation_timestamp', $servertimenow); $this->cache_Blog->dbupdate(); } } else { $last_invalidation_timestamp = $Settings->get('last_invalidation_timestamp'); if ($last_invalidation_timestamp == 0) { $Settings->set('last_invalidation_timestamp', $servertimenow); $Settings->dbupdate(); } } // fp> note we are using empty() so that we detect both the case where there is no file and the case where the file // might have ended up empty because PHP crashed while writing to it or sth like that... if (!empty($lines)) { // We have data in the cache! $Debuglog->add('Retrieving from cache!', 'pagecache'); $Timer->resume('Cache file processing'); // Retrieved cached URL: $retrieved_url = trim($lines[0]); unset($lines[0]); if ($retrieved_url != $ReqURL) { $Debuglog->add('Cached file URL [' . $retrieved_url . '] does not match current URL, aborting retrieve.', 'pagecache'); return false; } // timestamp of cache generation: $retrieved_ts = trim($lines[1]); unset($lines[1]); $cache_age = $servertimenow - $retrieved_ts; $Debuglog->add('Cache age: ' . floor($cache_age / 60) . ' min ' . $cache_age % 60 . ' sec', 'pagecache'); if ($cache_age > $this->max_age_seconds || $last_invalidation_timestamp > $retrieved_ts) { // Cache has expired return false; } $i = 1; $optional_headers = array(); // Go through optional header lines // Optional headers are separated from the file header with an empty line. while ($optional_header_line = trim($lines[++$i])) { // All optional header name value must be separated with ':' if (strpos($optional_header_line, ':') === false) { $Debuglog->add('Cached file format not recognized, aborting retrieve.', 'pagecache'); return false; } list($header_name, $header_value) = explode(":", $optional_header_line); // Optional header name and value must not be empty $header_name = trim($header_name); $header_value = trim($header_value); if (empty($header_name) || empty($header_value)) { $Debuglog->add('Cached file format not recognized, aborting retrieve.', 'pagecache'); return false; } $optional_headers[$header_name] = $header_value; unset($lines[$i]); } // unset the empty line unset($lines[$i]); // count item views happening on this page: if (isset($optional_headers['item_IDs_on_this_page'])) { global $shutdown_count_item_views; $shutdown_count_item_views = explode(',', $optional_headers['item_IDs_on_this_page']); } // Check if the request has an If-Modified-Since date if (array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER)) { $if_modified_since = strtotime(preg_replace('/;.*$/', '', $_SERVER['HTTP_IF_MODIFIED_SINCE'])); if ($retrieved_ts <= $if_modified_since) { // Cached version is equal to (or older than) $if_modified since; contents probably not modified... // It is still possible that in between we have sent logged-in versions (including evobar) of the page // and that the browser has an evobar version of the page in cache. Let's verify this before sending a 304... // We do this with an ETag header (another solution may be the Vary header) if (array_key_exists('HTTP_IF_NONE_MATCH', $_SERVER)) { $if_none_match = $_SERVER['HTTP_IF_NONE_MATCH']; // pre_dump($if_none_match, gen_current_page_etag() ); if ($if_none_match == gen_current_page_etag()) { // Ok, this seems to be really the same: header_http_response('304 Not Modified'); exit(0); } } } } // Page was modified, revert $shutdown_count_item_views set $shutdown_count_item_views = array(); // ============== Ready to send cached version of the page ================= // Send no cache header including last modified date: header_nocache($retrieved_ts); // Go through headers that were saved in the cache: // $i was already set while ($headerline = trim($lines[++$i])) { header($headerline); unset($lines[$i]); } unset($lines[$i]); // SEND CONTENT! $body = implode('', $lines); $Timer->pause('Cache file processing'); $Timer->resume('Sending cached content'); // Echo a first chunk (see explanation below) $buffer_size = 12000; // Empiric value, you can make it smaller if you show me screenshots of better timings with a smaller value echo substr($body, 0, $buffer_size); ob_start(); // fp> So why do we want an ob_start here? // fp> Because otherwise echo will "hang" until all the data gets passed through apache (on default Apache install with default SendBufferSize) // fp> With ob_start() the script will terminate much faster and the total exec time of the script will look much smaller. // fp> This doesn't actually improve the speed of the transmission, it just lets the PHP script exit earlier // fp> DRAWBACK: shutdown will be executed *before* the "ob" data is actually sent :'( // fp> This is why we send a first chunk of data before ob_start(). shutdown can occur while that data is sent. then the remainder is sent. // Inspiration: http://wonko.com/post/seeing_poor_performance_using_phps_echo_statement_heres_why // http://fplanque.com/dev/linux/how-to-log-request-processing-times-in-apache // http://fplanque.com/dev/linux/why-echo-is-slow-in-php-how-to-make-it-really-fast // fp> TODO: do something similar during page cache collection. echo substr($body, $buffer_size); // ob_end_flush(); // fp> WARNING: Putting an end flush here would just kill the benefit of the ob_start() above. $Timer->pause('Sending cached content'); return true; } return false; }
} if (!empty($Goal->redir_url) || !empty($Goal->temp_redir_url)) { // TODO adapt and use header_redirect() $redir_url = $Goal->get_active_url(); if (preg_match('/\\$([a-z_]+)\\$/i', $redir_url, $matches)) { // We want to replace a special code like $hit_ID$ in the redir URL: // Tblue> What about using preg_replace_callback() to do this? switch ($matches[1]) { case 'hit_ID': // We need to log the HIT now! Because we need the hit ID! $Hit->log(); $redir_url = str_replace('$hit_ID$', $Hit->ID, $redir_url); break; } } header_http_response('302 Found'); header('Location: ' . $redir_url, true, 302); // explictly setting the status is required for (fast)cgi // TODO: dh> str_repeat won't be enough (when gzipped), see http://core.trac.wordpress.org/ticket/8942 // should be probably a more general function and get used in e.g. bad_request_die(), too (if necessary) echo str_repeat(' ', 1024); evo_flush(); // At this point Firefox 2 will redirect without waiting for the end of the page, but IE7 will not :/ } else { // No redirection specified, we send a blank pixel instead: load_funcs('_core/_template.funcs.php'); $blank_gif = $rsc_path . 'img/blank.gif'; header('Content-type: image/gif'); header('Content-Length: ' . filesize($blank_gif)); header_nocache(); readfile($blank_gif);
<?php /** * This page displays an error message if the user is denied access to the admin section * * @package evocore */ if (!defined('EVO_MAIN_INIT')) { die('Please, do not access this page directly.'); } header_http_response('403 Forbidden'); headers_content_mightcache('text/html', 0); // Do NOT cache error messages! (Users would not see they fixed them) ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title><?php echo T_('Access denied'); ?> </title> </head> <body> <div style="background-color:#fee; border: 1px solid red; text-align:center;"> <h1><?php echo T_('Access denied'); ?> </h1> <p><?php echo T_('Sorry, you have no permission to access this section.'); ?>
<?php /** * This page displays an error message when we have detected access to the stats. * * @package evocore */ if (!defined('EVO_MAIN_INIT')) { die('Please, do not access this page directly.'); } // Note: if you have a really really good reason to bypass this, uncomment the following line: // return; header_http_response('410 Gone'); header('Content-Type: text/html; charset=iso-8859-1'); // no translation ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>410 Gone</title> </head> <body> <h1>410 Gone</h1> <p><?php echo $app_name; ?> does no longer publish referer statistics publicly in order not to attract spam robots.</p> </body> </html> <?php exit(0);
/** * Sends HTTP header to redirect to the previous location (which * can be given as function parameter, GET parameter (redirect_to), * is taken from {@link Hit::$referer} or {@link $baseurl}). * * {@link $Debuglog} and {@link $Messages} get stored in {@link $Session}, so they * are available after the redirect. * * NOTE: This function {@link exit() exits} the php script execution. * * @todo fp> do NOT allow $redirect_to = NULL. This leads to spaghetti code and unpredictable behavior. * * @param string Destination URL to redirect to * @param boolean|integer is this a permanent redirect? if true, send a 301; otherwise a 303 OR response code 301,302,303 * @param boolean is this a redirected post display? This param may be true only if we should redirect to a post url where the post status is 'redirected'! */ function header_redirect($redirect_to = NULL, $status = false, $redirected_post = false) { /** * put your comment there... * * @var Hit */ global $Hit; global $baseurl, $Blog, $htsrv_url_sensitive, $ReqHost, $ReqURL, $dispatcher; global $Session, $Debuglog, $Messages; global $http_response_code, $allow_redirects_to_different_domain; // TODO: fp> get this out to the caller, make a helper func like get_returnto_url() if (empty($redirect_to)) { // see if there's a redirect_to request param given: $redirect_to = param('redirect_to', 'url', ''); if (empty($redirect_to)) { if (!empty($Hit->referer)) { $redirect_to = $Hit->referer; } elseif (isset($Blog) && is_object($Blog)) { $redirect_to = $Blog->get('url'); } else { $redirect_to = $baseurl; } } elseif ($redirect_to[0] == '/') { // relative URL, prepend current host: $redirect_to = $ReqHost . $redirect_to; } } // <fp $Debuglog->add('Preparing to redirect to: ' . $redirect_to, 'request'); // Determine if this is an external or internal redirect: $external_redirect = true; // Start with worst case, then whitelist: if ($redirect_to[0] == '/' || $redirect_to[0] == '?') { // We stay on the same domain or same page: $external_redirect = false; } elseif (strpos($redirect_to, $dispatcher) === 0) { // $dispatcher is DEPRECATED and pages should use $admin_url URL instead, but at least we're staying on the same site: $external_redirect = false; } elseif (strpos($redirect_to, $baseurl) === 0) { $Debuglog->add('Redirecting within $baseurl, all is fine.', 'request'); $external_redirect = false; } elseif (strpos($redirect_to, $htsrv_url_sensitive) === 0) { $Debuglog->add('Redirecting within $htsrv_url_sensitive, all is fine.', 'request'); $external_redirect = false; } elseif (!empty($Blog) && strpos($redirect_to, $Blog->gen_baseurl()) === 0) { $Debuglog->add('Redirecting within current collection URL, all is fine.', 'request'); $external_redirect = false; } // Remove login and pwd parameters from URL, so that they do not trigger the login screen again (and also as global security measure): $redirect_to = preg_replace('~(?<=\\?|&) (login|pwd) = [^&]+ ~x', '', $redirect_to); if ($external_redirect == false) { // (blueyed>) Remove "confirm(ed)?" from redirect_to so it doesn't do the same thing twice // TODO: fp> confirm should be normalized to confirmed $redirect_to = preg_replace('~(?<=\\?|&) (confirm(ed)?) = [^&]+ ~x', '', $redirect_to); } $allow_collection_redirect = false; if ($external_redirect && $allow_redirects_to_different_domain == 'all_collections_and_redirected_posts' && !$redirected_post) { // If a redirect is external and we allow to redirect to all collection domains: $BlogCache =& get_BlogCache(); $BlogCache->load_all(); $redirect_to_domain = preg_replace('~https?://([^/]+)/?.*~i', '$1', $redirect_to); foreach ($BlogCache->cache as $url_Blog) { $blog_domain = preg_replace('~https?://([^/]+)/?.*~i', '$1', $url_Blog->gen_baseurl()); if ($blog_domain == $redirect_to_domain) { // We found current redirect goes to a collection domain, so it is not external $allow_collection_redirect = true; break; } } } // Check if we're trying to redirect to an external URL: if ($external_redirect && $allow_redirects_to_different_domain != 'always' && !$allow_collection_redirect && !(in_array($allow_redirects_to_different_domain, array('all_collections_and_redirected_posts', 'only_redirected_posts')) && $redirected_post)) { // Force header redirects into the same domain. Do not allow external URLs. $Messages->add(T_('A redirection to an external URL was blocked for security reasons.'), 'error'); syslog_insert('A redirection to an external URL ' . $redirect_to . ' was blocked for security reasons.', 'error', NULL); $redirect_to = $baseurl; } if (is_integer($status)) { $http_response_code = $status; } else { $http_response_code = $status ? 301 : 303; } $Debuglog->add('***** REDIRECT TO ' . $redirect_to . ' (status ' . $http_response_code . ') *****', 'request'); if (!empty($Session)) { // Session is required here // Transfer of Debuglog to next page: if ($Debuglog->count('all')) { // Save Debuglog into Session, so that it's available after redirect (gets loaded by Session constructor): $sess_Debuglogs = $Session->get('Debuglogs'); if (empty($sess_Debuglogs)) { $sess_Debuglogs = array(); } $sess_Debuglogs[] = $Debuglog; $Session->set('Debuglogs', $sess_Debuglogs, 60); // echo 'Passing Debuglog(s) to next page'; // pre_dump( $sess_Debuglogs ); } // Transfer of Messages to next page: if ($Messages->count()) { // Set Messages into user's session, so they get restored on the next page (after redirect): $Session->set('Messages', $Messages); // echo 'Passing Messages to next page'; } $Session->dbsave(); // If we don't save now, we run the risk that the redirect goes faster than the PHP script shutdown. } // see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html switch ($http_response_code) { case 301: // This should be a permanent move redirect! header_http_response('301 Moved Permanently'); break; case 303: // This should be a "follow up" redirect // Note: Also see http://de3.php.net/manual/en/function.header.php#50588 and the other comments around header_http_response('303 See Other'); break; case 302: default: header_http_response('302 Found'); } // debug_die($redirect_to); if (headers_sent($filename, $line)) { debug_die(sprintf('Headers have already been sent in %s on line %d.', basename($filename), $line) . '<br />Cannot <a href="' . htmlspecialchars($redirect_to) . '">redirect</a>.'); } header('Location: ' . $redirect_to, true, $http_response_code); // explictly setting the status is required for (fast)cgi exit(0); }
// TODO: dh> this failed with filenames containing multiple dots! if (false !== strpos(urldecode($path), '..')) { debug_die('Relative pathnames not allowed!'); } // Load fileroot info: $FileRootCache =& get_FileRootCache(); $FileRoot =& $FileRootCache->get_by_ID($root); // Load file object (not the file content): $File = new File($FileRoot->type, $FileRoot->in_type_ID, $path); // Check if the request has an If-Modified-Since date if (array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER)) { $if_modified_since = strtotime(preg_replace('/;.*$/', '', $_SERVER['HTTP_IF_MODIFIED_SINCE'])); $file_lastmode_ts = $File->get_lastmod_ts(); if ($file_lastmode_ts <= $if_modified_since) { // file was not modified since if_modified_since ts header_http_response('304 Not Modified'); exit(0); } } if (!empty($size) && $File->is_image()) { // We want a thumbnail: // fp> TODO: for more efficient caching, this should probably redirect to the static file right after creating it (when $public_access_to_media=true OF COURSE) global $thumbnail_sizes; load_funcs('/files/model/_image.funcs.php'); $size_name = $size; if (!isset($thumbnail_sizes[$size])) { // this file size alias is not defined, use default: // TODO: dh> this causes links for e.g. "fit-50x50" to work also, but with the drawback of images not getting served from the // .evocache directory directly. I think invalid $size params should bark out here. // fp> ok. $size_name = 'fit-80x80';