source: trunk/tools/create_listing_file.php @ 1525

Last change on this file since 1525 was 1525, checked in by laurent_duretz, 18 years ago

merge -r1522:1523 from branch 1.6 to trunk (Bugs 122 and 475 : Crash on big remote site update)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 17.4 KB
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | PhpWebGallery - a PHP based picture gallery                           |
4// | Copyright (C) 2002-2003 Pierrick LE GALL - pierrick@phpwebgallery.net |
5// | Copyright (C) 2003-2005 PhpWebGallery Team - http://phpwebgallery.net |
6// +-----------------------------------------------------------------------+
7// | branch        : BSF (Best So Far)
8// | file          : $RCSfile$
9// | last update   : $Date: 2006-08-03 18:40:09 +0000 (Thu, 03 Aug 2006) $
10// | last modifier : $Author: laurent_duretz $
11// | revision      : $Revision: 1525 $
12// +-----------------------------------------------------------------------+
13// | This program is free software; you can redistribute it and/or modify  |
14// | it under the terms of the GNU General Public License as published by  |
15// | the Free Software Foundation                                          |
16// |                                                                       |
17// | This program is distributed in the hope that it will be useful, but   |
18// | WITHOUT ANY WARRANTY; without even the implied warranty of            |
19// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
20// | General Public License for more details.                              |
21// |                                                                       |
22// | You should have received a copy of the GNU General Public License     |
23// | along with this program; if not, write to the Free Software           |
24// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
25// | USA.                                                                  |
26// +-----------------------------------------------------------------------+
27
28// +-----------------------------------------------------------------------+
29// |                              parameters                               |
30// +-----------------------------------------------------------------------+
31
32// prefix for thumbnails in "thumbnail" sub directories
33$conf['prefix_thumbnail'] = 'TN-';
34
35// $conf['file_ext'] lists all extensions (case insensitive) allowed for
36// your PhpWebGallery installation
37$conf['file_ext'] = array('jpg','JPG','png','PNG','gif','GIF','mpg','zip',
38                          'avi','mp3','ogg');
39
40// $conf['picture_ext'] must be a subset of $conf['file_ext']
41$conf['picture_ext'] = array('jpg','JPG','png','PNG','gif','GIF');
42
43// $conf['version'] is used to verify the compatibility of the generated
44// listing.xml file and the PhpWebGallery version you're running
45$conf['version'] = '%PWGVERSION%';
46
47// $conf['use_exif'] set to true if you want to use Exif information
48$conf['use_exif'] = true;
49
50// use_exif_mapping: same behaviour as use_iptc_mapping
51$conf['use_exif_mapping'] = array(
52  'date_creation' => 'DateTimeOriginal'
53  );
54
55// $conf['use_iptc'] set to true if you want to use IPTC informations of the
56// element according to get_sync_iptc_data function mapping, otherwise, set
57// to false
58$conf['use_iptc'] = false;
59
60// use_iptc_mapping : in which IPTC fields will PhpWebGallery find image
61// information ? This setting is used during metadata synchronisation. It
62// associates a phpwebgallery_images column name to a IPTC key
63$conf['use_iptc_mapping'] = array(
64  'keywords'        => '2#025',
65  'date_creation'   => '2#055',
66  'author'          => '2#122',
67  'name'            => '2#005',
68  'comment'         => '2#120'
69  );
70
71// +-----------------------------------------------------------------------+
72// |                               functions                               |
73// +-----------------------------------------------------------------------+
74
75/**
76 * returns informations from IPTC metadata, mapping is done at the beginning
77 * of the function
78 *
79 * @param string $filename
80 * @return array
81 */
82function get_iptc_data($filename, $map)
83{
84  $result = array();
85
86  // Read IPTC data
87  $iptc = array();
88
89  $imginfo = array();
90  getimagesize($filename, $imginfo);
91
92  if (isset($imginfo['APP13']))
93  {
94    $iptc = iptcparse($imginfo['APP13']);
95    if (is_array($iptc))
96    {
97      $rmap = array_flip($map);
98      foreach (array_keys($rmap) as $iptc_key)
99      {
100        if (isset($iptc[$iptc_key][0]))
101        {
102          if ($iptc_key == '2#025')
103          {
104            $value = implode(',',
105                             array_map('clean_iptc_value',$iptc[$iptc_key]));
106          }
107          else
108          {
109            $value = clean_iptc_value($iptc[$iptc_key][0]);
110          }
111
112          foreach (array_keys($map, $iptc_key) as $pwg_key)
113          {
114            $result[$pwg_key] = $value;
115          }
116        }
117      }
118    }
119  }
120  return $result;
121}
122
123/**
124 * return a cleaned IPTC value
125 *
126 * @param string value
127 * @return string
128 */
129function clean_iptc_value($value)
130{
131  // strip leading zeros (weird Kodak Scanner software)
132  while ($value[0] == chr(0))
133  {
134    $value = substr($value, 1);
135  }
136  // remove binary nulls
137  $value = str_replace(chr(0x00), ' ', $value);
138
139  return $value;
140}
141
142function get_sync_iptc_data($file)
143{
144  global $conf;
145
146  $map = $conf['use_iptc_mapping'];
147  $datefields = array('date_creation', 'date_available');
148
149  $iptc = get_iptc_data($file, $map);
150
151  foreach ($iptc as $pwg_key => $value)
152  {
153    if (in_array($pwg_key, $datefields))
154    {
155      if ( preg_match('/(\d{4})(\d{2})(\d{2})/', $value, $matches))
156      {
157        $value = $matches[1].'-'.$matches[2].'-'.$matches[3];
158      }
159    }
160    if ($pwg_key == 'keywords')
161    {
162      // official keywords separator is the comma
163      $value = preg_replace('/[.;]/', ',', $value);
164      $value = preg_replace('/^,+|,+$/', '', $value);
165    }
166    $iptc[$pwg_key] = htmlentities($value);
167  }
168
169  $iptc['keywords'] = implode(
170               ',',
171               array_unique(
172                 explode(
173                   ',',
174                   $iptc['keywords']
175                   )
176                 )
177               );
178  return $iptc;
179}
180
181/**
182 * returns a float value coresponding to the number of seconds since the
183 * unix epoch (1st January 1970) and the microseconds are precised :
184 * e.g. 1052343429.89276600
185 *
186 * @return float
187 */
188function get_moment()
189{
190  $t1 = explode(' ', microtime());
191  $t2 = explode('.', $t1[0]);
192  $t2 = $t1[1].'.'.$t2[1];
193  return $t2;
194}
195
196/**
197 * returns the number of seconds (with 3 decimals precision) between the
198 * start time and the end time given.
199 *
200 * @param float start
201 * @param float end
202 * @return void
203 */
204function get_elapsed_time($start, $end)
205{
206  return number_format($end - $start, 3, '.', ' ').' s';
207}
208
209/**
210 * returns an array with all picture files according to $conf['file_ext']
211 *
212 * @param string $dir
213 * @return array
214 */
215function get_pwg_files($dir)
216{
217  global $conf;
218
219  $pictures = array();
220  if ($opendir = opendir($dir))
221  {
222    while ($file = readdir($opendir))
223    {
224      if (in_array(get_extension($file), $conf['file_ext']))
225      {
226        array_push($pictures, $file);
227        if (!preg_match('/^[a-zA-Z0-9-_.]+$/', $file))
228        {
229          echo 'PWG-WARNING-2: "'.$file.'" : ';
230          echo 'The name of the file should be composed of ';
231          echo 'letters, figures, "-", "_" or "." ONLY';
232          echo "\n";
233        }
234      }
235    }
236  }
237  return $pictures;
238}
239
240/**
241 * returns an array with all thumbnails according to $conf['picture_ext']
242 * and $conf['prefix_thumbnail']
243 *
244 * @param string $dir
245 * @return array
246 */
247function get_thumb_files($dir)
248{
249  global $conf;
250
251  $prefix_length = strlen($conf['prefix_thumbnail']);
252
253  $thumbnails = array();
254  if (is_dir($dir.'/thumbnail'))
255  {
256    if ($opendir = opendir($dir.'/thumbnail'))
257    {
258      while ($file = readdir($opendir))
259      {
260        if (in_array(get_extension($file), $conf['picture_ext'])
261            and substr($file,0,$prefix_length) == $conf['prefix_thumbnail'])
262        {
263          array_push($thumbnails, $file);
264        }
265      }
266    }
267  }
268  return $thumbnails;
269}
270
271/**
272 * returns an array with representative picture files of a directory
273 * according to $conf['picture_ext']
274 *
275 * @param string $dir
276 * @return array
277 */
278function get_representative_files($dir)
279{
280  global $conf;
281
282  $pictures = array();
283  if (is_dir($dir.'/pwg_representative'))
284  {
285    if ($opendir = opendir($dir.'/pwg_representative'))
286    {
287      while ($file = readdir($opendir))
288      {
289        if (in_array(get_extension($file), $conf['picture_ext']))
290        {
291          array_push($pictures, $file);
292        }
293      }
294    }
295  }
296  return $pictures;
297}
298
299/**
300 * returns an array with high quality/resolution picture files of a directory
301 * according to $conf['picture_ext']
302 *
303 * @param string $dir
304 * @return array
305 */
306function get_high_files($dir)
307{
308  global $conf;
309
310  $pictures = array();
311  if (is_dir($dir.'/pwg_high'))
312  {
313    if ($opendir = opendir($dir.'/pwg_high'))
314    {
315      while ($file = readdir($opendir))
316      {
317        if (in_array(get_extension($file), $conf['picture_ext']))
318        {
319          array_push($pictures, $file);
320        }
321      }
322    }
323  }
324  return $pictures;
325}
326
327/**
328 * search in $basedir the sub-directories and calls get_pictures
329 *
330 * @return void
331 */
332function get_dirs($basedir, $indent, $level)
333{
334  $fs_dirs = array();
335  $dirs = "";
336  global $conf_safe_mode;
337
338  // Refresh the max_execution_time to avoid timout error
339  // By default time to scan a directory (without subdirs) is fixed to 30 seconds
340  if (!$conf_safe_mode)
341  {
342    set_time_limit(30);
343  }
344
345  if ($opendir = opendir($basedir))
346  {
347    while ($file = readdir($opendir))
348    {
349      if ($file != '.'
350          and $file != '..'
351          and $file != '.svn'
352          and $file != 'thumbnail'
353          and $file != 'pwg_high'
354          and $file != 'pwg_representative'
355          and is_dir ($basedir.'/'.$file))
356      {
357        array_push($fs_dirs, $file);
358        if (!preg_match('/^[a-zA-Z0-9-_.]+$/', $file))
359        {
360          echo 'PWG-WARNING-1: "'.$file.'" : ';
361          echo 'The name of the directory should be composed of ';
362          echo 'letters, figures, "-", "_" or "." ONLY';
363          echo "\n";
364        }
365      }
366    }
367  }
368  // write of the dirs
369  foreach ($fs_dirs as $fs_dir)
370  {
371    $dirs.= "\n".$indent.'<dir'.$level.' name="'.$fs_dir.'">';
372    $dirs.= get_pictures($basedir.'/'.$fs_dir, $indent.'  ');
373    $dirs.= get_dirs($basedir.'/'.$fs_dir, $indent.'  ', $level + 1);
374    $dirs.= "\n".$indent.'</dir'.$level.'>';
375  }
376  return $dirs;
377}
378
379// get_extension returns the part of the string after the last "."
380function get_extension($filename)
381{
382  return substr(strrchr($filename, '.'), 1, strlen ($filename));
383}
384
385// get_filename_wo_extension returns the part of the string before the last
386// ".".
387// get_filename_wo_extension('test.tar.gz') -> 'test.tar'
388function get_filename_wo_extension($filename)
389{
390  return substr($filename, 0, strrpos($filename, '.'));
391}
392
393function get_pictures($dir, $indent)
394{
395  global $conf, $page;
396
397  // fs means FileSystem : $fs_files contains files in the filesystem found
398  // in $dir that can be managed by PhpWebGallery (see get_pwg_files
399  // function), $fs_thumbnails contains thumbnails, $fs_representatives
400  // contains potentially representative pictures for non picture files
401  $fs_files = get_pwg_files($dir);
402  $fs_thumbnails = get_thumb_files($dir);
403  $fs_representatives = get_representative_files($dir);
404  $fs_highs = get_high_files($dir);
405
406  $elements = array();
407
408  $print_dir = preg_replace('/^\.\//', '', $dir);
409  $print_dir = preg_replace('/\/*$/', '/', $print_dir);
410
411  foreach ($fs_files as $fs_file)
412  {
413    $element = array();
414    $element['file'] = $fs_file;
415    $element['path'] = $page['url'].$print_dir.$fs_file;
416    $element['filesize'] = floor(filesize($dir.'/'.$fs_file) / 1024);
417
418    $file_wo_ext = get_filename_wo_extension($fs_file);
419
420    foreach ($conf['picture_ext'] as $ext)
421    {
422      $test = $conf['prefix_thumbnail'].$file_wo_ext.'.'.$ext;
423      if (!in_array($test, $fs_thumbnails))
424      {
425        continue;
426      }
427      else
428      {
429        $element['tn_ext'] = $ext;
430        break;
431      }
432    }
433
434    // 2 cases : the element is a picture or not. Indeed, for a picture
435    // thumbnail is mandatory, high is optional and for non picture element,
436    // thumbnail and representative is optionnal
437    if (in_array(get_extension($fs_file), $conf['picture_ext']))
438    {
439      // if we found a thumnbnail corresponding to our picture...
440      if (isset($element['tn_ext']))
441      {
442        if ($image_size = @getimagesize($dir.'/'.$fs_file))
443        {
444          $element['width'] = $image_size[0];
445          $element['height'] = $image_size[1];
446        }
447
448        if ( in_array($fs_file, $fs_highs) )
449        {
450          $element['has_high'] = 'true';
451        }
452
453        if ($conf['use_exif'])
454        {
455          // Verify activation of exif module
456          if (extension_loaded('exif'))
457          {
458            if ($exif = read_exif_data($dir.'/'.$fs_file))
459            {
460              foreach ($conf['use_exif_mapping'] as $pwg_key => $exif_key )
461              {
462                if (isset($exif[$exif_key]))
463                {
464                  if ( in_array($pwg_key, array('date_creation','date_available') ) )
465                  {
466                     if (preg_match('/^(\d{4}):(\d{2}):(\d{2})/'
467                           ,$exif[$exif_key]
468                           ,$matches))
469                     {
470                       $element[$pwg_key] =
471                          $matches[1].'-'.$matches[2].'-'.$matches[3];
472                     }
473                  }
474                  else
475                  {
476                    $element[$pwg_key] = $exif[$exif_key];
477                  }
478                }
479              }
480            }
481          }
482        }
483
484        if ($conf['use_iptc'])
485        {
486          $iptc = get_sync_iptc_data($dir.'/'.$fs_file);
487          if (count($iptc) > 0)
488          {
489            foreach (array_keys($iptc) as $key)
490            {
491              $element[$key] = $iptc[$key];
492            }
493          }
494        }
495
496        array_push($elements, $element);
497      }
498      else
499      {
500        echo 'PWG-ERROR-1: The thumbnail is missing for '.$dir.'/'.$fs_file;
501        echo '-> '.$dir.'/thumbnail/';
502        echo $conf['prefix_thumbnail'].$file_wo_ext.'.xxx';
503        echo ' ("xxx" can be : ';
504        echo implode(', ', $conf['picture_ext']);
505        echo ')'."\n";
506      }
507    }
508    else
509    {
510      foreach ($conf['picture_ext'] as $ext)
511      {
512        $candidate = $file_wo_ext.'.'.$ext;
513        if (!in_array($candidate, $fs_representatives))
514        {
515          continue;
516        }
517        else
518        {
519          $element['representative_ext'] = $ext;
520          break;
521        }
522      }
523
524      array_push($elements, $element);
525    }
526  }
527
528  $xml = "\n".$indent.'<root>';
529  $attributes = array('file','tn_ext','representative_ext','filesize',
530                      'width','height','date_creation','author','keywords',
531                      'name','comment','has_high', 'path');
532  foreach ($elements as $element)
533  {
534    $xml.= "\n".$indent.'  ';
535    $xml.= '<element';
536    foreach ($attributes as $attribute)
537    {
538      if (isset($element{$attribute}))
539      {
540        $xml.= ' '.$attribute.'="'.$element{$attribute}.'"';
541      }
542    }
543    $xml.= ' />';
544  }
545  $xml.= "\n".$indent.'</root>';
546
547  return $xml;
548}
549
550// +-----------------------------------------------------------------------+
551// |                                script                                 |
552// +-----------------------------------------------------------------------+
553if (isset($_GET['action']))
554{
555  $page['action'] = $_GET['action'];
556}
557else
558{
559  $page['action'] = '';
560}
561
562// Looking at the safe_mode configuration for execution time
563$conf_safe_mode = TRUE;
564if (ini_get('safe_mode') == 0)
565{
566  $conf_safe_mode = FALSE;
567}
568
569echo '<pre>';
570switch ($page['action'])
571{
572  case 'generate' :
573  {
574    $start = get_moment();
575
576    $listing = '<informations';
577    $listing.= ' generation_date="'.date('Y-m-d').'"';
578    $listing.= ' phpwg_version="'.htmlentities($conf{'version'}).'"';
579
580    $attrs=array();
581    if ($conf['use_iptc'])
582    {
583      $attrs = array_merge($attrs, array_keys($conf['use_iptc_mapping']) );
584    }
585    if ($conf['use_exif'])
586    {
587      $attrs = array_merge($attrs, array_keys($conf['use_exif_mapping']) );
588    }
589    $listing.= ' metadata="'.implode(',',array_unique($attrs)).'"';
590
591    $end = strrpos($_SERVER['PHP_SELF'], '/') + 1;
592    $local_folder = substr($_SERVER['PHP_SELF'], 0, $end);
593    $page['url'] = 'http://'.$_SERVER['HTTP_HOST'].$local_folder;
594
595    $listing.= ' url="'.$page['url'].'"';
596    $listing.= '/>'."\n";
597
598    $listing.= get_dirs('.', '', 0);
599
600    if ($fp = @fopen("./listing.xml","w"))
601    {
602      fwrite($fp, $listing);
603      fclose($fp);
604      echo 'PWG-INFO-1: listing.xml created in ';
605      echo get_elapsed_time($start, get_moment());
606      echo "\n";
607    }
608    else
609    {
610      echo "PWG-ERROR-2: I can't write the file listing.xml"."\n";
611    }
612    break;
613  }
614  case 'test' :
615  {
616    if (isset($_GET['version']))
617    {
618      if ($_GET['version'] != $conf['version'])
619      {
620        echo 'PWG-ERROR-4: PhpWebGallery versions differs'."\n";
621      }
622      else
623      {
624        echo 'PWG-INFO-2: test successful'."\n";
625      }
626    }
627    else
628    {
629      echo 'PWG-INFO-2: test successful'."\n";
630    }
631    break;
632  }
633  case 'clean' :
634  {
635    if( @unlink('./listing.xml'))
636    {
637      echo 'PWG-INFO-3 : listing.xml file deleted'."\n";
638    }
639    else
640    {
641      echo 'PWG-ERROR-3 : listing.xml does not exist'."\n";
642    }
643    break;
644  }
645  default :
646  {
647    // Menu de lancement pour la mise à jour manuel des sites distant
648    echo '</pre>
649<ul>
650  <li>
651    <a href="create_listing_file.php?action=generate">Generate listing.xml</a>
652  </li>
653
654  <li>
655    <a href="create_listing_file.php?action=test">Test</a>
656  </li>
657
658  <li>
659    <a href="create_listing_file.php?action=clean">Clean</a>
660  </li>
661</ul>
662<pre>';
663  }
664}
665echo '</pre>';
666?>
Note: See TracBrowser for help on using the repository browser.