diff --git a/admin/bloglevelupgrade.php b/admin/bloglevelupgrade.php index 3a08d45047168..7d20ef593abd3 100644 --- a/admin/bloglevelupgrade.php +++ b/admin/bloglevelupgrade.php @@ -1,6 +1,8 @@ dirroot.'/course/lib.php'); require_once($CFG->dirroot.'/blog/lib.php'); @@ -28,9 +30,7 @@ /// Turn off time limits, sometimes upgrades can be slow. -@set_time_limit(0); -@ob_implicit_flush(true); -while(@ob_end_flush()); +set_time_limit(0); $i = 0; diff --git a/admin/cron.php b/admin/cron.php index 51b34aecc4d37..e131e9bbf057a 100644 --- a/admin/cron.php +++ b/admin/cron.php @@ -40,24 +40,12 @@ // CLI via web interface, please do not use this hack elsewhere define('CLI_SCRIPT', true); define('WEB_CRON_EMULATED_CLI', 'defined'); // ugly ugly hack, do not use elsewhere please +define('NO_OUTPUT_BUFFERING', true); require('../config.php'); require_once($CFG->libdir.'/clilib.php'); require_once($CFG->libdir.'/cronlib.php'); -// disable compression, it would prevent closing of buffers -if (ini_get('zlib.output_compression')) { - ini_set('zlib.output_compression', 'Off'); -} -// no more headers and buffers -ob_implicit_flush(true); -while(ob_get_level()) { - if (!ob_end_clean()) { - // prevent infinite loop - break; - } -} - // extra safety session_get_instance()->write_close(); diff --git a/admin/index.php b/admin/index.php index e70c14c01b1c2..14b6f243321af 100644 --- a/admin/index.php +++ b/admin/index.php @@ -38,19 +38,7 @@ die; } -// disable compression, it would prevent closing of buffers -if (ini_get('zlib.output_compression')) { - ini_set('zlib.output_compression', 'Off'); -} - -// try to flush everything all the time -ob_implicit_flush(true); -while(ob_get_level()) { - if (!ob_end_clean()) { - // prevent infinite loop - break; - } -} +define('NO_OUTPUT_BUFFERING', true); require('../config.php'); require_once($CFG->libdir.'/adminlib.php'); // various admin-only functions diff --git a/admin/multilangupgrade.php b/admin/multilangupgrade.php index 453e68227d43f..d25c70953a512 100644 --- a/admin/multilangupgrade.php +++ b/admin/multilangupgrade.php @@ -1,6 +1,8 @@ dirroot.'/course/lib.php'); require_once($CFG->libdir.'/adminlib.php'); @@ -33,8 +35,6 @@ /// Turn off time limits, sometimes upgrades can be slow. @set_time_limit(0); -@ob_implicit_flush(true); -while(@ob_end_flush()); echo 'Progress:'; $i = 0; diff --git a/admin/replace.php b/admin/replace.php index 37b67c0ceb5f0..e77070b11d990 100644 --- a/admin/replace.php +++ b/admin/replace.php @@ -1,15 +1,12 @@ dirroot.'/course/lib.php'); require_once($CFG->libdir.'/adminlib.php'); -// workaround for problems with compression -if (ini_get('zlib.output_compression')) { - @ini_set('zlib.output_compression', 'Off'); -} - admin_externalpage_setup('replace'); $search = optional_param('search', '', PARAM_RAW); diff --git a/admin/report/security/index.php b/admin/report/security/index.php index ddb96d73097a7..9b7cfbe1780a4 100644 --- a/admin/report/security/index.php +++ b/admin/report/security/index.php @@ -23,6 +23,8 @@ // // /////////////////////////////////////////////////////////////////////////// +define('NO_OUTPUT_BUFFERING', true); + require_once('../../../config.php'); require_once($CFG->dirroot.'/'.$CFG->admin.'/report/security/lib.php'); require_once($CFG->libdir.'/adminlib.php'); @@ -49,8 +51,6 @@ echo $OUTPUT->heading(get_string('pluginname', 'report_security')); echo '
'.get_string('timewarning', 'report_security').'
'; -while(@ob_end_flush()); -@flush(); $strok = ''.get_string('statusok', 'report_security').''; $strinfo = ''.get_string('statusinfo', 'report_security').''; diff --git a/admin/report/unittest/dbtest.php b/admin/report/unittest/dbtest.php index 8e4725685ed24..63060a1660392 100644 --- a/admin/report/unittest/dbtest.php +++ b/admin/report/unittest/dbtest.php @@ -4,27 +4,14 @@ * @package SimpleTestEx */ -/** */ +define('NO_OUTPUT_BUFFERING', true); + require_once(dirname(__FILE__).'/../../../config.php'); require_once($CFG->libdir.'/adminlib.php'); require_once($CFG->libdir.'/simpletestcoveragelib.php'); require_once('ex_simple_test.php'); require_once('ex_reporter.php'); -// disable compression, it would prevent closing of buffers -if (ini_get('zlib.output_compression')) { - ini_set('zlib.output_compression', 'Off'); -} - -// try to flush everything all the time -ob_implicit_flush(true); -while(ob_get_level()) { - if (!ob_end_clean()) { - // prevent infinite loop - break; - } -} - $showpasses = optional_param('showpasses', false, PARAM_BOOL); $codecoverage = optional_param('codecoverage', false, PARAM_BOOL); $selected = optional_param('selected', array(), PARAM_INT); diff --git a/admin/report/unittest/index.php b/admin/report/unittest/index.php index c5768997c43d5..c19f4e8f0132b 100644 --- a/admin/report/unittest/index.php +++ b/admin/report/unittest/index.php @@ -8,27 +8,14 @@ * @package SimpleTestEx */ -/** */ +define('NO_OUTPUT_BUFFERING', true); + require_once(dirname(__FILE__).'/../../../config.php'); require_once($CFG->libdir.'/adminlib.php'); require_once($CFG->libdir.'/simpletestcoveragelib.php'); require_once('ex_simple_test.php'); require_once('ex_reporter.php'); -// disable compression, it would prevent closing of buffers -if (ini_get('zlib.output_compression')) { - ini_set('zlib.output_compression', 'Off'); -} - -// try to flush everything all the time -ob_implicit_flush(true); -while(ob_get_level()) { - if (!ob_end_clean()) { - // prevent infinite loop - break; - } -} - // Always run the unit tests in developer debug mode. $CFG->debug = DEBUG_DEVELOPER; error_reporting($CFG->debug); diff --git a/calendar/export_execute.php b/calendar/export_execute.php index 1c676be3f690b..e4d62bd322990 100644 --- a/calendar/export_execute.php +++ b/calendar/export_execute.php @@ -152,7 +152,7 @@ } //IE compatibility HACK! -if(ini_get('zlib.output_compression')) { +if (ini_get_bool('zlib.output_compression')) { ini_set('zlib.output_compression', 'Off'); } diff --git a/lang/en/error.php b/lang/en/error.php index f1cf1b70be00f..c0241d9888ea5 100755 --- a/lang/en/error.php +++ b/lang/en/error.php @@ -129,6 +129,7 @@ $string['cannotsavefile'] = 'Cannot save the file "{$a}"!'; $string['cannotsavemd5file'] = 'Cannot save md5 file'; $string['cannotsavezipfile'] = 'Cannot save ZIP file'; +$string['cannotservefile'] = 'Can not serve file - server configuration problem.'; $string['cannotsetparentforcatoritem'] = 'Cannot set parent for category or course item!'; $string['cannotsetpassword'] = 'Could not set user password!'; $string['cannotsetprefgrade'] = 'Could not set preference aggregationview to {$a} for this grade category'; diff --git a/lib/adminlib.php b/lib/adminlib.php index d44f3cb2b500a..f9152582006f6 100644 --- a/lib/adminlib.php +++ b/lib/adminlib.php @@ -5919,8 +5919,6 @@ function db_replace($search, $replace) { /// Turn off time limits, sometimes upgrades can be slow. @set_time_limit(0); - @ob_implicit_flush(true); - while(@ob_end_flush()); if (!$tables = $DB->get_tables() ) { // No tables yet at all. return false; diff --git a/lib/filelib.php b/lib/filelib.php index 2cfa78914d3e6..23687bf2019de 100644 --- a/lib/filelib.php +++ b/lib/filelib.php @@ -1474,11 +1474,43 @@ function send_file_not_found() { print_error('filenotfound', 'error', $CFG->wwwroot.'/course/view.php?id='.$COURSE->id); //this is not displayed on IIS?? } +/** + * Check output buffering settings before sending file + * @private to be called only from lib/filelib.php ! + * @return void + */ +function prepare_file_sending() { + $olddebug = error_reporting(0); + + // IE compatibility HACK - it does not like zlib compression much + // there is also a problem with the length header in older PHP versions + if (ini_get_bool('zlib.output_compression')) { + ini_set('zlib.output_compression', 'Off'); + } + + // flush and close all buffers if possible + while(ob_get_level()) { + if (!ob_end_flush()) { + // prevent infinite loop when buffer can not be closed + break; + } + } + + error_reporting($olddebug); + + // now make sure we can actually send out headers, + // if not it is a fatal problem because we could + // create XSS problems through student files + // or the content of the file would be borked. + if (headers_sent()) { + throw new file_serving_exception('Headers already sent, can not serve file!'); + } +} + /** * Handles the sending of temporary file to user, download is forced. * File is deleted after abort or successful sending. * - * @global object * @param string $path path to file, preferably from moodledata/temp/something; or content of file itself * @param string $filename proposed file name when saving file * @param bool $path is content of file @@ -1499,32 +1531,31 @@ function send_temp_file($path, $filename, $pathisstring=false) { @register_shutdown_function('send_temp_file_finished', $path); } - //IE compatibility HACK! - if (ini_get('zlib.output_compression')) { - ini_set('zlib.output_compression', 'Off'); - } - // if user is using IE, urlencode the filename so that multibyte file name will show up correctly on popup if (check_browser_version('MSIE')) { $filename = urlencode($filename); } + //flush the buffers - save memory and disable sid rewrite + // this also disables zlib compression + prepare_file_sending(); + $filesize = $pathisstring ? strlen($path) : filesize($path); - @header('Content-Disposition: attachment; filename='.$filename); - @header('Content-Length: '.$filesize); + header('Content-Disposition: attachment; filename='.$filename); + header('Content-Length: '.$filesize); if (strpos($CFG->wwwroot, 'https://') === 0) { //https sites - watch out for IE! KB812935 and KB316431 - @header('Cache-Control: max-age=10'); - @header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT'); - @header('Pragma: '); + header('Cache-Control: max-age=10'); + header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT'); + header('Pragma: '); } else { //normal http - prevent caching at all cost - @header('Cache-Control: private, must-revalidate, pre-check=0, post-check=0, max-age=0'); - @header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT'); - @header('Pragma: no-cache'); + header('Cache-Control: private, must-revalidate, pre-check=0, post-check=0, max-age=0'); + header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT'); + header('Pragma: no-cache'); } - @header('Accept-Ranges: none'); // Do not allow byteserving + header('Accept-Ranges: none'); // Do not allow byteserving - while (@ob_end_flush()); //flush the buffers - save memory and disable sid rewrite + // send the contents if ($pathisstring) { echo $path; } else { @@ -1609,17 +1640,15 @@ function send_file($path, $filename, $lifetime = 'default' , $filter=0, $pathiss } */ - //IE compatibiltiy HACK! - if (ini_get('zlib.output_compression')) { - ini_set('zlib.output_compression', 'Off'); - } - //try to disable automatic sid rewrite in cookieless mode @ini_set("session.use_trans_sid", "false"); + //flush the buffers - save memory and disable sid rewrite + //this also disables zlib compression + prepare_file_sending(); + //do not put '@' before the next header to detect incorrect moodle configurations, //error should be better than "weird" empty lines for admins/users - //TODO: should we remove all those @ before the header()? Are all of the values supported on all servers? header('Last-Modified: '. gmdate('D, d M Y H:i:s', $lastmodified) .' GMT'); // if user is using IE, urlencode the filename so that multibyte file name will show up correctly on popup @@ -1628,19 +1657,19 @@ function send_file($path, $filename, $lifetime = 'default' , $filter=0, $pathiss } if ($forcedownload) { - @header('Content-Disposition: attachment; filename="'.$filename.'"'); + header('Content-Disposition: attachment; filename="'.$filename.'"'); } else { - @header('Content-Disposition: inline; filename="'.$filename.'"'); + header('Content-Disposition: inline; filename="'.$filename.'"'); } if ($lifetime > 0) { - @header('Cache-Control: max-age='.$lifetime); - @header('Expires: '. gmdate('D, d M Y H:i:s', time() + $lifetime) .' GMT'); - @header('Pragma: '); + header('Cache-Control: max-age='.$lifetime); + header('Expires: '. gmdate('D, d M Y H:i:s', time() + $lifetime) .' GMT'); + header('Pragma: '); if (empty($CFG->disablebyteserving) && !$pathisstring && $mimetype != 'text/plain' && $mimetype != 'text/html') { - @header('Accept-Ranges: bytes'); + header('Accept-Ranges: bytes'); if (!empty($_SERVER['HTTP_RANGE']) && strpos($_SERVER['HTTP_RANGE'],'bytes=') !== FALSE) { // byteserving stuff - for acrobat reader and download accelerators @@ -1676,41 +1705,43 @@ function send_file($path, $filename, $lifetime = 'default' , $filter=0, $pathiss } } else { /// Do not byteserve (disabled, strings, text and html files). - @header('Accept-Ranges: none'); + header('Accept-Ranges: none'); } } else { // Do not cache files in proxies and browsers if (strpos($CFG->wwwroot, 'https://') === 0) { //https sites - watch out for IE! KB812935 and KB316431 - @header('Cache-Control: max-age=10'); - @header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT'); - @header('Pragma: '); + header('Cache-Control: max-age=10'); + header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT'); + header('Pragma: '); } else { //normal http - prevent caching at all cost - @header('Cache-Control: private, must-revalidate, pre-check=0, post-check=0, max-age=0'); - @header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT'); - @header('Pragma: no-cache'); + header('Cache-Control: private, must-revalidate, pre-check=0, post-check=0, max-age=0'); + header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT'); + header('Pragma: no-cache'); } - @header('Accept-Ranges: none'); // Do not allow byteserving when caching disabled + header('Accept-Ranges: none'); // Do not allow byteserving when caching disabled } if (empty($filter)) { if ($mimetype == 'text/html' && !empty($CFG->usesid)) { //cookieless mode - rewrite links - @header('Content-Type: text/html'); + header('Content-Type: text/html'); $path = $pathisstring ? $path : implode('', file($path)); $path = sid_ob_rewrite($path); $filesize = strlen($path); $pathisstring = true; } else if ($mimetype == 'text/plain') { - @header('Content-Type: Text/plain; charset=utf-8'); //add encoding + header('Content-Type: Text/plain; charset=utf-8'); //add encoding } else { - @header('Content-Type: '.$mimetype); + header('Content-Type: '.$mimetype); } - @header('Content-Length: '.$filesize); - while (@ob_end_flush()); //flush the buffers - save memory and disable sid rewrite + header('Content-Length: '.$filesize); + + // send the contents if ($pathisstring) { echo $path; } else { @readfile($path); } + } else { // Try to put the file through filters if ($mimetype == 'text/html') { $options = new stdClass(); @@ -1725,9 +1756,9 @@ function send_file($path, $filename, $lifetime = 'default' , $filter=0, $pathiss $output = sid_ob_rewrite($output); } - @header('Content-Length: '.strlen($output)); - @header('Content-Type: text/html'); - while (@ob_end_flush()); //flush the buffers - save memory and disable sid rewrite + header('Content-Length: '.strlen($output)); + header('Content-Type: text/html'); + // send the contents echo $output; // only filter text if filter all files is selected } else if (($mimetype == 'text/plain') and ($filter == 1)) { @@ -1741,14 +1772,14 @@ function send_file($path, $filename, $lifetime = 'default' , $filter=0, $pathiss $output = sid_ob_rewrite($output); } - @header('Content-Length: '.strlen($output)); - @header('Content-Type: text/html; charset=utf-8'); //add encoding - while (@ob_end_flush()); //flush the buffers - save memory and disable sid rewrite + header('Content-Length: '.strlen($output)); + header('Content-Type: text/html; charset=utf-8'); //add encoding + // send the contents echo $output; } else { // Just send it out raw - @header('Content-Length: '.$filesize); - @header('Content-Type: '.$mimetype); - while (@ob_end_flush()); //flush the buffers - save memory and disable sid rewrite + header('Content-Length: '.$filesize); + header('Content-Type: '.$mimetype); + // send the contents if ($pathisstring) { echo $path; }else { @@ -1808,14 +1839,13 @@ function send_stored_file($stored_file, $lifetime=86400 , $filter=0, $forcedownl $lastmodified = $stored_file->get_timemodified(); $filesize = $stored_file->get_filesize(); - //IE compatibiltiy HACK! - if (ini_get('zlib.output_compression')) { - ini_set('zlib.output_compression', 'Off'); - } - //try to disable automatic sid rewrite in cookieless mode @ini_set("session.use_trans_sid", "false"); + //flush the buffers - save memory and disable sid rewrite + //this also disables zlib compression + prepare_file_sending(); + //do not put '@' before the next header to detect incorrect moodle configurations, //error should be better than "weird" empty lines for admins/users //TODO: should we remove all those @ before the header()? Are all of the values supported on all servers? @@ -1827,19 +1857,19 @@ function send_stored_file($stored_file, $lifetime=86400 , $filter=0, $forcedownl } if ($forcedownload) { - @header('Content-Disposition: attachment; filename="'.$filename.'"'); + header('Content-Disposition: attachment; filename="'.$filename.'"'); } else { - @header('Content-Disposition: inline; filename="'.$filename.'"'); + header('Content-Disposition: inline; filename="'.$filename.'"'); } if ($lifetime > 0) { - @header('Cache-Control: max-age='.$lifetime); - @header('Expires: '. gmdate('D, d M Y H:i:s', time() + $lifetime) .' GMT'); - @header('Pragma: '); + header('Cache-Control: max-age='.$lifetime); + header('Expires: '. gmdate('D, d M Y H:i:s', time() + $lifetime) .' GMT'); + header('Pragma: '); if (empty($CFG->disablebyteserving) && $mimetype != 'text/plain' && $mimetype != 'text/html') { - @header('Accept-Ranges: bytes'); + header('Accept-Ranges: bytes'); if (!empty($_SERVER['HTTP_RANGE']) && strpos($_SERVER['HTTP_RANGE'],'bytes=') !== FALSE) { // byteserving stuff - for acrobat reader and download accelerators @@ -1874,37 +1904,37 @@ function send_stored_file($stored_file, $lifetime=86400 , $filter=0, $forcedownl } } else { /// Do not byteserve (disabled, strings, text and html files). - @header('Accept-Ranges: none'); + header('Accept-Ranges: none'); } } else { // Do not cache files in proxies and browsers if (strpos($CFG->wwwroot, 'https://') === 0) { //https sites - watch out for IE! KB812935 and KB316431 - @header('Cache-Control: max-age=10'); - @header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT'); - @header('Pragma: '); + header('Cache-Control: max-age=10'); + header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT'); + header('Pragma: '); } else { //normal http - prevent caching at all cost - @header('Cache-Control: private, must-revalidate, pre-check=0, post-check=0, max-age=0'); - @header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT'); - @header('Pragma: no-cache'); + header('Cache-Control: private, must-revalidate, pre-check=0, post-check=0, max-age=0'); + header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT'); + header('Pragma: no-cache'); } - @header('Accept-Ranges: none'); // Do not allow byteserving when caching disabled + header('Accept-Ranges: none'); // Do not allow byteserving when caching disabled } if (empty($filter)) { $filtered = false; if ($mimetype == 'text/html' && !empty($CFG->usesid)) { //cookieless mode - rewrite links - @header('Content-Type: text/html'); + header('Content-Type: text/html'); $text = $stored_file->get_content(); $text = sid_ob_rewrite($text); $filesize = strlen($text); $filtered = true; } else if ($mimetype == 'text/plain') { - @header('Content-Type: Text/plain; charset=utf-8'); //add encoding + header('Content-Type: Text/plain; charset=utf-8'); //add encoding } else { - @header('Content-Type: '.$mimetype); + header('Content-Type: '.$mimetype); } - @header('Content-Length: '.$filesize); - while (@ob_end_flush()); //flush the buffers - save memory and disable sid rewrite + header('Content-Length: '.$filesize); + // send the contents if ($filtered) { echo $text; } else { @@ -1924,9 +1954,9 @@ function send_stored_file($stored_file, $lifetime=86400 , $filter=0, $forcedownl $output = sid_ob_rewrite($output); } - @header('Content-Length: '.strlen($output)); - @header('Content-Type: text/html'); - while (@ob_end_flush()); //flush the buffers - save memory and disable sid rewrite + header('Content-Length: '.strlen($output)); + header('Content-Type: text/html'); + // send the contents echo $output; // only filter text if filter all files is selected } else if (($mimetype == 'text/plain') and ($filter == 1)) { @@ -1940,14 +1970,14 @@ function send_stored_file($stored_file, $lifetime=86400 , $filter=0, $forcedownl $output = sid_ob_rewrite($output); } - @header('Content-Length: '.strlen($output)); - @header('Content-Type: text/html; charset=utf-8'); //add encoding - while (@ob_end_flush()); //flush the buffers - save memory and disable sid rewrite + header('Content-Length: '.strlen($output)); + header('Content-Type: text/html; charset=utf-8'); //add encoding + // send the contents echo $output; } else { // Just send it out raw - @header('Content-Length: '.$filesize); - @header('Content-Type: '.$mimetype); - while (@ob_end_flush()); //flush the buffers - save memory and disable sid rewrite + header('Content-Length: '.$filesize); + header('Content-Type: '.$mimetype); + // send the contents $stored_file->readfile(); } } @@ -2134,11 +2164,10 @@ function byteserving_send_file($handle, $mimetype, $ranges, $filesize) { } if (count($ranges) == 1) { //only one range requested $length = $ranges[0][2] - $ranges[0][1] + 1; - @header('HTTP/1.1 206 Partial content'); - @header('Content-Length: '.$length); - @header('Content-Range: bytes '.$ranges[0][1].'-'.$ranges[0][2].'/'.$filesize); - @header('Content-Type: '.$mimetype); - while (@ob_end_flush()); //flush the buffers - save memory and disable sid rewrite + header('HTTP/1.1 206 Partial content'); + header('Content-Length: '.$length); + header('Content-Range: bytes '.$ranges[0][1].'-'.$ranges[0][2].'/'.$filesize); + header('Content-Type: '.$mimetype); $buffer = ''; fseek($handle, $ranges[0][1]); while (!feof($handle) && $length > 0) { @@ -2156,11 +2185,10 @@ function byteserving_send_file($handle, $mimetype, $ranges, $filesize) { $totallength += strlen($range[0]) + $range[2] - $range[1] + 1; } $totallength += strlen("\r\n--".BYTESERVING_BOUNDARY."--\r\n"); - @header('HTTP/1.1 206 Partial content'); - @header('Content-Length: '.$totallength); - @header('Content-Type: multipart/byteranges; boundary='.BYTESERVING_BOUNDARY); + header('HTTP/1.1 206 Partial content'); + header('Content-Length: '.$totallength); + header('Content-Type: multipart/byteranges; boundary='.BYTESERVING_BOUNDARY); //TODO: check if "multipart/x-byteranges" is more compatible with current readers/browsers/servers - while (@ob_end_flush()); //flush the buffers - save memory and disable sid rewrite foreach($ranges as $range) { $length = $range[2] - $range[1] + 1; echo $range[0]; diff --git a/lib/moodlelib.php b/lib/moodlelib.php index 53de0b0d3dcee..4a7966f839fb5 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -7635,28 +7635,6 @@ function get_browser_version_classes() { return $classes; } -/** - * This function makes the return value of ini_get consistent if you are - * setting server directives through the .htaccess file in apache. - * - * Current behavior for value set from php.ini On = 1, Off = [blank] - * Current behavior for value set from .htaccess On = On, Off = Off - * Contributed by jdell @ unr.edu - * - * @todo Finish documenting this function - * - * @param string $ini_get_arg The argument to get - * @return bool True for on false for not - */ -function ini_get_bool($ini_get_arg) { - $temp = ini_get($ini_get_arg); - - if ($temp == '1' or strtolower($temp) == 'on') { - return true; - } - return false; -} - /** * Can handle rotated text. Whether it is safe to use the trickery in textrotate.js. * diff --git a/lib/setup.php b/lib/setup.php index 80adab7ef92f9..5ea062d225156 100644 --- a/lib/setup.php +++ b/lib/setup.php @@ -113,6 +113,11 @@ define('NO_DEBUG_DISPLAY', false); } +// Some scripts such as upgrade may want to prevent output buffering +if (!defined('NO_OUTPUT_BUFFERING')) { + define('NO_OUTPUT_BUFFERING', false); +} + // Servers should define a default timezone in php.ini, but if they don't then make sure something is defined. // This is a quick hack. Ideally we should ask the admin for a value. See MDL-22625 for more on this. if (function_exists('date_default_timezone_set') and function_exists('date_default_timezone_get')) { @@ -339,6 +344,10 @@ require_once($CFG->libdir .'/setuplib.php'); // Functions that MUST be loaded first +if (NO_OUTPUT_BUFFERING) { + disable_output_buffering(); +} + // Increase memory limits if possible raise_memory_limit(MEMORY_STANDARD); diff --git a/lib/setuplib.php b/lib/setuplib.php index 34cbd6c0b1247..e6fa28b558fd5 100644 --- a/lib/setuplib.php +++ b/lib/setuplib.php @@ -267,6 +267,24 @@ function __construct($debuginfo = NULL) { } } +/** + * An exception that indicates that file can not be served + * + * @package core + * @subpackage lib + * @copyright 2010 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class file_serving_exception extends moodle_exception { + /** + * Constructor + * @param string $debuginfo optional more detailed information + */ + function __construct($debuginfo = NULL) { + parent::__construct('cannotservefile', 'error', '', NULL, $debuginfo); + } +} + /** * Default exception handler, uncaught exceptions are equivalent to error() in 1.9 and earlier * @@ -529,6 +547,26 @@ function format_backtrace($callers, $plaintext = false) { return $from; } +/** + * This function makes the return value of ini_get consistent if you are + * setting server directives through the .htaccess file in apache. + * + * Current behavior for value set from php.ini On = 1, Off = [blank] + * Current behavior for value set from .htaccess On = On, Off = Off + * Contributed by jdell @ unr.edu + * + * @param string $ini_get_arg The argument to get + * @return bool True for on false for not + */ +function ini_get_bool($ini_get_arg) { + $temp = ini_get($ini_get_arg); + + if ($temp == '1' or strtolower($temp) == 'on') { + return true; + } + return false; +} + /** * This function verifies the sanity of PHP configuration * and stops execution if anything critical found. @@ -838,7 +876,7 @@ function raise_memory_limit($newlimit) { return false; } - $cur = @ini_get('memory_limit'); + $cur = ini_get('memory_limit'); if (empty($cur)) { // if php is compiled without --enable-memory-limits // apparently memory_limit is set to '' @@ -872,7 +910,7 @@ function reduce_memory_limit($newlimit) { if (empty($newlimit)) { return false; } - $cur = @ini_get('memory_limit'); + $cur = ini_get('memory_limit'); if (empty($cur)) { // if php is compiled without --enable-memory-limits // apparently memory_limit is set to '' @@ -925,6 +963,34 @@ function get_real_size($size = 0) { return $size; } +/** + * Try to disable all output buffering + * @private to be called only from lib/setup.php ! + * @return void + */ +function disable_output_buffering() { + $olddebug = error_reporting(0); + + // disable compression, it would prevent closing of buffers + if (ini_get_bool('zlib.output_compression')) { + ini_set('zlib.output_compression', 'Off'); + } + + // try to flush everything all the time + ob_implicit_flush(true); + + // close all buffers if possible and discard any existing output + // this can actually work around some whitespace problems in config.php + while(ob_get_level()) { + if (!ob_end_clean()) { + // prevent infinite loop when buffer can not be closed + break; + } + } + + error_reporting($olddebug); +} + /** * Check whether a major upgrade is needed. That is defined as an upgrade that * changes something really fundamental in the database, so nothing can possibly diff --git a/mod/chat/gui_header_js/jsupdated.php b/mod/chat/gui_header_js/jsupdated.php index 5c8d0c37a6d06..9a98185f9708f 100644 --- a/mod/chat/gui_header_js/jsupdated.php +++ b/mod/chat/gui_header_js/jsupdated.php @@ -18,6 +18,7 @@ define('CHAT_MAX_CLIENT_UPDATES', 1000); define('NO_MOODLE_COOKIES', true); // session not used here +define('NO_OUTPUT_BUFFERING', true); require('../../../config.php'); require('../lib.php'); @@ -119,7 +120,6 @@ function safari_refresh() { // Ensure the HTML head makes it out there echo $CHAT_DUMMY_DATA; - @ob_end_flush(); for ($n=0; $n <= CHAT_MAX_CLIENT_UPDATES; $n++) { @@ -135,7 +135,6 @@ function safari_refresh() { $chat_newlastid = 0; print " \n"; print $CHAT_DUMMY_DATA; - @ob_end_flush(); sleep($CFG->chat_refresh_room); continue; } @@ -164,7 +163,6 @@ function safari_refresh() { } else { print " \n"; print $CHAT_DUMMY_DATA; - @ob_end_flush(); sleep($CFG->chat_refresh_room); continue; $num = 0; @@ -229,7 +227,6 @@ function safari_refresh() { print ''; } print $CHAT_DUMMY_DATA; - @ob_end_flush(); sleep($CFG->chat_refresh_room); } // here ends the for() loop diff --git a/search/indexer.php b/search/indexer.php index 3a33ef4e4db7f..8f2b9e31c4d3d 100644 --- a/search/indexer.php +++ b/search/indexer.php @@ -30,24 +30,25 @@ /** * includes and requires */ + +define('NO_OUTPUT_BUFFERING', true); + require_once('../config.php'); require_once($CFG->dirroot.'/search/lib.php'); //this'll take some time, set up the environment @set_time_limit(0); -@ob_implicit_flush(true); -@ob_end_flush(); ini_set('include_path', $CFG->dirroot.DIRECTORY_SEPARATOR.'search'.PATH_SEPARATOR.ini_get('include_path')); /// only administrators can index the moodle installation, because access to all pages is required require_login(); - + if (empty($CFG->enableglobalsearch)) { print_error('globalsearchdisabled', 'search'); } - + if (!has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM))) { print_error('beadmin', 'search', get_login_url()); } @@ -55,72 +56,72 @@ /// confirmation flag to prevent accidental reindexing (indexersplash.php is the correct entry point) $sure = strtolower(optional_param('areyousure', '', PARAM_ALPHA)); - + if ($sure != 'yes') { mtrace("
Sorry, you need to confirm indexing via indexersplash.php"
               .". (Back to query page).
"); - + exit(0); } - + /// check for php5 (lib.php) //php5 found, continue including php5-only files //require_once("$CFG->dirroot/search/Zend/Search/Lucene.php"); require_once($CFG->dirroot.'/search/indexlib.php'); - + mtrace(''); mtrace('
Server Time: '.date('r',time())."\n");
-    
+
     if (isset($CFG->search_indexer_busy) && $CFG->search_indexer_busy == '1') {
         //means indexing was not finished previously
         mtrace("Warning: Indexing was not successfully completed last time, restarting.\n");
     }
-    
+
 /// turn on busy flag
 
     set_config('search_indexer_busy', '1');
-    
+
     //paths
     $index_path = SEARCH_INDEX_PATH;
     $index_db_file = "{$CFG->dirroot}/search/db/$CFG->dbtype.sql";
     $dbcontrol = new IndexDBControl();
-    
+
 /// setup directory in data root
 
     if (!file_exists($index_path)) {
         mtrace("Data directory ($index_path) does not exist, attempting to create.");
         if (!mkdir($index_path, $CFG->directorypermissions)) {
             search_pexit("Error creating data directory at: $index_path. Please correct.");
-        } 
+        }
         else {
             mtrace("Directory successfully created.");
-        } 
-    } 
+        }
+    }
     else {
         mtrace("Using {$index_path} as data directory.");
-    } 
-    
+    }
+
     Zend_Search_Lucene_Analysis_Analyzer::setDefault(new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8_CaseInsensitive());
     $index = new Zend_Search_Lucene($index_path, true);
-    
+
 /// New regeneration
 
     mtrace('Deleting old index entries.');
     $DB->delete_records(SEARCH_DATABASE_TABLE);
-    
+
 /// begin timer
 
     search_stopwatch();
     mtrace("Starting activity modules\n");
-    
+
     //the presence of the required search functions -
     // * mod_iterator
     // * mod_get_content_for_index
     //are the sole basis for including a module in the index at the moment.
 
     $searchables = search_collect_searchables();
-    
+
 /// start indexation
 
     if ($searchables){
@@ -131,24 +132,24 @@
             set_config($indexdatestring, time());
             $indexdatestring = 'search_indexer_run_date_'.$mod->name;
             set_config($indexdatestring, time());
-        
+
             mtrace("starting indexing {$mod->name}\n");
-        
+
             $key = 'search_in_'.$mod->name;
             if (isset($CFG->$key) && !$CFG->$key) {
                 mtrace("module $key has been administratively disabled. Skipping...\n");
                 continue;
             }
-        
+
             if ($mod->location == 'internal'){
                 $class_file = $CFG->dirroot.'/search/documents/'.$mod->name.'_document.php';
             } else {
                 $class_file = $CFG->dirroot.'/'.$mod->location.'/'.$mod->name.'/search_document.php';
             }
-            
+
             if (file_exists($class_file)) {
                 include_once($class_file);
-    
+
                 //build function names
                 $iter_function = $mod->name.'_iterator';
                 $index_function = $mod->name.'_get_content_for_index';
@@ -159,7 +160,7 @@
                     if ($sources){
                         foreach ($sources as $i) {
                             $documents = $index_function($i);
-                  
+
                             //begin transaction
                             if ($documents){
                                 foreach($documents as $document) {
@@ -171,27 +172,27 @@
                                     }
                                     //object to insert into db
                                     $dbid = $dbcontrol->addDocument($document);
-                                    
+
                                     //synchronise db with index
                                     $document->addField(Zend_Search_Lucene_Field::Keyword('dbid', $dbid));
-                                    
+
                                     //add document to index
                                     $index->addDocument($document);
-                                    
+
                                     //commit every x new documents, and print a status message
                                     if (($counter % 2000) == 0) {
                                         $index->commit();
                                         mtrace(".. $counter");
-                                    } 
+                                    }
                                 }
                             }
                             //end transaction
                         }
                     }
-            
+
                     //commit left over documents, and finish up
                     $index->commit();
-          
+
                     mtrace("-- $counter documents indexed");
                     mtrace("done.\n");
                 }
@@ -200,19 +201,19 @@
             }
         }
     }
-      
+
 /// finished modules
 
     mtrace('Finished activity modules');
     search_stopwatch();
-        
+
     mtrace(".
Back to query page."); mtrace('
'); - + /// finished, turn busy flag off set_config('search_indexer_busy', '0'); - + /// mark the time we last updated set_config('search_indexer_run_date', time()); diff --git a/search/tests/index.php b/search/tests/index.php index 0fdedffb508c0..594fd6330b30b 100644 --- a/search/tests/index.php +++ b/search/tests/index.php @@ -17,41 +17,40 @@ * @version Moodle 2.0 **/ + define('NO_OUTPUT_BUFFERING', true); require_once('../../config.php'); @set_time_limit(0); - @ob_implicit_flush(true); - @ob_end_flush(); /// makes inclusions of the Zend Engine more reliable ini_set('include_path', $CFG->dirroot.DIRECTORY_SEPARATOR.'search'.PATH_SEPARATOR.ini_get('include_path')); require_once($CFG->dirroot.'/search/lib.php'); require_login(); - + if (empty($CFG->enableglobalsearch)) { print_error('globalsearchdisabled', 'search'); } - + if (!has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM))) { print_error('onlyadmins', 'error', get_login_url()); } mtrace('
Server Time: '.date('r',time()));
     mtrace("Testing global search capabilities:\n");
-    
+
     //fix paths for testing
     set_include_path(get_include_path().":../");
     require_once("$CFG->dirroot/search/Zend/Search/Lucene.php");
-    
+
     mtrace("Checking activity modules:\n");
-    
+
     //the presence of the required search functions -
     // * mod_iterator
     // * mod_get_content_for_index
     //are the sole basis for including a module in the index at the moment.
-    
+
 /// get all installed modules
     if ($mods = $DB->get_records('modules', null, 'name', 'id, name')){
 
@@ -67,11 +66,11 @@
                 if (file_exists($documentfile)){
                     $searchables[] = $mod;
                 }
-            }        
-        }    
+            }
+        }
         mtrace(count($searchables).' modules to search in / '.count($mods).' modules found.');
     }
-      
+
 /// collects blocks as indexable information may be found in blocks either
     if ($blocks = $DB->get_records('block', null, 'name', 'id,name')) {
         $blocks_searchables = array();
@@ -88,18 +87,18 @@
                     $mod->location = 'blocks';
                     $blocks_searchables[] = $block;
                 }
-            }        
-        }    
+            }
+        }
         mtrace(count($blocks_searchables).' blocks to search in / '.count($blocks).' blocks found.');
         $searchables = array_merge($searchables, $blocks_searchables);
     }
-      
+
 /// add virtual modules onto the back of the array
 
     $additional = search_get_additional_modules();
     mtrace(count($additional).' additional to search in.');
     $searchables = array_merge($searchables, $additional);
-    
+
     foreach ($searchables as $mod) {
 
         $key = 'search_in_'.$mod->name;
@@ -113,41 +112,41 @@
         } else {
             $class_file = $CFG->dirroot.'/'.$mod->location.'/'.$mod->name.'/search_document.php';
         }
-    
+
         if (file_exists($class_file)) {
             include_once($class_file);
-    
+
             if ($mod->location != 'internal' && !defined('X_SEARCH_TYPE_'.strtoupper($mod->name))) {
                 mtrace("ERROR: Constant 'X_SEARCH_TYPE_".strtoupper($mod->name)."' is not defined in search/searchtypes.php or in module");
                 continue;
             }
-            
+
             $iter_function = $mod->name.'_iterator';
             $index_function = $mod->name.'_get_content_for_index';
-            
+
             if (function_exists($index_function) && function_exists($iter_function)) {
                 $entries = $iter_function();
                 if (!empty($entries)) {
                     $documents = $index_function(array_pop($entries));
-            
+
                     if (is_array($documents)) {
                         mtrace("Success: '$mod->name' module seems to be ready for indexing.");
                     } else {
                         mtrace("ERROR: $index_function() doesn't seem to be returning an array.");
-                    } 
+                    }
                 } else {
                     mtrace("Success : '$mod->name' has nothing to index.");
-                } 
+                }
             } else {
                 mtrace("ERROR: $iter_function() and/or $index_function() does not exist in $class_file");
-            } 
+            }
         } else {
             mtrace("Notice: $class_file does not exist, this module will not be indexed.");
-        } 
-    } 
-    
+        }
+    }
+
     mtrace("\nFinished checking for searcheable items.");
-        
+
     mtrace("
Back to query page or Start indexing."); mtrace('
'); ?> \ No newline at end of file