/** * Get the EDP downloaded * * @param string $path path to the file * @param string $filename file name to be displayed in download dialog * @param boolean $delete deletes original file after download * @return bool Always false */ function fn_get_file($file_path, $filename = '', $delete = false) { $handle_stream = @fopen($file_path, 'rb'); if (!$handle_stream) { return false; } $file_size = filesize($file_path); $file_mime_type = fn_get_mime_content_type($file_path); $file_last_modified_time = date('D, d M Y H:i:s T', filemtime($file_path)); if (empty($filename)) { // Non-ASCII filenames containing spaces and underscore // characters are chunked if no locale is provided setlocale(LC_ALL, 'en_US.UTF8'); $filename = fn_basename($file_path); } if (isset($_SERVER['HTTP_RANGE'])) { $range = str_replace('bytes=', '', $_SERVER['HTTP_RANGE']); $range = (int) strtok($range, '-'); if (!empty($range)) { fseek($handle_stream, $range); } } else { $range = 0; } // Clear output buffers before headers are sent to prevent dowloading damaged file // if any content was added to buffers before $gz_handler = false; foreach (ob_list_handlers() as $handler) { if (strpos($handler, 'gzhandler') !== false) { $gz_handler = true; break; } } fn_clear_ob(); // Delete headers added by ob_start("ob_gzhandler") if ($gz_handler && !headers_sent() && !ob_list_handlers()) { header_remove('Vary'); header_remove('Content-Encoding'); } // Browser bug workaround: filenames can't be sent to IE if there is // any kind of traffic compression enabled on the server side if (USER_AGENT == 'ie') { if (function_exists('apache_setenv')) { apache_setenv('no-gzip', '1'); } ini_set("zlib.output_compression", "Off"); // Browser bug workaround: During the file download with IE, // non-ASCII filenames appears with a broken encoding $filename = rawurlencode($filename); } if ($range) { header($_SERVER['SERVER_PROTOCOL'] . ' 206 Partial Content'); header("Content-Range: bytes {$range}-" . ($file_size - 1) . '/' . $file_size); } else { header($_SERVER['SERVER_PROTOCOL'] . ' 200 OK'); } header('Content-Disposition: attachment; filename="' . $filename . '"'); header('Content-Type: ' . $file_mime_type); header('Last-Modified: ' . $file_last_modified_time); header('Accept-Ranges: bytes'); header('Content-Length: ' . ($file_size - $range)); header('Pragma: public'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Cache-Control: private', false); $result = fpassthru($handle_stream); fclose($handle_stream); if ($delete) { fn_rm($file_path); } if ($result === false) { return false; } exit; }
/** * Registers custom error handlers * * @return array */ function fn_init_error_handler() { // Fatal error handler defined('AREA') && AREA == 'C' && register_shutdown_function(function () { $error = error_get_last(); // Check whether error is fatal (i.e. couldn't have been catched with trivial error handler) if (isset($error['type']) && in_array($error['type'], array(E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING))) { // Try to hide PHP's fatal error message fn_clear_ob(); $exception = new PHPErrorException($error['message'], $error['type'], $error['file'], $error['line']); $exception->output(); exit(1); } }); // Non-fatal errors, warnings and notices are caught and properly formatted defined('DEVELOPMENT') && DEVELOPMENT && !extension_loaded('xdebug') && set_error_handler(function ($code, $message, $filename, $line) { if (error_reporting() & $code) { switch ($code) { // Non-fatal errors, code execution wouldn't be stopped case E_NOTICE: case E_USER_NOTICE: case E_WARNING: case E_USER_WARNING: case E_DEPRECATED: case E_USER_DEPRECATED: $exception = new PHPErrorException($message, $code, $filename, $line); $exception->output(); error_log(addslashes((string) $exception), 0); return true; break; } } // Let PHP's internal error handler handle other cases return false; }); return array(INIT_STATUS_OK); }