source: trunk/admin/include/functions_upload.inc.php @ 12831

Last change on this file since 12831 was 12831, checked in by rvelices, 12 years ago

feature 2548 multisize

  • rewrote local site sync + metadata sync
File size: 17.4 KB
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | Piwigo - a PHP based photo gallery                                    |
4// +-----------------------------------------------------------------------+
5// | Copyright(C) 2008-2011 Piwigo Team                  http://piwigo.org |
6// | Copyright(C) 2003-2008 PhpWebGallery Team    http://phpwebgallery.net |
7// | Copyright(C) 2002-2003 Pierrick LE GALL   http://le-gall.net/pierrick |
8// +-----------------------------------------------------------------------+
9// | This program is free software; you can redistribute it and/or modify  |
10// | it under the terms of the GNU General Public License as published by  |
11// | the Free Software Foundation                                          |
12// |                                                                       |
13// | This program is distributed in the hope that it will be useful, but   |
14// | WITHOUT ANY WARRANTY; without even the implied warranty of            |
15// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
16// | General Public License for more details.                              |
17// |                                                                       |
18// | You should have received a copy of the GNU General Public License     |
19// | along with this program; if not, write to the Free Software           |
20// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
21// | USA.                                                                  |
22// +-----------------------------------------------------------------------+
23
24include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
25include_once(PHPWG_ROOT_PATH.'admin/include/image.class.php');
26
27// add default event handler for image and thumbnail resize
28add_event_handler('upload_image_resize', 'pwg_image_resize', EVENT_HANDLER_PRIORITY_NEUTRAL, 7);
29add_event_handler('upload_thumbnail_resize', 'pwg_image_resize', EVENT_HANDLER_PRIORITY_NEUTRAL, 9);
30
31function get_upload_form_config()
32{
33  // default configuration for upload
34  $upload_form_config = array(
35    'websize_resize' => array(
36      'default' => true,
37      'can_be_null' => false,
38      ),
39   
40    'websize_maxwidth' => array(
41      'default' => 800,
42      'min' => 100,
43      'max' => 1600,
44      'pattern' => '/^\d+$/',
45      'can_be_null' => true,
46      'error_message' => l10n('The websize maximum width must be a number between %d and %d'),
47      ),
48 
49    'websize_maxheight' => array(
50      'default' => 600,
51      'min' => 100,
52      'max' => 1200,
53      'pattern' => '/^\d+$/',
54      'can_be_null' => true,
55      'error_message' => l10n('The websize maximum height must be a number between %d and %d'),
56      ),
57 
58    'websize_quality' => array(
59      'default' => 95,
60      'min' => 50,
61      'max' => 100,
62      'pattern' => '/^\d+$/',
63      'can_be_null' => false,
64      'error_message' => l10n('The websize image quality must be a number between %d and %d'),
65      ),
66 
67    'thumb_maxwidth' => array(
68      'default' => 128,
69      'min' => 50,
70      'max' => 300,
71      'pattern' => '/^\d+$/',
72      'can_be_null' => false,
73      'error_message' => l10n('The thumbnail maximum width must be a number between %d and %d'),
74      ),
75 
76    'thumb_maxheight' => array(
77      'default' => 96,
78      'min' => 50,
79      'max' => 300,
80      'pattern' => '/^\d+$/',
81      'can_be_null' => false,
82      'error_message' => l10n('The thumbnail maximum height must be a number between %d and %d'),
83      ),
84 
85    'thumb_quality' => array(
86      'default' => 95,
87      'min' => 50,
88      'max' => 100,
89      'pattern' => '/^\d+$/',
90      'can_be_null' => false,
91      'error_message' => l10n('The thumbnail image quality must be a number between %d and %d'),
92      ),
93
94    'thumb_crop' => array(
95      'default' => false,
96      'can_be_null' => false,
97      ),
98
99    'thumb_follow_orientation' => array(
100      'default' => true,
101      'can_be_null' => false,
102      ),
103 
104    'hd_keep' => array(
105      'default' => true,
106      'can_be_null' => false,
107      ),
108 
109    'hd_resize' => array(
110      'default' => false,
111      'can_be_null' => false,
112      ),
113 
114    'hd_maxwidth' => array(
115      'default' => 2000,
116      'min' => 500,
117      'max' => 20000,
118      'pattern' => '/^\d+$/',
119      'can_be_null' => false,
120      'error_message' => l10n('The high definition maximum width must be a number between %d and %d'),
121      ),
122 
123    'hd_maxheight' => array(
124      'default' => 2000,
125      'min' => 500,
126      'max' => 20000,
127      'pattern' => '/^\d+$/',
128      'can_be_null' => false,
129      'error_message' => l10n('The high definition maximum height must be a number between %d and %d'),
130      ),
131 
132    'hd_quality' => array(
133      'default' => 95,
134      'min' => 50,
135      'max' => 100,
136      'pattern' => '/^\d+$/',
137      'can_be_null' => false,
138      'error_message' => l10n('The high definition image quality must be a number between %d and %d'),
139      ),
140    );
141
142  return $upload_form_config;
143}
144
145function save_upload_form_config($data, &$errors=array())
146{
147  if (!is_array($data) or empty($data))
148  {
149    return false;
150  }
151
152  $upload_form_config = get_upload_form_config();
153  $updates = array();
154
155  foreach ($data as $field => $value)
156  {
157    if (!isset($upload_form_config[$field]))
158    {
159      continue;
160    }
161    if (is_bool($upload_form_config[$field]['default']))
162    {
163      if (isset($value))
164      {
165        $value = true;
166      }
167      else
168      {
169        $value = false;
170      }
171
172      $updates[] = array(
173        'param' => 'upload_form_'.$field,
174        'value' => boolean_to_string($value)
175        );
176    }
177    elseif ($upload_form_config[$field]['can_be_null'] and empty($value))
178    {
179      $updates[] = array(
180        'param' => 'upload_form_'.$field,
181        'value' => 'false'
182        );
183    }
184    else
185    {
186      $min = $upload_form_config[$field]['min'];
187      $max = $upload_form_config[$field]['max'];
188      $pattern = $upload_form_config[$field]['pattern'];
189     
190      if (preg_match($pattern, $value) and $value >= $min and $value <= $max)
191      {
192         $updates[] = array(
193          'param' => 'upload_form_'.$field,
194          'value' => $value
195          );
196      }
197      else
198      {
199        array_push(
200          $errors,
201          sprintf(
202            $upload_form_config[$field]['error_message'],
203            $min,
204            $max
205            )
206          );
207      }
208    }
209  }
210
211  if (count($errors) == 0)
212  {
213    mass_updates(
214      CONFIG_TABLE,
215      array(
216        'primary' => array('param'),
217        'update' => array('value')
218        ),
219      $updates
220      );
221    return true;
222  }
223
224  return false;
225}
226
227function add_uploaded_file($source_filepath, $original_filename=null, $categories=null, $level=null, $image_id=null)
228{
229  // Here is the plan
230  //
231  // 1) move uploaded file to upload/2010/01/22/20100122003814-449ada00.jpg
232  //
233  // 2) if taller than max_height or wider than max_width, move to pwg_high
234  //    + web sized creation
235  //
236  // 3) thumbnail creation from web sized
237  //
238  // 4) register in database
239 
240  // TODO
241  // * check md5sum (already exists?)
242 
243  global $conf, $user;
244
245  $md5sum = md5_file($source_filepath);
246  $file_path = null;
247 
248  if (isset($image_id))
249  {
250    // we are performing an update
251    $query = '
252SELECT
253    path
254  FROM '.IMAGES_TABLE.'
255  WHERE id = '.$image_id.'
256;';
257    $result = pwg_query($query);
258    while ($row = pwg_db_fetch_assoc($result))
259    {
260      $file_path = $row['path'];
261    }
262   
263    if (!isset($file_path))
264    {
265      die('['.__FUNCTION__.'] this photo does not exist in the database');
266    }
267
268    // delete all physical files related to the photo (thumbnail, web site, HD)
269    delete_element_files(array($image_id));
270  }
271  else
272  {
273    // this photo is new
274   
275    // current date
276    list($dbnow) = pwg_db_fetch_row(pwg_query('SELECT NOW();'));
277    list($year, $month, $day) = preg_split('/[^\d]/', $dbnow, 4);
278 
279    // upload directory hierarchy
280    $upload_dir = sprintf(
281      PHPWG_ROOT_PATH.$conf['upload_dir'].'/%s/%s/%s',
282      $year,
283      $month,
284      $day
285      );
286
287    // compute file path
288    $date_string = preg_replace('/[^\d]/', '', $dbnow);
289    $random_string = substr($md5sum, 0, 8);
290    $filename_wo_ext = $date_string.'-'.$random_string;
291    $file_path = $upload_dir.'/'.$filename_wo_ext.'.';
292
293    list($width, $height, $type) = getimagesize($source_filepath);
294    if (IMAGETYPE_PNG == $type)
295    {
296      $file_path.= 'png';
297    }
298    elseif (IMAGETYPE_GIF == $type)
299    {
300      $file_path.= 'gif';
301    }
302    else
303    {
304      $file_path.= 'jpg';
305    }
306
307    prepare_directory($upload_dir);
308  }
309
310  if (is_uploaded_file($source_filepath))
311  {
312    move_uploaded_file($source_filepath, $file_path);
313  }
314  else
315  {
316    copy($source_filepath, $file_path);
317  }
318
319  if ($conf['upload_form_websize_resize']
320      and need_resize($file_path, $conf['upload_form_websize_maxwidth'], $conf['upload_form_websize_maxheight']))
321  {
322    $high_path = file_path_for_type($file_path, 'high');
323    $high_dir = dirname($high_path);
324    prepare_directory($high_dir);
325   
326    rename($file_path, $high_path);
327    $high_infos = pwg_image_infos($high_path);
328   
329    $img = new pwg_image($high_path);
330
331    $img->pwg_resize(
332      $file_path,
333      $conf['upload_form_websize_maxwidth'],
334      $conf['upload_form_websize_maxheight'],
335      $conf['upload_form_websize_quality'],
336      $conf['upload_form_automatic_rotation'],
337      false
338      );
339
340    if ($img->library != 'gd')
341    {
342      if ($conf['upload_form_hd_keep'])
343      {
344        if ($conf['upload_form_hd_resize'])
345        {
346          $need_resize = need_resize($high_path, $conf['upload_form_hd_maxwidth'], $conf['upload_form_hd_maxheight']);
347       
348          if ($need_resize)
349          {
350            $img->pwg_resize(
351              $high_path,
352              $conf['upload_form_hd_maxwidth'],
353              $conf['upload_form_hd_maxheight'],
354              $conf['upload_form_hd_quality'],
355              $conf['upload_form_automatic_rotation'],
356              false
357              );
358            $high_infos = pwg_image_infos($high_path);
359          }
360        }
361      }
362      else
363      {
364        unlink($high_path);
365        $high_infos = null;
366      }
367    }
368    $img->destroy();
369  }
370
371  $file_infos = pwg_image_infos($file_path);
372 
373  $thumb_path = file_path_for_type($file_path, 'thumb');
374  $thumb_dir = dirname($thumb_path);
375  prepare_directory($thumb_dir);
376
377  $img = new pwg_image($file_path);
378  $img->pwg_resize(
379    $thumb_path,
380    $conf['upload_form_thumb_maxwidth'],
381    $conf['upload_form_thumb_maxheight'],
382    $conf['upload_form_thumb_quality'],
383    false,
384    true,
385    $conf['upload_form_thumb_crop'],
386    $conf['upload_form_thumb_follow_orientation']
387    );
388  $img->destroy();
389 
390  $thumb_infos = pwg_image_infos($thumb_path);
391
392  if (isset($image_id))
393  {
394    $update = array(
395      'id' => $image_id,
396      'file' => pwg_db_real_escape_string(isset($original_filename) ? $original_filename : basename($file_path)),
397      'filesize' => $file_infos['filesize'],
398      'width' => $file_infos['width'],
399      'height' => $file_infos['height'],
400      'md5sum' => $md5sum,
401      'added_by' => $user['id'],
402      );
403   
404    if (isset($high_infos))
405    {
406      $update['has_high'] = 'true';
407      $update['high_filesize'] = $high_infos['filesize'];
408      $update['high_width'] = $high_infos['width'];
409      $update['high_height'] = $high_infos['height'];
410    }
411    else
412    {
413      $update['has_high'] = 'false';
414      $update['high_filesize'] = null;
415      $update['high_width'] = null;
416      $update['high_height'] = null;
417    }
418
419    if (isset($level))
420    {
421      $update['level'] = $level;
422    }
423
424    mass_updates(
425      IMAGES_TABLE,
426      array(
427        'primary' => array('id'),
428        'update' => array_keys($update)
429        ),
430      array($update)
431      );
432  }
433  else
434  {
435    // database registration
436    $insert = array(
437      'file' => pwg_db_real_escape_string(isset($original_filename) ? $original_filename : basename($file_path)),
438      'date_available' => $dbnow,
439      'tn_ext' => 'jpg',
440      'path' => preg_replace('#^'.preg_quote(PHPWG_ROOT_PATH).'#', '', $file_path),
441      'filesize' => $file_infos['filesize'],
442      'width' => $file_infos['width'],
443      'height' => $file_infos['height'],
444      'md5sum' => $md5sum,
445      'added_by' => $user['id'],
446      );
447
448    if (isset($high_infos))
449    {
450      $insert['has_high'] = 'true';
451      $insert['high_filesize'] = $high_infos['filesize'];
452      $insert['high_width'] = $high_infos['width'];
453      $insert['high_height'] = $high_infos['height'];
454    }
455
456    if (isset($level))
457    {
458      $insert['level'] = $level;
459    }
460 
461    mass_inserts(
462      IMAGES_TABLE,
463      array_keys($insert),
464      array($insert)
465      );
466 
467    $image_id = pwg_db_insert_id(IMAGES_TABLE);
468  }
469
470  if (isset($categories) and count($categories) > 0)
471  {
472    associate_images_to_categories(
473      array($image_id),
474      $categories
475      );
476  }
477 
478  // update metadata from the uploaded file (exif/iptc)
479  if ($conf['use_exif'] and !function_exists('read_exif_data'))
480  {
481    $conf['use_exif'] = false;
482  }
483  sync_metadata(array($image_id));
484
485  invalidate_user_cache();
486
487  return $image_id;
488}
489
490function prepare_directory($directory)
491{
492  if (!is_dir($directory)) {
493    if (substr(PHP_OS, 0, 3) == 'WIN')
494    {
495      $directory = str_replace('/', DIRECTORY_SEPARATOR, $directory);
496    }
497    umask(0000);
498    $recursive = true;
499    if (!@mkdir($directory, 0777, $recursive))
500    {
501      die('[prepare_directory] cannot create directory "'.$directory.'"');
502    }
503  }
504
505  if (!is_writable($directory))
506  {
507    // last chance to make the directory writable
508    @chmod($directory, 0777);
509
510    if (!is_writable($directory))
511    {
512      die('[prepare_directory] directory "'.$directory.'" has no write access');
513    }
514  }
515
516  secure_directory($directory);
517}
518
519function need_resize($image_filepath, $max_width, $max_height)
520{
521  // TODO : the resize check should take the orientation into account. If a
522  // rotation must be applied to the resized photo, then we should test
523  // invert width and height.
524  list($width, $height) = getimagesize($image_filepath);
525 
526  if ($width > $max_width or $height > $max_height)
527  {
528    return true;
529  }
530
531  return false;
532}
533
534function pwg_image_infos($path)
535{
536  list($width, $height) = getimagesize($path);
537  $filesize = floor(filesize($path)/1024);
538 
539  return array(
540    'width'  => $width,
541    'height' => $height,
542    'filesize' => $filesize,
543    );
544}
545
546function is_valid_image_extension($extension)
547{
548  return in_array(strtolower($extension), array('jpg', 'jpeg', 'png', 'gif'));
549}
550
551function file_upload_error_message($error_code)
552{
553  switch ($error_code) {
554    case UPLOAD_ERR_INI_SIZE:
555      return sprintf(
556        l10n('The uploaded file exceeds the upload_max_filesize directive in php.ini: %sB'),
557        get_ini_size('upload_max_filesize', false)
558        );
559    case UPLOAD_ERR_FORM_SIZE:
560      return l10n('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form');
561    case UPLOAD_ERR_PARTIAL:
562      return l10n('The uploaded file was only partially uploaded');
563    case UPLOAD_ERR_NO_FILE:
564      return l10n('No file was uploaded');
565    case UPLOAD_ERR_NO_TMP_DIR:
566      return l10n('Missing a temporary folder');
567    case UPLOAD_ERR_CANT_WRITE:
568      return l10n('Failed to write file to disk');
569    case UPLOAD_ERR_EXTENSION:
570      return l10n('File upload stopped by extension');
571    default:
572      return l10n('Unknown upload error');
573  }
574}
575
576function get_ini_size($ini_key, $in_bytes=true)
577{
578  $size = ini_get($ini_key);
579
580  if ($in_bytes)
581  {
582    $size = convert_shorthand_notation_to_bytes($size);
583  }
584 
585  return $size;
586}
587
588function convert_shorthand_notation_to_bytes($value)
589{
590  $suffix = substr($value, -1);
591  $multiply_by = null;
592 
593  if ('K' == $suffix)
594  {
595    $multiply_by = 1024;
596  }
597  else if ('M' == $suffix)
598  {
599    $multiply_by = 1024*1024;
600  }
601  else if ('G' == $suffix)
602  {
603    $multiply_by = 1024*1024*1024;
604  }
605 
606  if (isset($multiply_by))
607  {
608    $value = substr($value, 0, -1);
609    $value*= $multiply_by;
610  }
611
612  return $value;
613}
614
615function add_upload_error($upload_id, $error_message)
616{
617  if (!isset($_SESSION['uploads_error']))
618  {
619    $_SESSION['uploads_error'] = array();
620  }
621  if (!isset($_SESSION['uploads_error'][$upload_id]))
622  {
623    $_SESSION['uploads_error'][$upload_id] = array();
624  }
625
626  array_push($_SESSION['uploads_error'][$upload_id], $error_message);
627}
628
629function ready_for_upload_message()
630{
631  global $conf;
632
633  $relative_dir = preg_replace('#^'.PHPWG_ROOT_PATH.'#', '', $conf['upload_dir']);
634
635  if (!is_dir($conf['upload_dir']))
636  {
637    if (!is_writable(dirname($conf['upload_dir'])))
638    {
639      return sprintf(
640        l10n('Create the "%s" directory at the root of your Piwigo installation'),
641        $relative_dir
642        );
643    }
644  }
645  else
646  {
647    if (!is_writable($conf['upload_dir']))
648    {
649      @chmod($conf['upload_dir'], 0777);
650     
651      if (!is_writable($conf['upload_dir']))
652      {
653        return sprintf(
654          l10n('Give write access (chmod 777) to "%s" directory at the root of your Piwigo installation'),
655          $relative_dir
656          );
657      }
658    }
659  }
660
661  return null;
662}
663
664function file_path_for_type($file_path, $type='thumb')
665{
666  // resolve the $file_path depending on the $type
667  if ('thumb' == $type) {
668    $file_path = get_thumbnail_location(
669      array(
670        'path' => $file_path,
671        'tn_ext' => 'jpg',
672        )
673      );
674  }
675
676  if ('high' == $type) {
677    @include_once(PHPWG_ROOT_PATH.'include/functions_picture.inc.php');
678    $file_path = get_high_location(
679      array(
680        'path' => $file_path,
681        'has_high' => 'true'
682        )
683      );
684  }
685
686  return $file_path;
687}
688
689?>
Note: See TracBrowser for help on using the repository browser.