| 93 | | |
| 94 | | header("Cache-Control: "); |
| 95 | | header("Pragma: "); |
| 96 | | header("Content-Type: application/octet-stream"); |
| 97 | | header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); |
| 98 | | |
| 99 | | header("Content-Length: " .(string)($file_obj->file_size)); |
| 100 | | header('Content-Disposition: attachment; filename="'.$filename.'"'); |
| 101 | | header("Content-Transfer-Encoding: binary\n"); |
| 102 | | |
| 103 | | fpassthru($fp); |
| | 93 | |
| | 94 | // Support for broken downloads resuming via parsing 'Range' header value. Made by X-[Vr]bL1s5. |
| | 95 | // This addition will ONLY work if PHP is run as Apache module and PHP >= 4.3.0 |
| | 96 | if (function_exists('apache_request_headers')) { // check if we run as Apache module. |
| | 97 | $fr_buffer_size = 8192; |
| | 98 | |
| | 99 | $fr_headers = apache_request_headers(); |
| | 100 | if (isset($fr_headers['Range'])) { |
| | 101 | $fr_range_header = trim($fr_headers['Range']); |
| | 102 | $fr_range_header = str_replace('bytes=', '', $fr_range_header); |
| | 103 | $fr_range = explode ('-', $fr_range_header); |
| | 104 | if (isset($fr_range[0]) && ($fr_range[0] != NULL)) { |
| | 105 | if (!is_numeric($fr_range[0])) return $this->stop('msg_not_permitted_download'); // invalid header values |
| | 106 | $fr_range_begin = $fr_range[0]; |
| | 107 | if ((int) ($fr_range_begin) < 0) $fr_range_begin = 0; |
| | 108 | } else { |
| | 109 | $fr_range_begin = 0; |
| | 110 | } |
| | 111 | if (isset($fr_range[1]) && ($fr_range[1] != NULL)) { |
| | 112 | if (!is_numeric($fr_range[1])) return $this->stop('msg_not_permitted_download'); // invalid header values |
| | 113 | $fr_range_end = $fr_range[1]; |
| | 114 | if ((int) ($fr_range_end) > ($file_obj->file_size - 1)) $fr_range_end = $file_obj->file_size - 1; |
| | 115 | } else { |
| | 116 | $fr_range_end = $file_obj->file_size - 1; |
| | 117 | } |
| | 118 | |
| | 119 | $fr_content_length = $fr_range_end - $fr_range_begin + 1; |
| | 120 | |
| | 121 | header("HTTP/1.1 206 Partial Content"); // oh... maybe HTTP proto version will change... ^^; |
| | 122 | header("Cache-Control: no-cache"); |
| | 123 | header("Pragma: no-cache"); |
| | 124 | |
| | 125 | header("Accept-Ranges: bytes"); |
| | 126 | header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); |
| | 127 | header("Content-Type: application/octet-stream"); |
| | 128 | header('Content-Disposition: attachment; filename="'.$filename.'"'); |
| | 129 | |
| | 130 | header("Content-Length: $fr_content_length"); |
| | 131 | header("Content-Range: bytes $fr_range_begin-$fr_range_end/" .(string)($file_obj->file_size)); |
| | 132 | header("Content-Transfer-Encoding: binary"); |
| | 133 | |
| | 134 | $fr_bytes_read = 0; |
| | 135 | |
| | 136 | if (fseek($fp, $fr_range_begin) != 0) return $this->stop('msg_not_permitted_download'); // unable to seek file. |
| | 137 | |
| | 138 | while (!feof($fp)) { |
| | 139 | $fr_buffer = fread($fp, $fr_buffer_size); |
| | 140 | $fr_bytes_read += strlen($fr_buffer); |
| | 141 | if ($fr_content_length > $fr_bytes_read) { |
| | 142 | echo $fr_buffer; |
| | 143 | } else { |
| | 144 | $fr_buffer = substr($fr_buffer, 0, strlen($fr_buffer) - ($fr_bytes_read - $fr_content_length)); |
| | 145 | echo $fr_buffer; |
| | 146 | break; |
| | 147 | } |
| | 148 | } |
| | 149 | } else { |
| | 150 | header("HTTP/1.1 200 OK"); // oh... maybe HTTP proto version will change... ^^; |
| | 151 | header("Cache-Control: no-cache"); |
| | 152 | header("Pragma: no-cache"); |
| | 153 | header("Accept-Ranges: bytes"); // we should claim that we accept ranges! |
| | 154 | header("Content-Type: application/octet-stream"); |
| | 155 | header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); |
| | 156 | |
| | 157 | header("Content-Length: " .(string)($file_obj->file_size)); |
| | 158 | header('Content-Disposition: attachment; filename="'.$filename.'"'); |
| | 159 | header("Content-Transfer-Encoding: binary"); |
| | 160 | |
| | 161 | fpassthru($fp); |
| | 162 | } |
| | 163 | } else { // end of the support... |
| | 164 | |
| | 165 | header("Cache-Control: no-cache"); // originally here it these lines were empty headers like "Cache-Control: ". I don't know why... but it might break the standards. // X-[Vr]bL1s5 |
| | 166 | header("Pragma: no-cache"); // here too |
| | 167 | header("Content-Type: application/octet-stream"); |
| | 168 | header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); |
| | 169 | |
| | 170 | header("Content-Length: " .(string)($file_obj->file_size)); |
| | 171 | header('Content-Disposition: attachment; filename="'.$filename.'"'); |
| | 172 | header("Content-Transfer-Encoding: binary"); |
| | 173 | |
| | 174 | fpassthru($fp); |
| | 175 | } |