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

Last change on this file since 10858 was 10858, checked in by flop25, 13 years ago

bug:2292
Fixed the spelling of a function name.
convert_shortand_to_bytes into
convert_shorthand_to_bytes

File size: 17.3 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    $conf['upload_form_automatic_rotation'],
384    true
385    );
386  $img->destroy();
387 
388  $thumb_infos = pwg_image_infos($thumb_path);
389
390  if (isset($image_id))
391  {
392    $update = array(
393      'id' => $image_id,
394      'file' => pwg_db_real_escape_string(isset($original_filename) ? $original_filename : basename($file_path)),
395      'filesize' => $file_infos['filesize'],
396      'width' => $file_infos['width'],
397      'height' => $file_infos['height'],
398      'md5sum' => $md5sum,
399      'added_by' => $user['id'],
400      );
401   
402    if (isset($high_infos))
403    {
404      $update['has_high'] = 'true';
405      $update['high_filesize'] = $high_infos['filesize'];
406      $update['high_width'] = $high_infos['width'];
407      $update['high_height'] = $high_infos['height'];
408    }
409    else
410    {
411      $update['has_high'] = 'false';
412      $update['high_filesize'] = null;
413      $update['high_width'] = null;
414      $update['high_height'] = null;
415    }
416
417    if (isset($level))
418    {
419      $update['level'] = $level;
420    }
421
422    mass_updates(
423      IMAGES_TABLE,
424      array(
425        'primary' => array('id'),
426        'update' => array_keys($update)
427        ),
428      array($update)
429      );
430  }
431  else
432  {
433    // database registration
434    $insert = array(
435      'file' => pwg_db_real_escape_string(isset($original_filename) ? $original_filename : basename($file_path)),
436      'date_available' => $dbnow,
437      'tn_ext' => 'jpg',
438      'path' => preg_replace('#^'.preg_quote(PHPWG_ROOT_PATH).'#', '', $file_path),
439      'filesize' => $file_infos['filesize'],
440      'width' => $file_infos['width'],
441      'height' => $file_infos['height'],
442      'md5sum' => $md5sum,
443      'added_by' => $user['id'],
444      );
445
446    if (isset($high_infos))
447    {
448      $insert['has_high'] = 'true';
449      $insert['high_filesize'] = $high_infos['filesize'];
450      $insert['high_width'] = $high_infos['width'];
451      $insert['high_height'] = $high_infos['height'];
452    }
453
454    if (isset($level))
455    {
456      $insert['level'] = $level;
457    }
458 
459    mass_inserts(
460      IMAGES_TABLE,
461      array_keys($insert),
462      array($insert)
463      );
464 
465    $image_id = pwg_db_insert_id(IMAGES_TABLE);
466  }
467
468  if (isset($categories) and count($categories) > 0)
469  {
470    associate_images_to_categories(
471      array($image_id),
472      $categories
473      );
474  }
475 
476  // update metadata from the uploaded file (exif/iptc)
477  if ($conf['use_exif'] and !function_exists('read_exif_data'))
478  {
479    $conf['use_exif'] = false;
480  }
481  update_metadata(array($image_id=>$file_path));
482
483  invalidate_user_cache();
484
485  return $image_id;
486}
487
488function prepare_directory($directory)
489{
490  if (!is_dir($directory)) {
491    if (substr(PHP_OS, 0, 3) == 'WIN')
492    {
493      $directory = str_replace('/', DIRECTORY_SEPARATOR, $directory);
494    }
495    umask(0000);
496    $recursive = true;
497    if (!@mkdir($directory, 0777, $recursive))
498    {
499      die('[prepare_directory] cannot create directory "'.$directory.'"');
500    }
501  }
502
503  if (!is_writable($directory))
504  {
505    // last chance to make the directory writable
506    @chmod($directory, 0777);
507
508    if (!is_writable($directory))
509    {
510      die('[prepare_directory] directory "'.$directory.'" has no write access');
511    }
512  }
513
514  secure_directory($directory);
515}
516
517function need_resize($image_filepath, $max_width, $max_height)
518{
519  // TODO : the resize check should take the orientation into account. If a
520  // rotation must be applied to the resized photo, then we should test
521  // invert width and height.
522  list($width, $height) = getimagesize($image_filepath);
523 
524  if ($width > $max_width or $height > $max_height)
525  {
526    return true;
527  }
528
529  return false;
530}
531
532function pwg_image_infos($path)
533{
534  list($width, $height) = getimagesize($path);
535  $filesize = floor(filesize($path)/1024);
536 
537  return array(
538    'width'  => $width,
539    'height' => $height,
540    'filesize' => $filesize,
541    );
542}
543
544function is_valid_image_extension($extension)
545{
546  return in_array(strtolower($extension), array('jpg', 'jpeg', 'png', 'gif'));
547}
548
549function file_upload_error_message($error_code)
550{
551  switch ($error_code) {
552    case UPLOAD_ERR_INI_SIZE:
553      return sprintf(
554        l10n('The uploaded file exceeds the upload_max_filesize directive in php.ini: %sB'),
555        get_ini_size('upload_max_filesize', false)
556        );
557    case UPLOAD_ERR_FORM_SIZE:
558      return l10n('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form');
559    case UPLOAD_ERR_PARTIAL:
560      return l10n('The uploaded file was only partially uploaded');
561    case UPLOAD_ERR_NO_FILE:
562      return l10n('No file was uploaded');
563    case UPLOAD_ERR_NO_TMP_DIR:
564      return l10n('Missing a temporary folder');
565    case UPLOAD_ERR_CANT_WRITE:
566      return l10n('Failed to write file to disk');
567    case UPLOAD_ERR_EXTENSION:
568      return l10n('File upload stopped by extension');
569    default:
570      return l10n('Unknown upload error');
571  }
572}
573
574function get_ini_size($ini_key, $in_bytes=true)
575{
576  $size = ini_get($ini_key);
577
578  if ($in_bytes)
579  {
580    $size = convert_shorthand_notation_to_bytes($size);
581  }
582 
583  return $size;
584}
585
586function convert_shorthand_notation_to_bytes($value)
587{
588  $suffix = substr($value, -1);
589  $multiply_by = null;
590 
591  if ('K' == $suffix)
592  {
593    $multiply_by = 1024;
594  }
595  else if ('M' == $suffix)
596  {
597    $multiply_by = 1024*1024;
598  }
599  else if ('G' == $suffix)
600  {
601    $multiply_by = 1024*1024*1024;
602  }
603 
604  if (isset($multiply_by))
605  {
606    $value = substr($value, 0, -1);
607    $value*= $multiply_by;
608  }
609
610  return $value;
611}
612
613function add_upload_error($upload_id, $error_message)
614{
615  if (!isset($_SESSION['uploads_error']))
616  {
617    $_SESSION['uploads_error'] = array();
618  }
619  if (!isset($_SESSION['uploads_error'][$upload_id]))
620  {
621    $_SESSION['uploads_error'][$upload_id] = array();
622  }
623
624  array_push($_SESSION['uploads_error'][$upload_id], $error_message);
625}
626
627function ready_for_upload_message()
628{
629  global $conf;
630
631  $relative_dir = preg_replace('#^'.PHPWG_ROOT_PATH.'#', '', $conf['upload_dir']);
632
633  if (!is_dir($conf['upload_dir']))
634  {
635    if (!is_writable(dirname($conf['upload_dir'])))
636    {
637      return sprintf(
638        l10n('Create the "%s" directory at the root of your Piwigo installation'),
639        $relative_dir
640        );
641    }
642  }
643  else
644  {
645    if (!is_writable($conf['upload_dir']))
646    {
647      @chmod($conf['upload_dir'], 0777);
648     
649      if (!is_writable($conf['upload_dir']))
650      {
651        return sprintf(
652          l10n('Give write access (chmod 777) to "%s" directory at the root of your Piwigo installation'),
653          $relative_dir
654          );
655      }
656    }
657  }
658
659  return null;
660}
661
662function file_path_for_type($file_path, $type='thumb')
663{
664  // resolve the $file_path depending on the $type
665  if ('thumb' == $type) {
666    $file_path = get_thumbnail_location(
667      array(
668        'path' => $file_path,
669        'tn_ext' => 'jpg',
670        )
671      );
672  }
673
674  if ('high' == $type) {
675    @include_once(PHPWG_ROOT_PATH.'include/functions_picture.inc.php');
676    $file_path = get_high_location(
677      array(
678        'path' => $file_path,
679        'has_high' => 'true'
680        )
681      );
682  }
683
684  return $file_path;
685}
686
687?>
Note: See TracBrowser for help on using the repository browser.