source: trunk/include/functions_metadata.inc.php @ 31222

Last change on this file since 31222 was 30887, checked in by plg, 10 years ago

feature 2943: ability to display metadata (via plugin) even if Piwigo core
finds no EXIF. Patch by xbgmsharp (will be used by plugin videoJS).

  • Property svn:eol-style set to LF
File size: 6.8 KB
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | Piwigo - a PHP based photo gallery                                    |
4// +-----------------------------------------------------------------------+
5// | Copyright(C) 2008-2014 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
24/**
25 * @package functions\metadata
26 */
27
28
29/**
30 * returns informations from IPTC metadata, mapping is done in this function.
31 *
32 * @param string $filename
33 * @param array $map
34 * @return array
35 */
36function get_iptc_data($filename, $map, $array_sep=',')
37{
38  global $conf;
39 
40  $result = array();
41
42  $imginfo = array();
43  if (false == @getimagesize($filename, $imginfo) )
44  {
45    return $result;
46  }
47
48  if (isset($imginfo['APP13']))
49  {
50    $iptc = iptcparse($imginfo['APP13']);
51    if (is_array($iptc))
52    {
53      $rmap = array_flip($map);
54      foreach (array_keys($rmap) as $iptc_key)
55      {
56        if (isset($iptc[$iptc_key][0]))
57        {
58          if ($iptc_key == '2#025')
59          {
60            $value = implode($array_sep,
61                             array_map('clean_iptc_value',$iptc[$iptc_key]));
62          }
63          else
64          {
65            $value = clean_iptc_value($iptc[$iptc_key][0]);
66          }
67
68          foreach (array_keys($map, $iptc_key) as $pwg_key)
69          {
70            $result[$pwg_key] = $value;
71
72            if (!$conf['allow_html_in_metadata'])
73            {
74              // in case the origin of the photo is unsecure (user upload), we
75              // remove HTML tags to avoid XSS (malicious execution of
76              // javascript)
77              $result[$pwg_key] = strip_tags($result[$pwg_key]);
78            }
79          }
80        }
81      }
82    }
83  }
84  return $result;
85}
86
87/**
88 * return a cleaned IPTC value.
89 *
90 * @param string $value
91 * @return string
92 */
93function clean_iptc_value($value)
94{
95  // strip leading zeros (weird Kodak Scanner software)
96  while ( isset($value[0]) and $value[0] == chr(0))
97  {
98    $value = substr($value, 1);
99  }
100  // remove binary nulls
101  $value = str_replace(chr(0x00), ' ', $value);
102
103  if ( preg_match('/[\x80-\xff]/', $value) )
104  {
105    // apparently mac uses some MacRoman crap encoding. I don't know
106    // how to detect it so a plugin should do the trick.
107    $value = trigger_change('clean_iptc_value', $value);
108    if ( ($qual = qualify_utf8($value)) != 0)
109    {// has non ascii chars
110      if ($qual>0)
111      {
112        $input_encoding = 'utf-8';
113      }
114      else
115      {
116        $input_encoding = 'iso-8859-1';
117        if (function_exists('iconv') or function_exists('mb_convert_encoding'))
118        {
119          // using windows-1252 because it supports additional characters
120          // such as "oe" in a single character (ligature). About the
121          // difference between Windows-1252 and ISO-8859-1: the characters
122          // 0x80-0x9F will not convert correctly. But these are control
123          // characters which are almost never used.
124          $input_encoding = 'windows-1252';
125        }
126      }
127     
128      $value = convert_charset($value, $input_encoding, get_pwg_charset());
129    }
130  }
131  return $value;
132}
133
134/**
135 * returns informations from EXIF metadata, mapping is done in this function.
136 *
137 * @param string $filename
138 * @param array $map
139 * @return array
140 */
141function get_exif_data($filename, $map)
142{
143  global $conf;
144 
145  $result = array();
146
147  if (!function_exists('read_exif_data'))
148  {
149    die('Exif extension not available, admin should disable exif use');
150  }
151
152  // Read EXIF data
153  if ($exif = @read_exif_data($filename) or $exif2 = trigger_change('format_exif_data', $exif=null, $filename, $map))
154  {
155    if (!empty($exif2))
156    {
157      $exif = $exif2;
158    }
159    else
160    {
161      $exif = trigger_change('format_exif_data', $exif, $filename, $map);
162    }
163
164    // configured fields
165    foreach ($map as $key => $field)
166    {
167      if (strpos($field, ';') === false)
168      {
169        if (isset($exif[$field]))
170        {
171          $result[$key] = $exif[$field];
172        }
173      }
174      else
175      {
176        $tokens = explode(';', $field);
177        if (isset($exif[$tokens[0]][$tokens[1]]))
178        {
179          $result[$key] = $exif[$tokens[0]][$tokens[1]];
180        }
181      }
182    }
183
184    // GPS data
185    $gps_exif = array_intersect_key($exif, array_flip(array('GPSLatitudeRef', 'GPSLatitude', 'GPSLongitudeRef', 'GPSLongitude')));
186    if (count($gps_exif) == 4)
187    {
188      if (
189        is_array($gps_exif['GPSLatitude'])  and in_array($gps_exif['GPSLatitudeRef'], array('S', 'N')) and
190        is_array($gps_exif['GPSLongitude']) and in_array($gps_exif['GPSLongitudeRef'], array('W', 'E'))
191        )
192      {
193        $result['latitude'] = parse_exif_gps_data($gps_exif['GPSLatitude'], $gps_exif['GPSLatitudeRef']);
194        $result['longitude'] = parse_exif_gps_data($gps_exif['GPSLongitude'], $gps_exif['GPSLongitudeRef']);
195      }
196    }
197  }
198
199  if (!$conf['allow_html_in_metadata'])
200  {
201    foreach ($result as $key => $value)
202    {
203      // in case the origin of the photo is unsecure (user upload), we remove
204      // HTML tags to avoid XSS (malicious execution of javascript)
205      $result[$key] = strip_tags($value);
206    }
207  }
208
209  return $result;
210}
211
212
213/**
214 * Converts EXIF GPS format to a float value.
215 * @since 2.6
216 *
217 * @param string[] $raw eg:
218 *    - 41/1
219 *    - 54/1
220 *    - 9843/500
221 * @param string $ref 'S', 'N', 'E', 'W'. eg: 'N'
222 * @return float eg: 41.905468
223 */
224function parse_exif_gps_data($raw, $ref)
225{
226  foreach ($raw as &$i)
227  {
228    $i = explode('/', $i);
229    $i = $i[1]==0 ? 0 : $i[0]/$i[1];
230  }
231  unset($i);
232
233  $v = $raw[0] + $raw[1]/60 + $raw[2]/3600;
234
235  $ref = strtoupper($ref);
236  if ($ref == 'S' or $ref == 'W') $v= -$v;
237
238  return $v;
239}
240
241?>
Note: See TracBrowser for help on using the repository browser.