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

Last change on this file since 28913 was 28587, checked in by mistic100, 10 years ago

feature 3010 : replace trigger_action/event by trigger_notify/change

  • Property svn:eol-style set to LF
File size: 6.7 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))
154  {
155    $exif = trigger_change('format_exif_data', $exif, $filename, $map);
156
157    // configured fields
158    foreach ($map as $key => $field)
159    {
160      if (strpos($field, ';') === false)
161      {
162        if (isset($exif[$field]))
163        {
164          $result[$key] = $exif[$field];
165        }
166      }
167      else
168      {
169        $tokens = explode(';', $field);
170        if (isset($exif[$tokens[0]][$tokens[1]]))
171        {
172          $result[$key] = $exif[$tokens[0]][$tokens[1]];
173        }
174      }
175    }
176
177    // GPS data
178    $gps_exif = array_intersect_key($exif, array_flip(array('GPSLatitudeRef', 'GPSLatitude', 'GPSLongitudeRef', 'GPSLongitude')));
179    if (count($gps_exif) == 4)
180    {
181      if (
182        is_array($gps_exif['GPSLatitude'])  and in_array($gps_exif['GPSLatitudeRef'], array('S', 'N')) and
183        is_array($gps_exif['GPSLongitude']) and in_array($gps_exif['GPSLongitudeRef'], array('W', 'E'))
184        )
185      {
186        $result['latitude'] = parse_exif_gps_data($gps_exif['GPSLatitude'], $gps_exif['GPSLatitudeRef']);
187        $result['longitude'] = parse_exif_gps_data($gps_exif['GPSLongitude'], $gps_exif['GPSLongitudeRef']);
188      }
189    }
190  }
191
192  if (!$conf['allow_html_in_metadata'])
193  {
194    foreach ($result as $key => $value)
195    {
196      // in case the origin of the photo is unsecure (user upload), we remove
197      // HTML tags to avoid XSS (malicious execution of javascript)
198      $result[$key] = strip_tags($value);
199    }
200  }
201
202  return $result;
203}
204
205
206/**
207 * Converts EXIF GPS format to a float value.
208 * @since 2.6
209 *
210 * @param string[] $raw eg:
211 *    - 41/1
212 *    - 54/1
213 *    - 9843/500
214 * @param string $ref 'S', 'N', 'E', 'W'. eg: 'N'
215 * @return float eg: 41.905468
216 */
217function parse_exif_gps_data($raw, $ref)
218{
219  foreach ($raw as &$i)
220  {
221    $i = explode('/', $i);
222    $i = $i[1]==0 ? 0 : $i[0]/$i[1];
223  }
224  unset($i);
225
226  $v = $raw[0] + $raw[1]/60 + $raw[2]/3600;
227
228  $ref = strtoupper($ref);
229  if ($ref == 'S' or $ref == 'W') $v= -$v;
230
231  return $v;
232}
233
234?>
Note: See TracBrowser for help on using the repository browser.