e730b6fb27
git-svn-id: http://piwigo.org/svn/trunk@1525 68402e56-0260-453c-a942-63ccdbb3a9ee
666 lines
17 KiB
PHP
666 lines
17 KiB
PHP
<?php
|
||
// +-----------------------------------------------------------------------+
|
||
// | PhpWebGallery - a PHP based picture gallery |
|
||
// | Copyright (C) 2002-2003 Pierrick LE GALL - pierrick@phpwebgallery.net |
|
||
// | Copyright (C) 2003-2005 PhpWebGallery Team - http://phpwebgallery.net |
|
||
// +-----------------------------------------------------------------------+
|
||
// | branch : BSF (Best So Far)
|
||
// | file : $RCSfile$
|
||
// | last update : $Date$
|
||
// | last modifier : $Author$
|
||
// | revision : $Revision$
|
||
// +-----------------------------------------------------------------------+
|
||
// | This program is free software; you can redistribute it and/or modify |
|
||
// | it under the terms of the GNU General Public License as published by |
|
||
// | the Free Software Foundation |
|
||
// | |
|
||
// | This program is distributed in the hope that it will be useful, but |
|
||
// | WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
||
// | General Public License for more details. |
|
||
// | |
|
||
// | You should have received a copy of the GNU General Public License |
|
||
// | along with this program; if not, write to the Free Software |
|
||
// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
|
||
// | USA. |
|
||
// +-----------------------------------------------------------------------+
|
||
|
||
// +-----------------------------------------------------------------------+
|
||
// | parameters |
|
||
// +-----------------------------------------------------------------------+
|
||
|
||
// prefix for thumbnails in "thumbnail" sub directories
|
||
$conf['prefix_thumbnail'] = 'TN-';
|
||
|
||
// $conf['file_ext'] lists all extensions (case insensitive) allowed for
|
||
// your PhpWebGallery installation
|
||
$conf['file_ext'] = array('jpg','JPG','png','PNG','gif','GIF','mpg','zip',
|
||
'avi','mp3','ogg');
|
||
|
||
// $conf['picture_ext'] must be a subset of $conf['file_ext']
|
||
$conf['picture_ext'] = array('jpg','JPG','png','PNG','gif','GIF');
|
||
|
||
// $conf['version'] is used to verify the compatibility of the generated
|
||
// listing.xml file and the PhpWebGallery version you're running
|
||
$conf['version'] = '%PWGVERSION%';
|
||
|
||
// $conf['use_exif'] set to true if you want to use Exif information
|
||
$conf['use_exif'] = true;
|
||
|
||
// use_exif_mapping: same behaviour as use_iptc_mapping
|
||
$conf['use_exif_mapping'] = array(
|
||
'date_creation' => 'DateTimeOriginal'
|
||
);
|
||
|
||
// $conf['use_iptc'] set to true if you want to use IPTC informations of the
|
||
// element according to get_sync_iptc_data function mapping, otherwise, set
|
||
// to false
|
||
$conf['use_iptc'] = false;
|
||
|
||
// use_iptc_mapping : in which IPTC fields will PhpWebGallery find image
|
||
// information ? This setting is used during metadata synchronisation. It
|
||
// associates a phpwebgallery_images column name to a IPTC key
|
||
$conf['use_iptc_mapping'] = array(
|
||
'keywords' => '2#025',
|
||
'date_creation' => '2#055',
|
||
'author' => '2#122',
|
||
'name' => '2#005',
|
||
'comment' => '2#120'
|
||
);
|
||
|
||
// +-----------------------------------------------------------------------+
|
||
// | functions |
|
||
// +-----------------------------------------------------------------------+
|
||
|
||
/**
|
||
* returns informations from IPTC metadata, mapping is done at the beginning
|
||
* of the function
|
||
*
|
||
* @param string $filename
|
||
* @return array
|
||
*/
|
||
function get_iptc_data($filename, $map)
|
||
{
|
||
$result = array();
|
||
|
||
// Read IPTC data
|
||
$iptc = array();
|
||
|
||
$imginfo = array();
|
||
getimagesize($filename, $imginfo);
|
||
|
||
if (isset($imginfo['APP13']))
|
||
{
|
||
$iptc = iptcparse($imginfo['APP13']);
|
||
if (is_array($iptc))
|
||
{
|
||
$rmap = array_flip($map);
|
||
foreach (array_keys($rmap) as $iptc_key)
|
||
{
|
||
if (isset($iptc[$iptc_key][0]))
|
||
{
|
||
if ($iptc_key == '2#025')
|
||
{
|
||
$value = implode(',',
|
||
array_map('clean_iptc_value',$iptc[$iptc_key]));
|
||
}
|
||
else
|
||
{
|
||
$value = clean_iptc_value($iptc[$iptc_key][0]);
|
||
}
|
||
|
||
foreach (array_keys($map, $iptc_key) as $pwg_key)
|
||
{
|
||
$result[$pwg_key] = $value;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* return a cleaned IPTC value
|
||
*
|
||
* @param string value
|
||
* @return string
|
||
*/
|
||
function clean_iptc_value($value)
|
||
{
|
||
// strip leading zeros (weird Kodak Scanner software)
|
||
while ($value[0] == chr(0))
|
||
{
|
||
$value = substr($value, 1);
|
||
}
|
||
// remove binary nulls
|
||
$value = str_replace(chr(0x00), ' ', $value);
|
||
|
||
return $value;
|
||
}
|
||
|
||
function get_sync_iptc_data($file)
|
||
{
|
||
global $conf;
|
||
|
||
$map = $conf['use_iptc_mapping'];
|
||
$datefields = array('date_creation', 'date_available');
|
||
|
||
$iptc = get_iptc_data($file, $map);
|
||
|
||
foreach ($iptc as $pwg_key => $value)
|
||
{
|
||
if (in_array($pwg_key, $datefields))
|
||
{
|
||
if ( preg_match('/(\d{4})(\d{2})(\d{2})/', $value, $matches))
|
||
{
|
||
$value = $matches[1].'-'.$matches[2].'-'.$matches[3];
|
||
}
|
||
}
|
||
if ($pwg_key == 'keywords')
|
||
{
|
||
// official keywords separator is the comma
|
||
$value = preg_replace('/[.;]/', ',', $value);
|
||
$value = preg_replace('/^,+|,+$/', '', $value);
|
||
}
|
||
$iptc[$pwg_key] = htmlentities($value);
|
||
}
|
||
|
||
$iptc['keywords'] = implode(
|
||
',',
|
||
array_unique(
|
||
explode(
|
||
',',
|
||
$iptc['keywords']
|
||
)
|
||
)
|
||
);
|
||
return $iptc;
|
||
}
|
||
|
||
/**
|
||
* returns a float value coresponding to the number of seconds since the
|
||
* unix epoch (1st January 1970) and the microseconds are precised :
|
||
* e.g. 1052343429.89276600
|
||
*
|
||
* @return float
|
||
*/
|
||
function get_moment()
|
||
{
|
||
$t1 = explode(' ', microtime());
|
||
$t2 = explode('.', $t1[0]);
|
||
$t2 = $t1[1].'.'.$t2[1];
|
||
return $t2;
|
||
}
|
||
|
||
/**
|
||
* returns the number of seconds (with 3 decimals precision) between the
|
||
* start time and the end time given.
|
||
*
|
||
* @param float start
|
||
* @param float end
|
||
* @return void
|
||
*/
|
||
function get_elapsed_time($start, $end)
|
||
{
|
||
return number_format($end - $start, 3, '.', ' ').' s';
|
||
}
|
||
|
||
/**
|
||
* returns an array with all picture files according to $conf['file_ext']
|
||
*
|
||
* @param string $dir
|
||
* @return array
|
||
*/
|
||
function get_pwg_files($dir)
|
||
{
|
||
global $conf;
|
||
|
||
$pictures = array();
|
||
if ($opendir = opendir($dir))
|
||
{
|
||
while ($file = readdir($opendir))
|
||
{
|
||
if (in_array(get_extension($file), $conf['file_ext']))
|
||
{
|
||
array_push($pictures, $file);
|
||
if (!preg_match('/^[a-zA-Z0-9-_.]+$/', $file))
|
||
{
|
||
echo 'PWG-WARNING-2: "'.$file.'" : ';
|
||
echo 'The name of the file should be composed of ';
|
||
echo 'letters, figures, "-", "_" or "." ONLY';
|
||
echo "\n";
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return $pictures;
|
||
}
|
||
|
||
/**
|
||
* returns an array with all thumbnails according to $conf['picture_ext']
|
||
* and $conf['prefix_thumbnail']
|
||
*
|
||
* @param string $dir
|
||
* @return array
|
||
*/
|
||
function get_thumb_files($dir)
|
||
{
|
||
global $conf;
|
||
|
||
$prefix_length = strlen($conf['prefix_thumbnail']);
|
||
|
||
$thumbnails = array();
|
||
if (is_dir($dir.'/thumbnail'))
|
||
{
|
||
if ($opendir = opendir($dir.'/thumbnail'))
|
||
{
|
||
while ($file = readdir($opendir))
|
||
{
|
||
if (in_array(get_extension($file), $conf['picture_ext'])
|
||
and substr($file,0,$prefix_length) == $conf['prefix_thumbnail'])
|
||
{
|
||
array_push($thumbnails, $file);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return $thumbnails;
|
||
}
|
||
|
||
/**
|
||
* returns an array with representative picture files of a directory
|
||
* according to $conf['picture_ext']
|
||
*
|
||
* @param string $dir
|
||
* @return array
|
||
*/
|
||
function get_representative_files($dir)
|
||
{
|
||
global $conf;
|
||
|
||
$pictures = array();
|
||
if (is_dir($dir.'/pwg_representative'))
|
||
{
|
||
if ($opendir = opendir($dir.'/pwg_representative'))
|
||
{
|
||
while ($file = readdir($opendir))
|
||
{
|
||
if (in_array(get_extension($file), $conf['picture_ext']))
|
||
{
|
||
array_push($pictures, $file);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return $pictures;
|
||
}
|
||
|
||
/**
|
||
* returns an array with high quality/resolution picture files of a directory
|
||
* according to $conf['picture_ext']
|
||
*
|
||
* @param string $dir
|
||
* @return array
|
||
*/
|
||
function get_high_files($dir)
|
||
{
|
||
global $conf;
|
||
|
||
$pictures = array();
|
||
if (is_dir($dir.'/pwg_high'))
|
||
{
|
||
if ($opendir = opendir($dir.'/pwg_high'))
|
||
{
|
||
while ($file = readdir($opendir))
|
||
{
|
||
if (in_array(get_extension($file), $conf['picture_ext']))
|
||
{
|
||
array_push($pictures, $file);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return $pictures;
|
||
}
|
||
|
||
/**
|
||
* search in $basedir the sub-directories and calls get_pictures
|
||
*
|
||
* @return void
|
||
*/
|
||
function get_dirs($basedir, $indent, $level)
|
||
{
|
||
$fs_dirs = array();
|
||
$dirs = "";
|
||
global $conf_safe_mode;
|
||
|
||
// Refresh the max_execution_time to avoid timout error
|
||
// By default time to scan a directory (without subdirs) is fixed to 30 seconds
|
||
if (!$conf_safe_mode)
|
||
{
|
||
set_time_limit(30);
|
||
}
|
||
|
||
if ($opendir = opendir($basedir))
|
||
{
|
||
while ($file = readdir($opendir))
|
||
{
|
||
if ($file != '.'
|
||
and $file != '..'
|
||
and $file != '.svn'
|
||
and $file != 'thumbnail'
|
||
and $file != 'pwg_high'
|
||
and $file != 'pwg_representative'
|
||
and is_dir ($basedir.'/'.$file))
|
||
{
|
||
array_push($fs_dirs, $file);
|
||
if (!preg_match('/^[a-zA-Z0-9-_.]+$/', $file))
|
||
{
|
||
echo 'PWG-WARNING-1: "'.$file.'" : ';
|
||
echo 'The name of the directory should be composed of ';
|
||
echo 'letters, figures, "-", "_" or "." ONLY';
|
||
echo "\n";
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// write of the dirs
|
||
foreach ($fs_dirs as $fs_dir)
|
||
{
|
||
$dirs.= "\n".$indent.'<dir'.$level.' name="'.$fs_dir.'">';
|
||
$dirs.= get_pictures($basedir.'/'.$fs_dir, $indent.' ');
|
||
$dirs.= get_dirs($basedir.'/'.$fs_dir, $indent.' ', $level + 1);
|
||
$dirs.= "\n".$indent.'</dir'.$level.'>';
|
||
}
|
||
return $dirs;
|
||
}
|
||
|
||
// get_extension returns the part of the string after the last "."
|
||
function get_extension($filename)
|
||
{
|
||
return substr(strrchr($filename, '.'), 1, strlen ($filename));
|
||
}
|
||
|
||
// get_filename_wo_extension returns the part of the string before the last
|
||
// ".".
|
||
// get_filename_wo_extension('test.tar.gz') -> 'test.tar'
|
||
function get_filename_wo_extension($filename)
|
||
{
|
||
return substr($filename, 0, strrpos($filename, '.'));
|
||
}
|
||
|
||
function get_pictures($dir, $indent)
|
||
{
|
||
global $conf, $page;
|
||
|
||
// fs means FileSystem : $fs_files contains files in the filesystem found
|
||
// in $dir that can be managed by PhpWebGallery (see get_pwg_files
|
||
// function), $fs_thumbnails contains thumbnails, $fs_representatives
|
||
// contains potentially representative pictures for non picture files
|
||
$fs_files = get_pwg_files($dir);
|
||
$fs_thumbnails = get_thumb_files($dir);
|
||
$fs_representatives = get_representative_files($dir);
|
||
$fs_highs = get_high_files($dir);
|
||
|
||
$elements = array();
|
||
|
||
$print_dir = preg_replace('/^\.\//', '', $dir);
|
||
$print_dir = preg_replace('/\/*$/', '/', $print_dir);
|
||
|
||
foreach ($fs_files as $fs_file)
|
||
{
|
||
$element = array();
|
||
$element['file'] = $fs_file;
|
||
$element['path'] = $page['url'].$print_dir.$fs_file;
|
||
$element['filesize'] = floor(filesize($dir.'/'.$fs_file) / 1024);
|
||
|
||
$file_wo_ext = get_filename_wo_extension($fs_file);
|
||
|
||
foreach ($conf['picture_ext'] as $ext)
|
||
{
|
||
$test = $conf['prefix_thumbnail'].$file_wo_ext.'.'.$ext;
|
||
if (!in_array($test, $fs_thumbnails))
|
||
{
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
$element['tn_ext'] = $ext;
|
||
break;
|
||
}
|
||
}
|
||
|
||
// 2 cases : the element is a picture or not. Indeed, for a picture
|
||
// thumbnail is mandatory, high is optional and for non picture element,
|
||
// thumbnail and representative is optionnal
|
||
if (in_array(get_extension($fs_file), $conf['picture_ext']))
|
||
{
|
||
// if we found a thumnbnail corresponding to our picture...
|
||
if (isset($element['tn_ext']))
|
||
{
|
||
if ($image_size = @getimagesize($dir.'/'.$fs_file))
|
||
{
|
||
$element['width'] = $image_size[0];
|
||
$element['height'] = $image_size[1];
|
||
}
|
||
|
||
if ( in_array($fs_file, $fs_highs) )
|
||
{
|
||
$element['has_high'] = 'true';
|
||
}
|
||
|
||
if ($conf['use_exif'])
|
||
{
|
||
// Verify activation of exif module
|
||
if (extension_loaded('exif'))
|
||
{
|
||
if ($exif = read_exif_data($dir.'/'.$fs_file))
|
||
{
|
||
foreach ($conf['use_exif_mapping'] as $pwg_key => $exif_key )
|
||
{
|
||
if (isset($exif[$exif_key]))
|
||
{
|
||
if ( in_array($pwg_key, array('date_creation','date_available') ) )
|
||
{
|
||
if (preg_match('/^(\d{4}):(\d{2}):(\d{2})/'
|
||
,$exif[$exif_key]
|
||
,$matches))
|
||
{
|
||
$element[$pwg_key] =
|
||
$matches[1].'-'.$matches[2].'-'.$matches[3];
|
||
}
|
||
}
|
||
else
|
||
{
|
||
$element[$pwg_key] = $exif[$exif_key];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if ($conf['use_iptc'])
|
||
{
|
||
$iptc = get_sync_iptc_data($dir.'/'.$fs_file);
|
||
if (count($iptc) > 0)
|
||
{
|
||
foreach (array_keys($iptc) as $key)
|
||
{
|
||
$element[$key] = $iptc[$key];
|
||
}
|
||
}
|
||
}
|
||
|
||
array_push($elements, $element);
|
||
}
|
||
else
|
||
{
|
||
echo 'PWG-ERROR-1: The thumbnail is missing for '.$dir.'/'.$fs_file;
|
||
echo '-> '.$dir.'/thumbnail/';
|
||
echo $conf['prefix_thumbnail'].$file_wo_ext.'.xxx';
|
||
echo ' ("xxx" can be : ';
|
||
echo implode(', ', $conf['picture_ext']);
|
||
echo ')'."\n";
|
||
}
|
||
}
|
||
else
|
||
{
|
||
foreach ($conf['picture_ext'] as $ext)
|
||
{
|
||
$candidate = $file_wo_ext.'.'.$ext;
|
||
if (!in_array($candidate, $fs_representatives))
|
||
{
|
||
continue;
|
||
}
|
||
else
|
||
{
|
||
$element['representative_ext'] = $ext;
|
||
break;
|
||
}
|
||
}
|
||
|
||
array_push($elements, $element);
|
||
}
|
||
}
|
||
|
||
$xml = "\n".$indent.'<root>';
|
||
$attributes = array('file','tn_ext','representative_ext','filesize',
|
||
'width','height','date_creation','author','keywords',
|
||
'name','comment','has_high', 'path');
|
||
foreach ($elements as $element)
|
||
{
|
||
$xml.= "\n".$indent.' ';
|
||
$xml.= '<element';
|
||
foreach ($attributes as $attribute)
|
||
{
|
||
if (isset($element{$attribute}))
|
||
{
|
||
$xml.= ' '.$attribute.'="'.$element{$attribute}.'"';
|
||
}
|
||
}
|
||
$xml.= ' />';
|
||
}
|
||
$xml.= "\n".$indent.'</root>';
|
||
|
||
return $xml;
|
||
}
|
||
|
||
// +-----------------------------------------------------------------------+
|
||
// | script |
|
||
// +-----------------------------------------------------------------------+
|
||
if (isset($_GET['action']))
|
||
{
|
||
$page['action'] = $_GET['action'];
|
||
}
|
||
else
|
||
{
|
||
$page['action'] = '';
|
||
}
|
||
|
||
// Looking at the safe_mode configuration for execution time
|
||
$conf_safe_mode = TRUE;
|
||
if (ini_get('safe_mode') == 0)
|
||
{
|
||
$conf_safe_mode = FALSE;
|
||
}
|
||
|
||
echo '<pre>';
|
||
switch ($page['action'])
|
||
{
|
||
case 'generate' :
|
||
{
|
||
$start = get_moment();
|
||
|
||
$listing = '<informations';
|
||
$listing.= ' generation_date="'.date('Y-m-d').'"';
|
||
$listing.= ' phpwg_version="'.htmlentities($conf{'version'}).'"';
|
||
|
||
$attrs=array();
|
||
if ($conf['use_iptc'])
|
||
{
|
||
$attrs = array_merge($attrs, array_keys($conf['use_iptc_mapping']) );
|
||
}
|
||
if ($conf['use_exif'])
|
||
{
|
||
$attrs = array_merge($attrs, array_keys($conf['use_exif_mapping']) );
|
||
}
|
||
$listing.= ' metadata="'.implode(',',array_unique($attrs)).'"';
|
||
|
||
$end = strrpos($_SERVER['PHP_SELF'], '/') + 1;
|
||
$local_folder = substr($_SERVER['PHP_SELF'], 0, $end);
|
||
$page['url'] = 'http://'.$_SERVER['HTTP_HOST'].$local_folder;
|
||
|
||
$listing.= ' url="'.$page['url'].'"';
|
||
$listing.= '/>'."\n";
|
||
|
||
$listing.= get_dirs('.', '', 0);
|
||
|
||
if ($fp = @fopen("./listing.xml","w"))
|
||
{
|
||
fwrite($fp, $listing);
|
||
fclose($fp);
|
||
echo 'PWG-INFO-1: listing.xml created in ';
|
||
echo get_elapsed_time($start, get_moment());
|
||
echo "\n";
|
||
}
|
||
else
|
||
{
|
||
echo "PWG-ERROR-2: I can't write the file listing.xml"."\n";
|
||
}
|
||
break;
|
||
}
|
||
case 'test' :
|
||
{
|
||
if (isset($_GET['version']))
|
||
{
|
||
if ($_GET['version'] != $conf['version'])
|
||
{
|
||
echo 'PWG-ERROR-4: PhpWebGallery versions differs'."\n";
|
||
}
|
||
else
|
||
{
|
||
echo 'PWG-INFO-2: test successful'."\n";
|
||
}
|
||
}
|
||
else
|
||
{
|
||
echo 'PWG-INFO-2: test successful'."\n";
|
||
}
|
||
break;
|
||
}
|
||
case 'clean' :
|
||
{
|
||
if( @unlink('./listing.xml'))
|
||
{
|
||
echo 'PWG-INFO-3 : listing.xml file deleted'."\n";
|
||
}
|
||
else
|
||
{
|
||
echo 'PWG-ERROR-3 : listing.xml does not exist'."\n";
|
||
}
|
||
break;
|
||
}
|
||
default :
|
||
{
|
||
// Menu de lancement pour la mise <20> jour manuel des sites distant
|
||
echo '</pre>
|
||
<ul>
|
||
<li>
|
||
<a href="create_listing_file.php?action=generate">Generate listing.xml</a>
|
||
</li>
|
||
|
||
<li>
|
||
<a href="create_listing_file.php?action=test">Test</a>
|
||
</li>
|
||
|
||
<li>
|
||
<a href="create_listing_file.php?action=clean">Clean</a>
|
||
</li>
|
||
</ul>
|
||
<pre>';
|
||
}
|
||
}
|
||
echo '</pre>';
|
||
?>
|