function _uc_file_download_transfer in Ubercart 7.3
Same name and namespace in other branches
- 6.2 uc_file/uc_file.pages.inc \_uc_file_download_transfer()
Sends the file's binary data to a user via HTTP and updates the database.
Parameters
$file_user: The file_user object from the uc_file_users.
$ip: The string containing the IP address the download is going to.
1 call to _uc_file_download_transfer()
- _uc_file_download in uc_file/
uc_file.pages.inc - Handles file downloading and error states.
File
- uc_file/
uc_file.pages.inc, line 320 - File menu items.
Code
function _uc_file_download_transfer($file_user, $ip) {
// Check if any hook_uc_file_transfer_alter() calls alter the download.
foreach (module_implements('uc_file_transfer_alter') as $module) {
$name = $module . '_uc_file_transfer_alter';
$file_user->full_path = $name($file_user, $ip, $file_user->fid, $file_user->full_path);
}
// This could get clobbered, so make a copy.
$filename = $file_user->filename;
// Gather relevant info about the file.
$size = filesize($file_user->full_path);
$mimetype = file_get_mimetype($filename);
// Workaround for IE filename bug with multiple periods / multiple dots
// in filename that adds square brackets to filename -
// eg. setup.abc.exe becomes setup[1].abc.exe
if (strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE')) {
$filename = preg_replace('/\\./', '%2e', $filename, substr_count($filename, '.') - 1);
}
// Check if HTTP_RANGE is sent by browser (or download manager).
$range = NULL;
if (isset($_SERVER['HTTP_RANGE'])) {
if (substr($_SERVER['HTTP_RANGE'], 0, 6) == 'bytes=') {
// Multiple ranges could be specified at the same time,
// but for simplicity only serve the first range
// See http://tools.ietf.org/id/draft-ietf-http-range-retrieval-00.txt
list($range, $extra_ranges) = explode(',', substr($_SERVER['HTTP_RANGE'], 6), 2);
}
else {
drupal_add_http_header('Status', '416 Requested Range Not Satisfiable');
drupal_add_http_header('Content-Range', 'bytes */' . $size);
exit;
}
}
// Figure out download piece from range (if set).
if (isset($range)) {
list($seek_start, $seek_end) = explode('-', $range, 2);
}
// Set start and end based on range (if set),
// else set defaults and check for invalid ranges.
$seek_end = intval(empty($seek_end) ? $size - 1 : min(abs(intval($seek_end)), $size - 1));
$seek_start = intval(empty($seek_start) || $seek_end < abs(intval($seek_start)) ? 0 : max(abs(intval($seek_start)), 0));
// Only send partial content header if downloading a piece of the file (IE
// workaround).
if ($seek_start > 0 || $seek_end < $size - 1) {
drupal_add_http_header('Status', '206 Partial Content');
}
// Standard headers, including content-range and length.
drupal_add_http_header('Pragma', 'public');
drupal_add_http_header('Cache-Control', 'cache, must-revalidate');
drupal_add_http_header('Accept-Ranges', 'bytes');
drupal_add_http_header('Content-Range', 'bytes ' . $seek_start . '-' . $seek_end . '/' . $size);
drupal_add_http_header('Content-Type', $mimetype);
drupal_add_http_header('Content-Disposition', 'attachment; filename="' . $filename . '"');
drupal_add_http_header('Content-Length', $seek_end - $seek_start + 1);
// Last-Modified is required for content served dynamically.
drupal_add_http_header('Last-Modified', gmdate("D, d M Y H:i:s", filemtime($file_user->full_path)) . " GMT");
// Etag header is required for Firefox3 and other managers.
drupal_add_http_header('ETag', md5($file_user->full_path));
// Open the file and seek to starting byte.
$fp = fopen($file_user->full_path, 'rb');
fseek($fp, $seek_start);
// Start buffered download.
while (!feof($fp)) {
// Reset time limit for large files.
drupal_set_time_limit(0);
// Push the data to the client.
print fread($fp, UC_FILE_BYTE_SIZE);
flush();
// Suppress PHP notice that occurs when output buffering isn't enabled.
// The ob_flush() is needed because if output buffering *is* enabled,
// clicking on the file download link won't download anything if the buffer
// isn't flushed.
@ob_flush();
}
// Finished serving the file, close the stream and log the download
// to the user table.
fclose($fp);
_uc_file_log_download($file_user, $ip);
}