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: