source: trunk/tools/create_listing_file.php @ 1020

Last change on this file since 1020 was 1020, checked in by rvelices, 18 years ago

feature 280: Allow visitors/users to choose image ordering inside a category

improvement 82: Viewing pictures from remote galleries does not check anymore
for the high pictures (existence flag added to create_listing_file and db)

correction: link element in picture is in the head instead of body (w3c spec)

correction: in profile.php the current template was not selected by default

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.9 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-02-01 02:46:26 +0000 (Wed, 01 Feb 2006) $
10// | last modifier : $Author: rvelices $
11// | revision      : $Revision: 1020 $
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 Date as "creation
48// date" for the element, otherwise, set to false
49$conf['use_exif'] = true;
50
51// $conf['use_iptc'] set to true if you want to use IPTC informations of the
52// element according to get_sync_iptc_data function mapping, otherwise, set
53// to false
54$conf['use_iptc'] = false;
55
56// use_iptc_mapping : in which IPTC fields will PhpWebGallery find image
57// information ? This setting is used during metadata synchronisation. It
58// associates a phpwebgallery_images column name to a IPTC key
59$conf['use_iptc_mapping'] = array(
60  'keywords'        => '2#025',
61  'date_creation'   => '2#055',
62  'author'          => '2#122',
63  'name'            => '2#005',
64  'comment'         => '2#120'
65  );
66
67// +-----------------------------------------------------------------------+
68// |                               functions                               |
69// +-----------------------------------------------------------------------+
70
71/**
72 * returns informations from IPTC metadata, mapping is done at the beginning
73 * of the function
74 *
75 * @param string $filename
76 * @return array
77 */
78function get_iptc_data($filename, $map)
79{
80  $result = array();
81 
82  // Read IPTC data
83  $iptc = array();
84 
85  $imginfo = array();
86  getimagesize($filename, $imginfo);
87 
88  if (isset($imginfo['APP13']))
89  {
90    $iptc = iptcparse($imginfo['APP13']);
91    if (is_array($iptc))
92    {
93      $rmap = array_flip($map);
94      foreach (array_keys($rmap) as $iptc_key)
95      {
96        if (isset($iptc[$iptc_key][0]))
97        {
98          if ($iptc_key == '2#025')
99          {
100            $value = implode(',',
101                             array_map('clean_iptc_value',$iptc[$iptc_key]));
102          }
103          else
104          {
105            $value = clean_iptc_value($iptc[$iptc_key][0]);
106          }
107
108          foreach (array_keys($map, $iptc_key) as $pwg_key)
109          {
110            $result[$pwg_key] = $value;
111          }
112        }
113      }
114    }
115  }
116  return $result;
117}
118
119/**
120 * return a cleaned IPTC value
121 *
122 * @param string value
123 * @return string
124 */
125function clean_iptc_value($value)
126{
127  // strip leading zeros (weird Kodak Scanner software)
128  while ($value[0] == chr(0))
129  {
130    $value = substr($value, 1);
131  }
132  // remove binary nulls
133  $value = str_replace(chr(0x00), ' ', $value);
134 
135  return htmlentities($value);
136}
137
138function get_sync_iptc_data($file)
139{
140  global $conf;
141
142  $map = $conf['use_iptc_mapping'];
143  $datefields = array('date_creation', 'date_available');
144 
145  $iptc = get_iptc_data($file, $map);
146
147  foreach ($iptc as $pwg_key => $value)
148  {
149    if (in_array($pwg_key, $datefields))
150    {
151      if ( preg_match('/(\d{4})(\d{2})(\d{2})/', $value, $matches))
152      {
153        $iptc[$pwg_key] = $matches[1].'-'.$matches[2].'-'.$matches[3];
154      }
155    }
156  }
157
158  if (isset($iptc['keywords']))
159  {
160    // keywords separator is the comma, nothing else. Allowed characters in
161    // keywords : [A-Za-z0-9], "-" and "_". All other characters will be
162    // considered as separators
163    $iptc['keywords'] = preg_replace('/[^\w-]+/', ',', $iptc['keywords']);
164    $iptc['keywords'] = preg_replace('/^,+|,+$/', '', $iptc['keywords']);
165  }
166
167  return $iptc;
168}
169
170/**
171 * returns a float value coresponding to the number of seconds since the
172 * unix epoch (1st January 1970) and the microseconds are precised :
173 * e.g. 1052343429.89276600
174 *
175 * @return float
176 */
177function get_moment()
178{
179  $t1 = explode(' ', microtime());
180  $t2 = explode('.', $t1[0]);
181  $t2 = $t1[1].'.'.$t2[1];
182  return $t2;
183}
184
185/**
186 * returns the number of seconds (with 3 decimals precision) between the
187 * start time and the end time given.
188 *
189 * @param float start
190 * @param float end
191 * @return void
192 */
193function get_elapsed_time($start, $end)
194{
195  return number_format($end - $start, 3, '.', ' ').' s';
196}
197
198/**
199 * returns an array with all picture files according to $conf['file_ext']
200 *
201 * @param string $dir
202 * @return array
203 */
204function get_pwg_files($dir)
205{
206  global $conf;
207
208  $pictures = array();
209  if ($opendir = opendir($dir))
210  {
211    while ($file = readdir($opendir))
212    {
213      if (in_array(get_extension($file), $conf['file_ext']))
214      {
215        array_push($pictures, $file);
216        if (!preg_match('/^[a-zA-Z0-9-_.]+$/', $file))
217        {
218          echo 'PWG-WARNING-2: "'.$file.'" : ';
219          echo 'The name of the file should be composed of ';
220          echo 'letters, figures, "-", "_" or "." ONLY';
221          echo "\n";
222        }
223      }
224    }
225  }
226  return $pictures;
227}
228
229/**
230 * returns an array with all thumbnails according to $conf['picture_ext']
231 * and $conf['prefix_thumbnail']
232 *
233 * @param string $dir
234 * @return array
235 */
236function get_thumb_files($dir)
237{
238  global $conf;
239
240  $prefix_length = strlen($conf['prefix_thumbnail']);
241 
242  $thumbnails = array();
243  if ($opendir = @opendir($dir.'/thumbnail'))
244  {
245    while ($file = readdir($opendir))
246    {
247      if (in_array(get_extension($file), $conf['picture_ext'])
248          and substr($file,0,$prefix_length) == $conf['prefix_thumbnail'])
249      {
250        array_push($thumbnails, $file);
251      }
252    }
253  }
254  return $thumbnails;
255}
256
257/**
258 * returns an array with representative picture files of a directory
259 * according to $conf['picture_ext']
260 *
261 * @param string $dir
262 * @return array
263 */
264function get_representative_files($dir)
265{
266  global $conf;
267
268  $pictures = array();
269  if ($opendir = @opendir($dir.'/pwg_representative'))
270  {
271    while ($file = readdir($opendir))
272    {
273      if (in_array(get_extension($file), $conf['picture_ext']))
274      {
275        array_push($pictures, $file);
276      }
277    }
278  }
279  return $pictures;
280}
281
282/**
283 * returns an array with high quality/resolution picture files of a directory
284 * according to $conf['picture_ext']
285 *
286 * @param string $dir
287 * @return array
288 */
289function get_high_files($dir)
290{
291  global $conf;
292
293  $pictures = array();
294  if ($opendir = @opendir($dir.'/pwg_high'))
295  {
296    while ($file = readdir($opendir))
297    {
298      if (in_array(get_extension($file), $conf['picture_ext']))
299      {
300        array_push($pictures, $file);
301      }
302    }
303  }
304  return $pictures;
305}
306
307/**
308 * search in $basedir the sub-directories and calls get_pictures
309 *
310 * @return void
311 */
312function get_dirs($basedir, $indent, $level)
313{
314  $fs_dirs = array();
315  $dirs = "";
316
317  if ($opendir = opendir($basedir))
318  {
319    while ($file = readdir($opendir))
320    {
321      if ($file != '.'
322          and $file != '..'
323          and $file != 'thumbnail'
324          and $file != 'pwg_high'
325          and $file != 'pwg_representative'
326          and is_dir ($basedir.'/'.$file))
327      {
328        array_push($fs_dirs, $file);
329        if (!preg_match('/^[a-zA-Z0-9-_.]+$/', $file))
330        {
331          echo 'PWG-WARNING-1: "'.$file.'" : ';
332          echo 'The name of the directory should be composed of ';
333          echo 'letters, figures, "-", "_" or "." ONLY';
334          echo "\n";
335        }
336      }
337    }
338  }
339  // write of the dirs
340  foreach ($fs_dirs as $fs_dir)
341  {
342    $dirs.= "\n".$indent.'<dir'.$level.' name="'.$fs_dir.'">';
343    $dirs.= get_pictures($basedir.'/'.$fs_dir, $indent.'  ');
344    $dirs.= get_dirs($basedir.'/'.$fs_dir, $indent.'  ', $level + 1);
345    $dirs.= "\n".$indent.'</dir'.$level.'>';
346  }
347  return $dirs;         
348}
349
350// get_extension returns the part of the string after the last "."
351function get_extension($filename)
352{
353  return substr(strrchr($filename, '.'), 1, strlen ($filename));
354}
355
356// get_filename_wo_extension returns the part of the string before the last
357// ".".
358// get_filename_wo_extension('test.tar.gz') -> 'test.tar'
359function get_filename_wo_extension($filename)
360{
361  return substr($filename, 0, strrpos($filename, '.'));
362}
363
364function get_pictures($dir, $indent)
365{
366  global $conf, $page;
367 
368  // fs means FileSystem : $fs_files contains files in the filesystem found
369  // in $dir that can be managed by PhpWebGallery (see get_pwg_files
370  // function), $fs_thumbnails contains thumbnails, $fs_representatives
371  // contains potentially representative pictures for non picture files
372  $fs_files = get_pwg_files($dir);
373  $fs_thumbnails = get_thumb_files($dir);
374  $fs_representatives = get_representative_files($dir);
375  $fs_highs = get_high_files($dir);
376
377  $elements = array();
378
379  $print_dir = preg_replace('/^\.\//', '', $dir);
380  $print_dir = preg_replace('/\/*$/', '/', $print_dir);
381 
382  foreach ($fs_files as $fs_file)
383  {
384    $element = array();
385    $element['file'] = $fs_file;
386    $element['path'] = $page['url'].$print_dir.$fs_file;
387    $element['filesize'] = floor(filesize($dir.'/'.$fs_file) / 1024);
388   
389    $file_wo_ext = get_filename_wo_extension($fs_file);
390
391    foreach ($conf['picture_ext'] as $ext)
392    {
393      $test = $conf['prefix_thumbnail'].$file_wo_ext.'.'.$ext;
394      if (!in_array($test, $fs_thumbnails))
395      {
396        continue;
397      }
398      else
399      {
400        $element['tn_ext'] = $ext;
401        break;
402      }
403    }
404
405    // 2 cases : the element is a picture or not. Indeed, for a picture
406    // thumbnail is mandatory, high is optional and for non picture element,
407    // thumbnail and representative is optionnal
408    if (in_array(get_extension($fs_file), $conf['picture_ext']))
409    {
410      // if we found a thumnbnail corresponding to our picture...
411      if (isset($element['tn_ext']))
412      {
413        if ($image_size = @getimagesize($dir.'/'.$fs_file))
414        {
415          $element['width'] = $image_size[0];
416          $element['height'] = $image_size[1];
417        }
418       
419        if ( in_array($fs_file, $fs_highs) )
420        {
421          $element['has_high'] = 'true';
422        }
423
424        if ($conf['use_exif'])
425        {
426          if ($exif = @read_exif_data($dir.'/'.$fs_file))
427          {
428            if (isset($exif['DateTime']))
429            {
430              preg_match('/^(\d{4}):(\d{2}):(\d{2})/'
431                         ,$exif['DateTime']
432                         ,$matches);
433              $element['date_creation'] =
434                $matches[1].'-'.$matches[2].'-'.$matches[3];
435            }
436          }
437        }
438
439        if ($conf['use_iptc'])
440        {
441          $iptc = get_sync_iptc_data($dir.'/'.$fs_file);
442          if (count($iptc) > 0)
443          {
444            foreach (array_keys($iptc) as $key)
445            {
446              $element[$key] = addslashes($iptc[$key]);
447            }
448          }
449        }
450       
451        array_push($elements, $element);
452      }
453      else
454      {
455        echo 'PWG-ERROR-1: The thumbnail is missing for '.$dir.'/'.$fs_file;
456        echo '-> '.$dir.'/thumbnail/';
457        echo $conf['prefix_thumbnail'].$file_wo_ext.'.xxx';
458        echo ' ("xxx" can be : ';
459        echo implode(', ', $conf['picture_ext']);
460        echo ')'."\n";
461      }
462    }
463    else
464    {
465      foreach ($conf['picture_ext'] as $ext)
466      {
467        $candidate = $file_wo_ext.'.'.$ext;
468        if (!in_array($candidate, $fs_representatives))
469        {
470          continue;
471        }
472        else
473        {
474          $element['representative_ext'] = $ext;
475          break;
476        }
477      }
478     
479      array_push($elements, $element);
480    }
481  }
482
483  $xml = "\n".$indent.'<root>';
484  $attributes = array('file','tn_ext','representative_ext','filesize',
485                      'width','height','date_creation','author','keywords',
486                      'name','comment','has_high', 'path');
487  foreach ($elements as $element)
488  {
489    $xml.= "\n".$indent.'  ';
490    $xml.= '<element';
491    foreach ($attributes as $attribute)
492    {
493      if (isset($element{$attribute}))
494      {
495        $xml.= ' '.$attribute.'="'.$element{$attribute}.'"';
496      }
497    }
498    $xml.= ' />';
499  }
500  $xml.= "\n".$indent.'</root>';
501
502  return $xml;
503}
504
505// +-----------------------------------------------------------------------+
506// |                                script                                 |
507// +-----------------------------------------------------------------------+
508if (isset($_GET['action']))
509{
510  $page['action'] = $_GET['action'];
511}
512else
513{
514  $page['action'] = '';
515}
516
517echo '<pre>';
518switch ($page['action'])
519{
520  case 'generate' :
521  {
522    $start = get_moment();
523   
524    $listing = '<informations';
525    $listing.= ' generation_date="'.date('Y-m-d').'"';
526    $listing.= ' phpwg_version="'.$conf{'version'}.'"';
527   
528    $end = strrpos($_SERVER['PHP_SELF'], '/') + 1;
529    $local_folder = substr($_SERVER['PHP_SELF'], 0, $end);
530    $page['url'] = 'http://'.$_SERVER['HTTP_HOST'].$local_folder;
531   
532    $listing.= ' url="'.$page['url'].'"';
533    $listing.= '/>'."\n";
534   
535    $listing.= get_dirs('.', '', 0);
536   
537    if ($fp = @fopen("./listing.xml","w"))
538    {
539      fwrite($fp, $listing);
540      fclose($fp);
541      echo 'PWG-INFO-1: listing.xml created in ';
542      echo get_elapsed_time($start, get_moment());
543      echo "\n";
544    }
545    else
546    {
547      echo "PWG-ERROR-2: I can't write the file listing.xml"."\n";
548    }
549    break;
550  }
551  case 'test' :
552  {
553    if (isset($_GET['version']))
554    {
555      if ($_GET['version'] != $conf['version'])
556      {
557        echo 'PWG-ERROR-4: PhpWebGallery versions differs'."\n";
558      }
559      else
560      {
561        echo 'PWG-INFO-2: test successful'."\n";
562      }
563    }
564    else
565    {
566      echo 'PWG-INFO-2: test successful'."\n";
567    }
568    break;
569  }
570  case 'clean' :
571  {
572    if( @unlink('./listing.xml'))
573    {
574      echo 'PWG-INFO-3 : listing.xml file deleted'."\n";
575    }
576    else
577    {
578      echo 'PWG-ERROR-3 : listing.xml does not exist'."\n";
579    }
580    break;
581  }
582  default :
583  {
584    // Menu de lancement pour la mise à jour manuel des sites distant
585    echo '</pre>
586<ul>
587  <li>
588    <a href="create_listing_file.php?action=generate">Generate listing.xml</a>
589  </li>
590
591  <li>
592    <a href="create_listing_file.php?action=test">Test</a>
593  </li>
594
595  <li>
596    <a href="create_listing_file.php?action=clean">Clean</a>
597  </li>
598</ul>
599<pre>';
600  }
601}
602echo '</pre>';
603?>
Note: See TracBrowser for help on using the repository browser.