diff --git a/file.php b/file.php index 0e18cb55eb4cc..3efd77d18f750 100644 --- a/file.php +++ b/file.php @@ -1,6 +1,7 @@ = 3) + and (strtolower($args[1]) == 'moddata') + and ((strtolower($args[2]) == 'forum') + or (strtolower($args[2]) == 'assignment') + or (strtolower($args[2]) == 'glossary') + or (strtolower($args[2]) == 'wiki') + or (strtolower($args[2]) == 'exercise') + or (strtolower($args[2]) == 'workshop') + )) { + $forcedownload = 1; // force download of all attachments + } + // security: some protection of hidden resource files // warning: it may break backwards compatibility - // TODO: case sensitive in PostgresQL, case insensitive in MySQL (ok?) - // TODO: should we protect directories too? if ((!empty($CFG->preventaccesstohiddenfiles)) and (count($args) >= 2) and (!isteacher($course->id))) { @@ -131,7 +144,7 @@ // ======================================== session_write_close(); // unlock session during fileserving $filename = $args[count($args)-1]; - send_file($pathname, $filename, $lifetime, !empty($CFG->filteruploadedfiles)); + send_file($pathname, $filename, $lifetime, !empty($CFG->filteruploadedfiles), false, $forcedownload); function not_found($courseid) { global $CFG; diff --git a/lib/filelib.php b/lib/filelib.php index 9ead6508d8a69..98ec01c2daa84 100644 --- a/lib/filelib.php +++ b/lib/filelib.php @@ -136,26 +136,37 @@ function mimeinfo($element, $filename) { } } -function send_file($path, $filename, $lifetime=86400 , $filter=false, $pathisstring=false) { +function send_file($path, $filename, $lifetime=86400 , $filter=false, $pathisstring=false,$forcedownload=false) { - $mimetype = mimeinfo('type', $filename); + $mimetype = $forcedownload ? 'application/force-download' : mimeinfo('type', $filename); $lastmodified = $pathisstring ? time() : filemtime($path); $filesize = $pathisstring ? strlen($path) : filesize($path); + //IE compatibiltiy HACK! + if(ini_get('zlib.output_compression')) { + ini_set('zlib.output_compression', 'Off'); + } + @header('Last-Modified: '. gmdate('D, d M Y H:i:s', $lastmodified) .' GMT'); if ($lifetime > 0) { @header('Cache-control: max-age='.$lifetime); @header('Expires: '. gmdate('D, d M Y H:i:s', time() + $lifetime) .'GMT'); @header('Pragma: '); } else { - // this part is tricky, displaying of MS Office documents in IE needs - // to store the file on disk, but no-cache may prevent it + // This part is tricky, displaying of MS Office documents in IE needs + // to store the file on disk, but no-cache may prevent it. + // HTTPS:// sites might have problems with following code in IE, tweak it yourself if needed ;-) @header('Cache-Control: private, must-revalidate, pre-check=0, post-check=0, max-age=10'); @header('Expires: '. gmdate('D, d M Y H:i:s', 0) .'GMT'); @header('Pragma: no-cache'); } - @header('Accept-Ranges: none'); // PDF compatibility - @header('Content-disposition: inline; filename='.$filename); + @header('Accept-Ranges: none'); // Comment out if PDFs do not work... + + if ($forcedownload) { + @header('Content-disposition: attachment; filename='.$filename); + } else { + @header('Content-disposition: inline; filename='.$filename); + } if (!$filter) { @header('Content-length: '.$filesize); @@ -167,7 +178,7 @@ function send_file($path, $filename, $lifetime=86400 , $filter=false, $pathisstr if ($pathisstring) { echo $path; }else { - readfile($path); + readfile_chunked($path); } } else { // Try to put the file through filters global $course; // HACK! @@ -199,7 +210,7 @@ function send_file($path, $filename, $lifetime=86400 , $filter=false, $pathisstr if ($pathisstring) { echo $path; }else { - readfile($path); + readfile_chunked($path); } } } @@ -344,5 +355,27 @@ function fulldelete($location) { return true; } +function readfile_chunked($filename,$retbytes=true) { + $chunksize = 1*(1024*1024); // 1MB chunks + $buffer = ''; + $cnt =0;// $handle = fopen($filename, 'rb'); + $handle = fopen($filename, 'rb'); + if ($handle === false) { + return false; + } + + while (!feof($handle)) { + $buffer = fread($handle, $chunksize); + echo $buffer; + if ($retbytes) { + $cnt += strlen($buffer);} + } + $status = fclose($handle); + if ($retbytes && $status) { + return $cnt; // return num. bytes delivered like readfile() does. + } + return $status; +} + ?>