|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* osCommerce Online Merchant |
|
4
|
|
|
* |
|
5
|
|
|
* @copyright (c) 2016 osCommerce; https://www.oscommerce.com |
|
6
|
|
|
* @license MIT; https://www.oscommerce.com/license/mit.txt |
|
7
|
|
|
*/ |
|
8
|
|
|
|
|
9
|
|
|
use OSC\OM\Hash; |
|
10
|
|
|
use OSC\OM\OSCOM; |
|
11
|
|
|
|
|
12
|
|
|
include('includes/application_top.php'); |
|
13
|
|
|
|
|
14
|
|
|
if (!isset($_SESSION['customer_id'])) die; |
|
15
|
|
|
|
|
16
|
|
|
// Check download.php was called with proper GET parameters |
|
17
|
|
|
if ((isset($_GET['order']) && !is_numeric($_GET['order'])) || (isset($_GET['id']) && !is_numeric($_GET['id'])) ) { |
|
18
|
|
|
die; |
|
19
|
|
|
} |
|
20
|
|
|
|
|
21
|
|
|
// Check that order_id, customer_id and filename match |
|
22
|
|
|
$Qdownload = $OSCOM_Db->prepare('select date_format(o.date_purchased, "%Y-%m-%d") as date_purchased_day, opd.download_maxdays, opd.download_count, opd.download_maxdays, opd.orders_products_filename from :table_orders o, :table_orders_products op, :table_orders_products_download opd, :table_orders_status os where o.orders_id = :orders_id and o.customers_id = :customers_id and o.orders_id = op.orders_id and op.orders_products_id = opd.orders_products_id and opd.orders_products_download_id = :orders_products_download_id and opd.orders_products_filename != "" and o.orders_status = os.orders_status_id and os.downloads_flag = "1" and os.language_id = :language_id'); |
|
23
|
|
|
$Qdownload->bindInt(':orders_id', $_GET['order']); |
|
24
|
|
|
$Qdownload->bindInt(':customers_id', $_SESSION['customer_id']); |
|
25
|
|
|
$Qdownload->bindInt(':orders_products_download_id', $_GET['id']); |
|
26
|
|
|
$Qdownload->bindInt(':language_id', $OSCOM_Language->getId()); |
|
27
|
|
|
$Qdownload->execute(); |
|
28
|
|
|
|
|
29
|
|
|
if ($Qdownload->fetch() === false) die; |
|
30
|
|
|
|
|
31
|
|
|
// MySQL 3.22 does not have INTERVAL |
|
32
|
|
|
list($dt_year, $dt_month, $dt_day) = explode('-', $Qdownload->value('date_purchased_day')); |
|
33
|
|
|
$download_timestamp = mktime(23, 59, 59, $dt_month, $dt_day + $Qdownload->valueInt('download_maxdays'), $dt_year); |
|
34
|
|
|
|
|
35
|
|
|
// Die if time expired (maxdays = 0 means no time limit) |
|
36
|
|
|
if (($Qdownload->valueInt('download_maxdays') != 0) && ($download_timestamp <= time())) die; |
|
37
|
|
|
// Die if remaining count is <=0 |
|
38
|
|
|
if ($Qdownload->valueInt('download_count') <= 0) die; |
|
39
|
|
|
// Die if file is not there |
|
40
|
|
|
if (!is_file(OSCOM::getConfig('dir_root') . 'download/' . $Qdownload->value('orders_products_filename'))) die; |
|
41
|
|
|
|
|
42
|
|
|
// Now decrement counter |
|
43
|
|
|
$Qupdate = $OSCOM_Db->prepare('update :table_orders_products_download set download_count = download_count-1 where orders_products_download_id = :orders_products_download_id'); |
|
44
|
|
|
$Qupdate->bindInt(':orders_products_download_id', $_GET['id']); |
|
45
|
|
|
$Qupdate->execute(); |
|
46
|
|
|
|
|
47
|
|
|
// Returns a random name, 16 to 20 characters long |
|
48
|
|
|
// There are more than 10^28 combinations |
|
49
|
|
|
// The directory is "hidden", i.e. starts with '.' |
|
50
|
|
|
function tep_random_name() |
|
51
|
|
|
{ |
|
52
|
|
|
$letters = 'abcdefghijklmnopqrstuvwxyz'; |
|
53
|
|
|
$dirname = '.'; |
|
54
|
|
|
$length = floor(Hash::getRandomInt(16, 20)); |
|
55
|
|
|
for ($i = 1; $i <= $length; $i++) { |
|
56
|
|
|
$q = floor(Hash::getRandomInt(1, 26)); |
|
57
|
|
|
$dirname .= $letters[$q]; |
|
58
|
|
|
} |
|
59
|
|
|
return $dirname; |
|
60
|
|
|
} |
|
61
|
|
|
|
|
62
|
|
|
// Unlinks all subdirectories and files in $dir |
|
63
|
|
|
// Works only on one subdir level, will not recurse |
|
64
|
|
|
function tep_unlink_temp_dir($dir) |
|
65
|
|
|
{ |
|
66
|
|
|
$h1 = opendir($dir); |
|
67
|
|
|
while ($subdir = readdir($h1)) { |
|
68
|
|
|
// Ignore non directories |
|
69
|
|
|
if (!is_dir($dir . $subdir)) continue; |
|
70
|
|
|
// Ignore . and .. and CVS |
|
71
|
|
|
if ($subdir == '.' || $subdir == '..' || $subdir == 'CVS') continue; |
|
72
|
|
|
// Loop and unlink files in subdirectory |
|
73
|
|
|
$h2 = opendir($dir . $subdir); |
|
74
|
|
|
while ($file = readdir($h2)) { |
|
75
|
|
|
if ($file == '.' || $file == '..') continue; |
|
76
|
|
|
@unlink($dir . $subdir . '/' . $file); |
|
|
|
|
|
|
77
|
|
|
} |
|
78
|
|
|
closedir($h2); |
|
79
|
|
|
@rmdir($dir . $subdir); |
|
|
|
|
|
|
80
|
|
|
} |
|
81
|
|
|
closedir($h1); |
|
82
|
|
|
} |
|
83
|
|
|
|
|
84
|
|
|
|
|
85
|
|
|
// Now send the file with header() magic |
|
86
|
|
|
header("Expires: Mon, 26 Nov 1962 00:00:00 GMT"); |
|
87
|
|
|
header("Last-Modified: " . gmdate("D,d M Y H:i:s") . " GMT"); |
|
88
|
|
|
header("Cache-Control: no-cache, must-revalidate"); |
|
89
|
|
|
header("Pragma: no-cache"); |
|
90
|
|
|
header("Content-Type: Application/octet-stream"); |
|
91
|
|
|
header("Content-disposition: attachment; filename=" . $Qdownload->value('orders_products_filename')); |
|
92
|
|
|
|
|
93
|
|
|
if (DOWNLOAD_BY_REDIRECT == 'true') { |
|
94
|
|
|
// This will work only on Unix/Linux hosts |
|
95
|
|
|
tep_unlink_temp_dir(OSCOM::getConfig('dir_root') . 'pub/'); |
|
96
|
|
|
$tempdir = tep_random_name(); |
|
97
|
|
|
umask(0000); |
|
98
|
|
|
mkdir(OSCOM::getConfig('dir_root') . 'pub/' . $tempdir, 0777); |
|
99
|
|
|
symlink(OSCOM::getConfig('dir_root') . 'download/' . $Qdownload->value('orders_products_filename'), OSCOM::getConfig('dir_root', 'Shop') . 'pub/' . $tempdir . '/' . $Qdownload->value('orders_products_filename')); |
|
100
|
|
|
if (is_file(OSCOM::getConfig('dir_root') . 'pub/' . $tempdir . '/' . $Qdownload->value('orders_products_filename'))) { |
|
101
|
|
|
OSCOM::redirect('pub/' . $tempdir . '/' . $Qdownload->value('orders_products_filename')); |
|
102
|
|
|
} |
|
103
|
|
|
} |
|
104
|
|
|
|
|
105
|
|
|
// Fallback to readfile() delivery method. This will work on all systems, but will need considerable resources |
|
106
|
|
|
readfile(OSCOM::getConfig('dir_root') . 'download/' . $Qdownload->value('orders_products_filename')); |
|
107
|
|
|
?> |
|
|
|
|
|
|
108
|
|
|
|
If you suppress an error, we recommend checking for the error condition explicitly: