source: extensions/derivatives/i.php @ 12778

Last change on this file since 12778 was 12778, checked in by rvelices, 9 years ago

derivatives

  • better status codes + http headers on i.php
  • automatically switch to script mode, regenerate and reload derivatives on demand if their parameters change (without the need to clear the cache)
File size: 7.5 KB
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | Piwigo - a PHP based photo gallery                                    |
4// +-----------------------------------------------------------------------+
5// | Copyright(C) 2008-2012 Piwigo Team                  http://piwigo.org |
6// +-----------------------------------------------------------------------+
7// | This program is free software; you can redistribute it and/or modify  |
8// | it under the terms of the GNU General Public License as published by  |
9// | the Free Software Foundation                                          |
10// |                                                                       |
11// | This program is distributed in the hope that it will be useful, but   |
12// | WITHOUT ANY WARRANTY; without even the implied warranty of            |
13// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
14// | General Public License for more details.                              |
15// |                                                                       |
16// | You should have received a copy of the GNU General Public License     |
17// | along with this program; if not, write to the Free Software           |
18// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
19// | USA.                                                                  |
20// +-----------------------------------------------------------------------+
21
22defined('PHPWG_ROOT_PATH') || die('hacking');
23
24// fast bootstrap - no db connection
25$prefixeTable = 'toto';
26include(PHPWG_ROOT_PATH . 'include/config_default.inc.php');
27@include(PHPWG_ROOT_PATH. 'local/config/config.inc.php');
28
29defined('PWG_LOCAL_DIR') or define('PWG_LOCAL_DIR', 'local/');
30defined('PWG_DERIVATIVE_DIR') or define('PWG_DERIVATIVE_DIR', PWG_LOCAL_DIR.'i/');
31
32function trigger_action() {}
33function get_extension( $filename )
34{
35  return substr( strrchr( $filename, '.' ), 1, strlen ( $filename ) );
36}
37
38function mkgetdir($dir)
39{
40  if ( !is_dir($dir) )
41  {
42    if (substr(PHP_OS, 0, 3) == 'WIN')
43    {
44      $dir = str_replace('/', DIRECTORY_SEPARATOR, $dir);
45    }
46    $umask = umask(0);
47    $mkd = @mkdir($dir, 0755, true);
48    umask($umask);
49    if ($mkd==false)
50    {
51      return false;
52    }
53
54    $file = $dir.'/index.htm';
55    file_exists($file) or @file_put_contents( $file, 'Not allowed!' );
56  }
57  if ( !is_writable($dir) )
58  {
59    return false;
60  }
61  return true;
62}
63
64// end fast bootstrap
65
66
67function ierror($msg, $code)
68{
69  if ($code==301 || $code==302)
70  {
71    if (ob_get_length () !== FALSE)
72    {
73      ob_clean();
74    }
75    // default url is on html format
76    $url = html_entity_decode($msg);
77    header('Request-URI: '.$url);
78    header('Content-Location: '.$url);
79    header('Location: '.$url);
80    exit;
81  }
82  if ($code>=400)
83  {
84    $protocol = $_SERVER["SERVER_PROTOCOL"];
85    if ( ('HTTP/1.1' != $protocol) && ('HTTP/1.0' != $protocol) )
86      $protocol = 'HTTP/1.0';
87
88    header( "$protocol $code $msg", true, $code );
89  }
90  //todo improve
91  echo $msg;
92  exit;
93}
94
95
96function parse_request()
97{
98  global $conf, $page;
99
100  if ( $conf['question_mark_in_urls']==false and
101       isset($_SERVER["PATH_INFO"]) and !empty($_SERVER["PATH_INFO"]) )
102  {
103    $req = $_SERVER["PATH_INFO"];
104    $req = str_replace('//', '/', $req);
105    $path_count = count( explode('/', $req) );
106    $page['root_path'] = PHPWG_ROOT_PATH.str_repeat('../', $path_count-1);
107  }
108  else
109  {
110    $req = $_SERVER["QUERY_STRING"];
111    /*foreach (array_keys($_GET) as $keynum => $key)
112    {
113      $req = $key;
114      break;
115    }*/
116    $page['root_path'] = PHPWG_ROOT_PATH;
117  }
118
119  $req = ltrim($req, '/');
120  !preg_match('#[^a-zA-Z0-9/_.-]#', $req) or ierror('Invalid chars in request', 400);
121
122  $page['derivative_path'] = PHPWG_ROOT_PATH.PWG_DERIVATIVE_DIR.$req;
123 
124  $pos = strrpos($req, '.');
125  $pos!== false || ierror('Missing .', 400);
126  $ext = substr($req, $pos);
127  $req = substr($req, 0, $pos);
128
129  $pos = strrpos($req, '-');
130  $pos!== false || ierror('Missing -', 400);
131  $deriv = substr($req, $pos+1);
132  $req = substr($req, 0, $pos);
133
134  $deriv = explode('_', $deriv);
135  foreach (ImageStdParams::get_defined_type_map() as $type => $params)
136  {
137    if (substr($type,0,2) == $deriv[0])
138    {
139      $page['derivative_type'] = $type;
140      $page['derivative_params'] = $params;
141      break;
142    }
143  }
144
145  if (!isset($page['derivative_type']))
146  {
147    if (substr(IMG_CUSTOM,0,2) == $deriv[0])
148    {
149      $page['derivative_type'] = IMG_CUSTOM;
150    }
151    else
152    {
153      ierror('Unknown parsing type', 400);
154    }
155  }
156  array_shift($deriv);
157 
158  $page['coi'] = '';
159  if (count($deriv) && $deriv[0][0]=='c' && $deriv[0][1]=='i')
160  {
161    $page['coi'] = substr(array_shift($deriv), 2);
162    preg_match('#^[a-z]{4}$#', $page['coi']) or ierror('Invalid center of interest', 400);
163  }
164 
165  if ($page['derivative_type'] == IMG_CUSTOM)
166  {
167    try
168    {
169      $page['derivative_params'] = ImageParams::from_url_tokens($deriv);
170    }
171    catch (Exception $e)
172    {
173      ierror($e->getMessage(), 400);
174    }
175  }
176 
177  if ($req[0]!='g' && $req[0]!='u')
178    $req = '../'.$req;
179   
180  $page['src_location'] = $req.$ext;
181  $page['src_path'] = PHPWG_ROOT_PATH.$page['src_location'];
182  $page['src_url'] = $page['root_path'].$page['src_location'];
183}
184
185
186
187$page=array();
188
189
190include_once( dirname(__FILE__).'/include/derivative_params.inc.php');
191include_once( dirname(__FILE__).'/include/derivative_std_params.inc.php');
192ImageStdParams::load_from_file();
193
194
195parse_request();
196//var_export($page);
197
198$params = $page['derivative_params'];
199if ($params->sizing->ideal_size[0] < 20 or $params->sizing->ideal_size[1] < 20)
200{
201  ierror('Invalid size', 400);
202}
203if ($params->sizing->max_crop < 0 or $params->sizing->max_crop > 1)
204{
205  ierror('Invalid crop', 400);
206}
207
208$src_mtime = @filemtime($page['src_path']);
209if ($src_mtime === false)
210{
211  ierror('Source not found', 404);
212}
213
214$need_generate = false;
215$derivative_mtime = @filemtime($page['derivative_path']);
216if ($derivative_mtime === false or
217    $derivative_mtime < $src_mtime or
218    $derivative_mtime < $params->last_mod_time)
219{
220  $need_generate = true;
221}
222
223if (!$need_generate)
224{
225  if ( isset( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) 
226    and strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $derivative_mtime)
227  {// send the last mod time of the file back
228    header('Last-Modified: '.gmdate('D, d M Y H:i:s', $derivative_mtime).' GMT', true, 304);
229    header('Expires: '.gmdate('D, d M Y H:i:s', time()+10*24*3600).' GMT', true, 304);
230    exit;
231  }
232  // todo send pass-through
233}
234
235
236include_once(PHPWG_ROOT_PATH . 'admin/include/image.class.php');
237$image = new pwg_image($page['src_path']);
238
239if (!mkgetdir(dirname($page['derivative_path'])))
240{
241  ierror("dir create error", 500);
242}
243
244$changes = 0;
245
246// todo rotate
247
248// Crop & scale
249$params->sizing->compute( array($image->get_width(),$image->get_height()), $page['coi'], $crop_rect, $scale_width );
250if ($crop_rect)
251{
252  $changes++;
253  $image->crop( $crop_rect->width(), $crop_rect->height(), $crop_rect->l, $crop_rect->t);
254}
255
256if ($scale_width)
257{
258  $changes++;
259  $image->resize( $scale_width[0], $scale_width[1] );
260}
261
262// no change required - redirect to source
263if (!$changes)
264{
265  header("X-i: No change");
266  ierror( $page['src_url'], 301);
267}
268
269$image->write( $page['derivative_path'] );
270$image->destroy();
271
272$fp = fopen($page['derivative_path'], 'rb');
273
274$fstat = fstat($fp);
275header('Last-Modified: '.gmdate('D, d M Y H:i:s', $fstat['mtime']).' GMT');
276header('Expires: '.gmdate('D, d M Y H:i:s', time()+10*24*3600).' GMT');
277header('Content-length: '.$fstat['size']);
278header('Connection: close');
279
280// todo send the right headers
281header("Content-Type: image/jpeg");
282
283fpassthru($fp);
284exit;
285?>
Note: See TracBrowser for help on using the repository browser.