1<?php
2// +-----------------------------------------------------------------------+
3// | This file is part of Piwigo.                                          |
4// |                                                                       |
5// | For copyright and license information, please view the COPYING.txt    |
6// | file that was distributed with this source code.                      |
7// +-----------------------------------------------------------------------+
8
9define('PHPWG_ROOT_PATH','./');
10session_cache_limiter('public');
11include_once(PHPWG_ROOT_PATH.'include/common.inc.php');
12
13// Check Access and exit when user status is not ok
14check_status(ACCESS_GUEST);
15
16function guess_mime_type($ext)
17{
18  switch ( strtolower($ext) )
19  {
20    case "jpe": case "jpeg":
21    case "jpg": $ctype="image/jpeg"; break;
22    case "png": $ctype="image/png"; break;
23    case "gif": $ctype="image/gif"; break;
24    case "tiff":
25    case "tif": $ctype="image/tiff"; break;
26    case "txt": $ctype="text/plain"; break;
27    case "html":
28    case "htm": $ctype="text/html"; break;
29    case "xml": $ctype="text/xml"; break;
30    case "pdf": $ctype="application/pdf"; break;
31    case "zip": $ctype="application/zip"; break;
32    case "ogg": $ctype="application/ogg"; break;
33    default: $ctype="application/octet-stream";
34  }
35  return $ctype;
36}
37
38function do_error( $code, $str )
39{
40  set_status_header( $code );
41  echo $str ;
42  exit();
43}
44
45if ($conf['enable_formats'] and isset($_GET['format']))
46{
47  check_input_parameter('format', $_GET, false, PATTERN_ID);
48
49  $query = '
50SELECT
51    *
52  FROM '.IMAGE_FORMAT_TABLE.'
53  WHERE format_id = '.$_GET['format'].'
54;';
55  $formats = query2array($query);
56
57  if (count($formats) == 0)
58  {
59    do_error(400, 'Invalid request - format');
60  }
61
62  $format = $formats[0];
63
64  $_GET['id'] = $format['image_id'];
65  $_GET['part'] = 'f'; // "f" for "format"
66}
67
68
69if (!isset($_GET['id'])
70    or !is_numeric($_GET['id'])
71    or !isset($_GET['part'])
72    or !in_array($_GET['part'], array('e','r','f') ) )
73{
74  do_error(400, 'Invalid request - id/part');
75}
76
77$query = '
78SELECT * FROM '. IMAGES_TABLE.'
79  WHERE id='.$_GET['id'].'
80;';
81
82$element_info = pwg_db_fetch_assoc(pwg_query($query));
83if ( empty($element_info) )
84{
85  do_error(404, 'Requested id not found');
86}
87
88// special download action for admins
89$is_admin_download = false;
90if (is_admin() and isset($_GET['pwg_token']) and get_pwg_token() == $_GET['pwg_token'])
91{
92  $is_admin_download = true;
93  $user['enabled_high'] = true;
94}
95
96$src_image = new SrcImage($element_info);
97
98// $filter['visible_categories'] and $filter['visible_images']
99// are not used because it's not necessary (filter <> restriction)
100$query='
101SELECT id
102  FROM '.CATEGORIES_TABLE.'
103    INNER JOIN '.IMAGE_CATEGORY_TABLE.' ON category_id = id
104  WHERE image_id = '.$_GET['id'].'
105'.get_sql_condition_FandF(
106  array(
107      'forbidden_categories' => 'category_id',
108      'forbidden_images' => 'image_id',
109    ),
110  '    AND'
111  ).'
112  LIMIT 1
113;';
114if (!$is_admin_download and pwg_db_num_rows(pwg_query($query))<1 )
115{
116  do_error(401, 'Access denied');
117}
118
119include_once(PHPWG_ROOT_PATH.'include/functions_picture.inc.php');
120$file='';
121switch ($_GET['part'])
122{
123  case 'e':
124    if ( $src_image->is_original() and !$user['enabled_high'] )
125    {// we have a photo and the user has no access to HD
126      $deriv = new DerivativeImage(IMG_XXLARGE, $src_image);
127      if ( !$deriv->same_as_source() )
128      {
129        do_error(401, 'Access denied e');
130      }
131    }
132    $file = get_element_path($element_info);
133    break;
134  case 'r':
135    $file = original_to_representative( get_element_path($element_info), $element_info['representative_ext'] );
136    break;
137  case 'f' :
138    $file = original_to_format(get_element_path($element_info), $format['ext']);
139    $element_info['file'] = get_filename_wo_extension($element_info['file']).'.'.$format['ext'];
140    break;
141}
142
143if ( empty($file) )
144{
145  do_error(404, 'Requested file not found');
146}
147
148if ($_GET['part'] == 'e') {
149  pwg_log($_GET['id'], 'high');
150}
151else if ($_GET['part'] == 'e')
152{
153  pwg_log($_GET['id'], 'other');
154}
155else if ($_GET['part'] == 'f')
156{
157  pwg_log($_GET['id'], 'high', $format['format_id']);
158}
159
160$http_headers = array();
161
162$ctype = null;
163if (!url_is_remote($file))
164{
165  if ( !@is_readable($file) )
166  {
167    do_error(404, "Requested file not found - $file");
168  }
169  $http_headers[] = 'Content-Length: '.@filesize($file);
170  if ( function_exists('mime_content_type') )
171  {
172    $ctype = mime_content_type($file);
173  }
174
175  $gmt_mtime = gmdate('D, d M Y H:i:s', filemtime($file)).' GMT';
176  $http_headers[] = 'Last-Modified: '.$gmt_mtime;
177
178  // following lines would indicate how the client should handle the cache
179  /* $max_age=300;
180  $http_headers[] = 'Expires: '.gmdate('D, d M Y H:i:s', time()+$max_age).' GMT';
181  // HTTP/1.1 only
182  $http_headers[] = 'Cache-Control: private, must-revalidate, max-age='.$max_age;*/
183
184  if ('f' != $_GET['part'] and isset( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) )
185  {
186    set_status_header(304);
187    foreach ($http_headers as $header)
188    {
189      header( $header );
190    }
191    exit();
192  }
193}
194
195if (!isset($ctype))
196{ // give it a guess
197  $ctype = guess_mime_type( get_extension($file) );
198}
199
200$http_headers[] = 'Content-Type: '.$ctype;
201
202if (isset($_GET['download']))
203{
204  $http_headers[] = 'Content-Disposition: attachment; filename="'.htmlspecialchars_decode($element_info['file']).'";';
205  $http_headers[] = 'Content-Transfer-Encoding: binary';
206}
207else
208{
209  $http_headers[] = 'Content-Disposition: inline; filename="'
210            .basename($file).'";';
211}
212
213foreach ($http_headers as $header)
214{
215  header( $header );
216}
217
218// Looking at the safe_mode configuration for execution time
219if (ini_get('safe_mode') == 0)
220{
221  @set_time_limit(0);
222}
223// Without clean and flush there may be some image download problems, or image can be corrupted after download
224if (ob_get_length() !== FALSE)
225{
226  ob_clean();
227  flush();
228}
229
230@readfile($file);
231
232?>
233