NextGEN Gallery – WordPress Gallery Plugin - Version 1.9.13

Version Description

  • 06.11.2013 =
  • NEW: Slideshows are now centered to their content area
  • Secured: Ensure that only logged in users can upload images
  • Fixed: Import date is presered are no longer Jan 1 1970
  • Fixed: Removed mention of upgrade.php, which no longer exists
Download this release

Release Info

Developer photocrati
Plugin Icon 128x128 NextGEN Gallery – WordPress Gallery Plugin
Version 1.9.13
Comparing to
See all releases

Code changes from version 1.9.12 to 1.9.13

admin/addgallery.php CHANGED
@@ -186,6 +186,9 @@ class nggAddGallery {
186
  preinit : {
187
  Init: function(up, info) {
188
  debug('[Init]', 'Info :', info, 'Features :', up.features);
 
 
 
189
  initUploader();
190
  }
191
  },
186
  preinit : {
187
  Init: function(up, info) {
188
  debug('[Init]', 'Info :', info, 'Features :', up.features);
189
+ if (navigator.appVersion.indexOf("MSIE 10") > -1) {
190
+ up.features.triggerDialog = true;
191
+ }
192
  initUploader();
193
  }
194
  },
admin/functions.php CHANGED
@@ -1040,7 +1040,7 @@ class nggAdmin{
1040
  * @param integer $galleryID
1041
  * @return string $result
1042
  */
1043
- function swfupload_image($galleryID = 0) {
1044
 
1045
  global $nggdb;
1046
 
1040
  * @param integer $galleryID
1041
  * @return string $result
1042
  */
1043
+ static function swfupload_image($galleryID = 0) {
1044
 
1045
  global $nggdb;
1046
 
admin/settings.php CHANGED
@@ -198,7 +198,6 @@ class nggOptions {
198
 
199
  if ( isset($_POST['createslugs']) ) {
200
  check_admin_referer('ngg_settings');
201
- include_once (dirname (__FILE__) . '/upgrade.php');
202
  ngg_rebuild_unique_slugs::start_rebuild();
203
  }
204
 
198
 
199
  if ( isset($_POST['createslugs']) ) {
200
  check_admin_referer('ngg_settings');
 
201
  ngg_rebuild_unique_slugs::start_rebuild();
202
  }
203
 
admin/upload.php CHANGED
@@ -18,22 +18,23 @@ if ( empty($_COOKIE[LOGGED_IN_COOKIE]) && !empty($_REQUEST['logged_in_cookie'])
18
 
19
  header('Content-Type: text/plain; charset=' . get_option('blog_charset'));
20
 
 
 
21
  if (wp_validate_auth_cookie()) {
22
  $results = wp_parse_auth_cookie();
23
- $logged_in = FALSE;
24
  if (isset($results['username']) && isset($results['expiration'])) {
25
  if (time() < floatval($results['expiration'])) {
26
  if (($userdata = get_user_by('login', $results['username'])))
27
  $logged_in = $userdata->ID;
28
  }
29
  }
30
-
31
- if (!$logged_in) die("Login failure. -1");
32
- else if (!user_can($logged_in, 'NextGEN Upload images')) {
33
- die('You do not have permission to upload files. -2');
34
- }
35
  }
36
 
 
 
 
 
 
37
  //check for nggallery
38
  if ( !defined('NGGALLERY_ABSPATH') )
39
  die('NextGEN Gallery not available. -3');
18
 
19
  header('Content-Type: text/plain; charset=' . get_option('blog_charset'));
20
 
21
+ $logged_in = FALSE;
22
+
23
  if (wp_validate_auth_cookie()) {
24
  $results = wp_parse_auth_cookie();
 
25
  if (isset($results['username']) && isset($results['expiration'])) {
26
  if (time() < floatval($results['expiration'])) {
27
  if (($userdata = get_user_by('login', $results['username'])))
28
  $logged_in = $userdata->ID;
29
  }
30
  }
 
 
 
 
 
31
  }
32
 
33
+ if (!$logged_in)
34
+ die("Login failure. -1");
35
+ else if (!user_can($logged_in, 'NextGEN Upload images'))
36
+ die('You do not have permission to upload files. -2');
37
+
38
  //check for nggallery
39
  if ( !defined('NGGALLERY_ABSPATH') )
40
  die('NextGEN Gallery not available. -3');
changelog.txt CHANGED
@@ -1,6 +1,12 @@
1
  NextGEN Gallery
2
  by Photocrati Media
3
 
 
 
 
 
 
 
4
  = V1.9.12 - 02.15.2013 =
5
  * Fixed: jQuery Conflict Detection was trying to dequeue irremovable scripts
6
 
1
  NextGEN Gallery
2
  by Photocrati Media
3
 
4
+ = V1.9.13 - 06.11.2013 =
5
+ * NEW: Slideshows are now centered to their content area
6
+ * Secured: Ensure that only logged in users can upload images
7
+ * Fixed: Import date is presered are no longer Jan 1 1970
8
+ * Fixed: Removed mention of upgrade.php, which no longer exists
9
+
10
  = V1.9.12 - 02.15.2013 =
11
  * Fixed: jQuery Conflict Detection was trying to dequeue irremovable scripts
12
 
css/nggallery.css CHANGED
@@ -266,6 +266,8 @@ html>body .ngg-album {
266
  .ngg-slideshow {
267
  overflow:hidden;
268
  position: relative;
 
 
269
  }
270
 
271
  .ngg-slideshow * {
266
  .ngg-slideshow {
267
  overflow:hidden;
268
  position: relative;
269
+ margin-left: auto;
270
+ margin-right: auto;
271
  }
272
 
273
  .ngg-slideshow * {
lib/meta.php CHANGED
@@ -24,547 +24,543 @@ class nggMeta{
24
 
25
  var $sanitize = false; // sanitize meta data on request
26
 
27
- /**
28
- * nggMeta::nggMeta()
29
- *
30
- * @param int $image path to a image
31
- * @param bool $onlyEXIF parse only exif if needed
32
- * @return
33
- */
34
- function nggMeta($pic_id, $onlyEXIF = false) {
35
 
36
- //get the path and other data about the image
37
- $this->image = nggdb::find_image( $pic_id );
38
 
39
- $this->image = apply_filters( 'ngg_find_image_meta', $this->image );
40
 
41
- if ( !file_exists( $this->image->imagePath ) )
42
- return false;
43
 
44
- $this->size = @getimagesize ( $this->image->imagePath , $metadata );
45
 
46
- if ($this->size && is_array($metadata)) {
47
 
48
- // get exif - data
49
- if ( is_callable('exif_read_data'))
50
  $this->exif_data = @exif_read_data($this->image->imagePath , 0, true );
51
 
52
- // stop here if we didn't need other meta data
53
- if ($onlyEXIF)
54
- return true;
55
 
56
- // get the iptc data - should be in APP13
57
- if ( is_callable('iptcparse') && isset($metadata['APP13']) )
58
  $this->iptc_data = @iptcparse($metadata['APP13']);
59
 
60
- // get the xmp data in a XML format
61
- if ( is_callable('xml_parser_create'))
62
  $this->xmp_data = $this->extract_XMP($this->image->imagePath );
63
 
64
- return true;
65
- }
66
 
67
- return false;
68
- }
69
 
70
- /**
71
- * return the saved meta data from the database
72
- *
73
- * @since 1.4.0
74
- * @param string $object (optional)
75
- * @return array|mixed return either the complete array or the single object
76
- */
77
- function get_saved_meta($object = false) {
78
 
79
- $meta = $this->image->meta_data;
80
 
81
- //check if we already import the meta data to the database
82
- if (!is_array($meta) || ($meta['saved'] != true))
83
- return false;
84
 
85
- // return one element if requested
86
- if ($object)
87
- return $meta[$object];
88
 
89
- //removed saved parameter we don't need that to show
90
- unset($meta['saved']);
91
 
92
- // and remove empty tags
93
- foreach ($meta as $key => $value) {
94
- if ( empty($value) )
95
- unset($meta[$key]);
96
- }
97
 
98
  // on request sanitize the output
99
- if ( $this->sanitize == true )
100
  array_walk( $meta , create_function('&$value', '$value = esc_html($value);'));
101
 
102
- return $meta;
103
- }
104
 
105
- /**
106
- * nggMeta::get_EXIF()
107
- * See also http://trac.wordpress.org/changeset/6313
108
- *
109
- * @return structured EXIF data
110
- */
111
- function get_EXIF($object = false) {
112
 
113
- if ( !$this->exif_data )
114
- return false;
115
 
116
- if (!is_array($this->exif_array)){
117
 
118
- $meta= array();
119
 
120
  if ( isset($this->exif_data['EXIF']) ) {
121
  $exif = $this->exif_data['EXIF'];
122
 
123
- if (!empty($exif['FNumber']))
124
- $meta['aperture'] = 'F ' . round( $this->exif_frac2dec( $exif['FNumber'] ), 2 );
125
- if (!empty($exif['Model']))
126
- $meta['camera'] = trim( $exif['Model'] );
127
- if (!empty($exif['DateTimeDigitized']))
128
- $meta['created_timestamp'] = date_i18n(get_option('date_format') . ' ' . get_option('time_format'), $this->exif_date2ts($exif['DateTimeDigitized']));
129
- else if (!empty($exif['DateTimeOriginal']))
130
- $meta['created_timestamp'] = date_i18n(get_option('date_format') . ' ' . get_option('time_format'), $this->exif_date2ts($exif['DateTimeOriginal']));
131
- if (!empty($exif['FocalLength']))
132
- $meta['focal_length'] = $this->exif_frac2dec( $exif['FocalLength'] ) . __(' mm','nggallery');
133
- if (!empty($exif['ISOSpeedRatings']))
134
- $meta['iso'] = $exif['ISOSpeedRatings'];
135
- if (!empty($exif['ExposureTime'])) {
136
- $meta['shutter_speed'] = $this->exif_frac2dec ($exif['ExposureTime']);
137
- $meta['shutter_speed'] =($meta['shutter_speed'] > 0.0 and $meta['shutter_speed'] < 1.0) ? ( '1/' . round( 1 / $meta['shutter_speed'], -1) ) : ($meta['shutter_speed']);
138
- $meta['shutter_speed'] .= __(' sec','nggallery');
139
- }
140
- //Bit 0 indicates the flash firing status
141
- if (!empty($exif['Flash']))
142
- $meta['flash'] = ( $exif['Flash'] & 1 ) ? __('Fired', 'nggallery') : __('Not fired',' nggallery');
143
  }
144
 
145
- // additional information
146
  if ( isset($this->exif_data['IFD0']) ) {
147
- $exif = $this->exif_data['IFD0'];
148
-
149
- if (!empty($exif['Model']))
150
- $meta['camera'] = $exif['Model'];
151
- if (!empty($exif['Make']))
152
- $meta['make'] = $exif['Make'];
153
- if (!empty($exif['ImageDescription']))
154
- $meta['title'] = utf8_encode($exif['ImageDescription']);
155
- if (!empty($exif['Orientation']))
156
- $meta['Orientation'] = $exif['Orientation'];
157
  }
158
 
159
- // this is done by Windows
160
  if ( isset($this->exif_data['WINXP']) ) {
161
  $exif = $this->exif_data['WINXP'];
162
 
163
- if (!empty($exif['Title']) && empty($meta['title']))
164
- $meta['title'] = utf8_encode($exif['Title']);
165
- if (!empty($exif['Author']))
166
- $meta['author'] = utf8_encode($exif['Author']);
167
- if (!empty($exif['Keywords']))
168
- $meta['tags'] = utf8_encode($exif['Keywords']);
169
- if (!empty($exif['Subject']))
170
- $meta['subject'] = utf8_encode($exif['Subject']);
171
- if (!empty($exif['Comments']))
172
- $meta['caption'] = utf8_encode($exif['Comments']);
173
  }
174
 
175
- $this->exif_array = $meta;
176
- }
177
 
178
- // return one element if requested
179
- if ( $object == true ) {
180
- $value = isset($this->exif_array[$object]) ? $this->exif_array[$object] : false;
181
- return $value;
182
- }
183
 
184
  // on request sanitize the output
185
- if ( $this->sanitize == true )
186
  array_walk( $this->exif_array , create_function('&$value', '$value = esc_html($value);'));
187
 
188
- return $this->exif_array;
189
-
190
- }
191
-
192
- // convert a fraction string to a decimal
193
- function exif_frac2dec($str) {
194
- @list( $n, $d ) = explode( '/', $str );
195
- if ( !empty($d) )
196
- return $n / $d;
197
- return $str;
198
- }
199
-
200
- // convert the exif date format to a unix timestamp
201
- function exif_date2ts($str) {
202
- // seriously, who formats a date like 'YYYY:MM:DD hh:mm:ss'?
203
- @list( $date, $time ) = explode( ' ', trim($str) );
204
- @list( $y, $m, $d ) = explode( ':', $date );
205
-
206
- return strtotime( "{$y}-{$m}-{$d} {$time}" );
207
- }
208
-
209
- /**
210
- * nggMeta::readIPTC() - IPTC Data Information for EXIF Display
211
- *
212
- * @param mixed $output_tag
213
- * @return IPTC-tags
214
- */
215
- function get_IPTC($object = false) {
216
-
217
- if (!$this->iptc_data)
218
- return false;
219
-
220
- if (!is_array($this->iptc_array)){
221
-
222
- // --------- Set up Array Functions --------- //
223
- $iptcTags = array (
224
- "2#005" => 'title',
225
- "2#007" => 'status',
226
- "2#012" => 'subject',
227
- "2#015" => 'category',
228
- "2#025" => 'keywords',
229
- "2#055" => 'created_date',
230
- "2#060" => 'created_time',
231
- "2#080" => 'author',
232
- "2#085" => 'position',
233
- "2#090" => 'city',
234
- "2#092" => 'location',
235
- "2#095" => 'state',
236
- "2#100" => 'country_code',
237
- "2#101" => 'country',
238
- "2#105" => 'headline',
239
- "2#110" => 'credit',
240
- "2#115" => 'source',
241
- "2#116" => 'copyright',
242
- "2#118" => 'contact',
243
- "2#120" => 'caption'
244
- );
245
-
246
- // var_dump($this->iptc_data);
247
- $meta = array();
248
- foreach ($iptcTags as $key => $value) {
249
- if (isset ( $this->iptc_data[$key] ) )
250
- $meta[$value] = trim(utf8_encode(implode(", ", $this->iptc_data[$key])));
251
-
252
- }
253
- $this->iptc_array = $meta;
254
- }
255
-
256
- // return one element if requested
257
- if ($object)
258
- return (isset($this->iptc_array[$object])) ? $this->iptc_array[$object] : NULL;
259
 
260
  // on request sanitize the output
261
- if ( $this->sanitize == true )
262
  array_walk( $this->iptc_array , create_function('&$value', '$value = esc_html($value);'));
263
 
264
- return $this->iptc_array;
265
- }
266
-
267
- /**
268
- * nggMeta::extract_XMP()
269
- * get XMP DATA
270
- * code by Pekka Saarinen http://photography-on-the.net
271
- *
272
- * @param mixed $filename
273
- * @return XML data
274
- */
275
- function extract_XMP( $filename ) {
276
-
277
- //TODO:Require a lot of memory, could be better
278
- ob_start();
279
- @readfile($filename);
280
- $source = ob_get_contents();
281
- ob_end_clean();
282
-
283
- $start = strpos( $source, "<x:xmpmeta" );
284
- $end = strpos( $source, "</x:xmpmeta>" );
285
- if ((!$start === false) && (!$end === false)) {
286
- $lenght = $end - $start;
287
- $xmp_data = substr($source, $start, $lenght+12 );
288
- unset($source);
289
- return $xmp_data;
290
- }
291
-
292
- unset($source);
293
- return false;
294
- }
295
-
296
- /**
297
- * nggMeta::get_XMP()
298
- *
299
- * @package Taken from http://php.net/manual/en/function.xml-parse-into-struct.php
300
- * @author Alf Marius Foss Olsen & Alex Rabe
301
- * @return XML Array or object
302
- *
303
- */
304
- function get_XMP($object = false) {
305
-
306
- if(!$this->xmp_data)
307
- return false;
308
-
309
- if (!is_array($this->xmp_array)){
310
-
311
- $parser = xml_parser_create();
312
- xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); // Dont mess with my cAsE sEtTings
313
- xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); // Dont bother with empty info
314
- xml_parse_into_struct($parser, $this->xmp_data, $values);
315
- xml_parser_free($parser);
316
-
317
- $xmlarray = array(); // The XML array
318
- $this->xmp_array = array(); // The returned array
319
- $stack = array(); // tmp array used for stacking
320
- $list_array = array(); // tmp array for list elements
321
- $list_element = false; // rdf:li indicator
322
-
323
- foreach($values as $val) {
324
-
325
- if($val['type'] == "open") {
326
- array_push($stack, $val['tag']);
327
-
328
- } elseif($val['type'] == "close") {
329
- // reset the compared stack
330
- if ($list_element == false)
331
- array_pop($stack);
332
- // reset the rdf:li indicator & array
333
- $list_element = false;
334
- $list_array = array();
335
-
336
- } elseif($val['type'] == "complete") {
337
- if ($val['tag'] == "rdf:li") {
338
- // first go one element back
339
- if ($list_element == false)
340
- array_pop($stack);
341
- $list_element = true;
342
  // do not parse empty tags
343
  if ( empty($val['value']) ) continue;
344
- // save it in our temp array
345
- $list_array[] = $val['value'];
346
- // in the case it's a list element we seralize it
347
- $value = implode(",", $list_array);
348
- $this->setArrayValue($xmlarray, $stack, $value);
349
- } else {
350
- array_push($stack, $val['tag']);
351
  // do not parse empty tags
352
  if ( !empty($val['value']) )
353
  $this->setArrayValue($xmlarray, $stack, $val['value']);
354
- array_pop($stack);
355
- }
356
- }
357
 
358
- } // foreach
359
 
360
  // don't parse a empty array
361
  if( empty($xmlarray) || empty($xmlarray['x:xmpmeta']) )
362
  return false;
363
 
364
  // cut off the useless tags
365
- $xmlarray = $xmlarray['x:xmpmeta']['rdf:RDF']['rdf:Description'];
366
-
367
- // --------- Some values from the XMP format--------- //
368
- $xmpTags = array (
369
- 'xap:CreateDate' => 'created_timestamp',
370
- 'xap:ModifyDate' => 'last_modfied',
371
- 'xap:CreatorTool' => 'tool',
372
- 'dc:format' => 'format',
373
- 'dc:title' => 'title',
374
- 'dc:creator' => 'author',
375
- 'dc:subject' => 'keywords',
376
- 'dc:description' => 'caption',
377
- 'photoshop:AuthorsPosition' => 'position',
378
- 'photoshop:City' => 'city',
379
- 'photoshop:Country' => 'country'
380
- );
381
-
382
- foreach ($xmpTags as $key => $value) {
383
- // if the kex exist
384
- if ( isset($xmlarray[$key]) ) {
385
- switch ($key) {
386
- case 'xap:CreateDate':
387
- case 'xap:ModifyDate':
388
- $this->xmp_array[$value] = date_i18n(get_option('date_format').' '.get_option('time_format'), strtotime($xmlarray[$key]));
389
- break;
390
- default :
391
- $this->xmp_array[$value] = $xmlarray[$key];
392
- }
393
- }
394
- }
395
-
396
- }
397
-
398
- // return one element if requested
399
- if ($object != false )
400
- return isset($this->xmp_array[$object]) ? $this->xmp_array[$object] : false;
401
 
402
  // on request sanitize the output
403
- if ( $this->sanitize == true )
404
  array_walk( $this->xmp_array , create_function('&$value', '$value = esc_html($value);'));
405
 
406
- return $this->xmp_array;
407
- }
408
 
409
- function setArrayValue(&$array, $stack, $value) {
410
- if ($stack) {
411
- $key = array_shift($stack);
412
  $this->setArrayValue($array[$key], $stack, $value);
413
- return $array;
414
- } else {
415
- $array = $value;
416
- }
417
- }
418
-
419
- /**
420
- * nggMeta::get_META() - return a meta value form the available list
421
- *
422
- * @param string $object
423
- * @return mixed $value
424
- */
425
- function get_META($object = false) {
426
-
427
- // defined order first look into database, then XMP, IPTC and EXIF.
428
- if ($value = $this->get_saved_meta($object))
429
- return $value;
430
- if ($value = $this->get_XMP($object))
431
- return $value;
432
- if ($value = $this->get_IPTC($object))
433
- return $value;
434
- if ($value = $this->get_EXIF($object))
435
- return $value;
436
-
437
- // nothing found ?
438
- return false;
439
- }
440
-
441
- /**
442
- * nggMeta::i8n_name() - localize the tag name
443
- *
444
- * @param mixed $key
445
- * @return translated $key
446
- */
447
- function i8n_name($key) {
448
-
449
- $tagnames = array(
450
- 'aperture' => __('Aperture','nggallery'),
451
- 'credit' => __('Credit','nggallery'),
452
- 'camera' => __('Camera','nggallery'),
453
- 'caption' => __('Caption','nggallery'),
454
- 'created_timestamp' => __('Date/Time','nggallery'),
455
- 'copyright' => __('Copyright','nggallery'),
456
- 'focal_length' => __('Focal length','nggallery'),
457
- 'iso' => __('ISO','nggallery'),
458
- 'shutter_speed' => __('Shutter speed','nggallery'),
459
- 'title' => __('Title','nggallery'),
460
- 'author' => __('Author','nggallery'),
461
- 'tags' => __('Tags','nggallery'),
462
- 'subject' => __('Subject','nggallery'),
463
- 'make' => __('Make','nggallery'),
464
- 'status' => __('Edit Status','nggallery'),
465
- 'category' => __('Category','nggallery'),
466
- 'keywords' => __('Keywords','nggallery'),
467
- 'created_date' => __('Date Created','nggallery'),
468
- 'created_time' => __('Time Created','nggallery'),
469
- 'position' => __('Author Position','nggallery'),
470
- 'city' => __('City','nggallery'),
471
- 'location' => __('Location','nggallery'),
472
- 'state' => __('Province/State','nggallery'),
473
- 'country_code' => __('Country code','nggallery'),
474
- 'country' => __('Country','nggallery'),
475
- 'headline' => __('Headline','nggallery'),
476
- 'credit' => __('Credit','nggallery'),
477
- 'source' => __('Source','nggallery'),
478
- 'copyright' => __('Copyright Notice','nggallery'),
479
- 'contact' => __('Contact','nggallery'),
480
- 'last_modfied' => __('Last modified','nggallery'),
481
- 'tool' => __('Program tool','nggallery'),
482
- 'format' => __('Format','nggallery'),
483
- 'width' => __('Image Width','nggallery'),
484
- 'height' => __('Image Height','nggallery'),
485
- 'flash' => __('Flash','nggallery')
486
- );
487
-
488
- if ( isset($tagnames[$key]) )
489
  $key = $tagnames[$key];
490
 
491
- return($key);
492
 
493
- }
494
 
495
- /**
496
- * Return the Timestamp from the image , if possible it's read from exif data
497
- *
498
- * @return
499
- */
500
- function get_date_time() {
501
 
502
- $date_time = false;
503
 
504
- // get exif - data
505
- if ( isset( $this->exif_data['EXIF']) ) {
506
 
507
  // try to read the date / time from the exif
508
- foreach (array('DateTimeDigitized', 'DateTimeOriginal', 'FileDateTime') as $key) {
509
- if (isset($this->exif_data['EXIF'][$key])) {
510
- $date_time = $this->exif_data['EXIF'][$key];
511
- }
512
- }
513
-
514
- if (!$date_time) $date_time = $this->exif_date2ts($date_time);
515
-
516
- } else {
517
- // if no other date available, get the filetime
518
- $date_time = @filectime($this->image->imagePath );
519
- }
520
-
521
- // Return the MySQL format
522
- $date_time = date( 'Y-m-d H:i:s', $date_time );
523
-
524
- return $date_time;
525
- }
526
-
527
- /**
528
- * This function return the most common metadata, via a filter we can add more
529
- * Reason : GD manipulation removes that options
530
- *
531
- * @since V1.4.0
532
- * @return void
533
- */
534
- function get_common_meta() {
535
- global $wpdb;
536
-
537
- $meta = array(
538
- 'aperture' => 0,
539
- 'credit' => '',
540
- 'camera' => '',
541
- 'caption' => '',
542
- 'created_timestamp' => 0,
543
- 'copyright' => '',
544
- 'focal_length' => 0,
545
- 'iso' => 0,
546
- 'shutter_speed' => 0,
547
- 'flash' => 0,
548
- 'title' => '',
549
- 'keywords' => ''
550
- );
551
-
552
- $meta = apply_filters( 'ngg_read_image_metadata', $meta );
553
-
554
- // meta should be still an array
555
- if ( !is_array($meta) )
556
- return false;
557
-
558
- foreach ($meta as $key => $value) {
559
- $meta[$key] = $this->get_META($key);
560
- }
561
-
562
- //let's add now the size of the image
563
- $meta['width'] = $this->size[0];
564
- $meta['height'] = $this->size[1];
565
-
566
- return $meta;
567
- }
568
 
569
  /**
570
  * If needed sanitize each value before output
@@ -575,6 +571,4 @@ class nggMeta{
575
  $this->sanitize = true;
576
  }
577
 
578
- }
579
-
580
- ?>
24
 
25
  var $sanitize = false; // sanitize meta data on request
26
 
27
+ /**
28
+ * Parses the nggMeta data only if needed
29
+ * @param int $image path to a image
30
+ * @param bool $onlyEXIF parse only exif if needed
31
+ * @return
32
+ */
33
+ function nggMeta($pic_id, $onlyEXIF = false) {
 
34
 
35
+ //get the path and other data about the image
36
+ $this->image = nggdb::find_image( $pic_id );
37
 
38
+ $this->image = apply_filters( 'ngg_find_image_meta', $this->image );
39
 
40
+ if ( !file_exists( $this->image->imagePath ) )
41
+ return false;
42
 
43
+ $this->size = @getimagesize ( $this->image->imagePath , $metadata );
44
 
45
+ if ($this->size && is_array($metadata)) {
46
 
47
+ // get exif - data
48
+ if ( is_callable('exif_read_data'))
49
  $this->exif_data = @exif_read_data($this->image->imagePath , 0, true );
50
 
51
+ // stop here if we didn't need other meta data
52
+ if ($onlyEXIF)
53
+ return true;
54
 
55
+ // get the iptc data - should be in APP13
56
+ if ( is_callable('iptcparse') && isset($metadata['APP13']) )
57
  $this->iptc_data = @iptcparse($metadata['APP13']);
58
 
59
+ // get the xmp data in a XML format
60
+ if ( is_callable('xml_parser_create'))
61
  $this->xmp_data = $this->extract_XMP($this->image->imagePath );
62
 
63
+ return true;
64
+ }
65
 
66
+ return false;
67
+ }
68
 
69
+ /**
70
+ * return the saved meta data from the database
71
+ *
72
+ * @since 1.4.0
73
+ * @param string $object (optional)
74
+ * @return array|mixed return either the complete array or the single object
75
+ */
76
+ function get_saved_meta($object = false) {
77
 
78
+ $meta = $this->image->meta_data;
79
 
80
+ //check if we already import the meta data to the database
81
+ if (!is_array($meta) || ($meta['saved'] != true))
82
+ return false;
83
 
84
+ // return one element if requested
85
+ if ($object)
86
+ return $meta[$object];
87
 
88
+ //removed saved parameter we don't need that to show
89
+ unset($meta['saved']);
90
 
91
+ // and remove empty tags or arrays
92
+ foreach ($meta as $key => $value) {
93
+ if ( empty($value) OR is_array($value))
94
+ unset($meta[$key]);
95
+ }
96
 
97
  // on request sanitize the output
98
+ if ( $this->sanitize == true )
99
  array_walk( $meta , create_function('&$value', '$value = esc_html($value);'));
100
 
101
+ return $meta;
102
+ }
103
 
104
+ /**
105
+ * nggMeta::get_EXIF()
106
+ * See also http://trac.wordpress.org/changeset/6313
107
+ *
108
+ * @return structured EXIF data
109
+ */
110
+ function get_EXIF($object = false) {
111
 
112
+ if ( !$this->exif_data )
113
+ return false;
114
 
115
+ if (!is_array($this->exif_array)){
116
 
117
+ $meta= array();
118
 
119
  if ( isset($this->exif_data['EXIF']) ) {
120
  $exif = $this->exif_data['EXIF'];
121
 
122
+ if (!empty($exif['FNumber']))
123
+ $meta['aperture'] = 'F ' . round( $this->exif_frac2dec( $exif['FNumber'] ), 2 );
124
+ if (!empty($exif['Model']))
125
+ $meta['camera'] = trim( $exif['Model'] );
126
+ if (!empty($exif['DateTimeDigitized']))
127
+ $meta['created_timestamp'] = date_i18n(get_option('date_format') . ' ' . get_option('time_format'), $this->exif_date2ts($exif['DateTimeDigitized']));
128
+ else if (!empty($exif['DateTimeOriginal']))
129
+ $meta['created_timestamp'] = date_i18n(get_option('date_format') . ' ' . get_option('time_format'), $this->exif_date2ts($exif['DateTimeOriginal']));
130
+ if (!empty($exif['FocalLength']))
131
+ $meta['focal_length'] = $this->exif_frac2dec( $exif['FocalLength'] ) . __(' mm','nggallery');
132
+ if (!empty($exif['ISOSpeedRatings']))
133
+ $meta['iso'] = $exif['ISOSpeedRatings'];
134
+ if (!empty($exif['ExposureTime'])) {
135
+ $meta['shutter_speed'] = $this->exif_frac2dec ($exif['ExposureTime']);
136
+ $meta['shutter_speed'] =($meta['shutter_speed'] > 0.0 and $meta['shutter_speed'] < 1.0) ? ( '1/' . round( 1 / $meta['shutter_speed'], -1) ) : ($meta['shutter_speed']);
137
+ $meta['shutter_speed'] .= __(' sec','nggallery');
138
+ }
139
+ //Bit 0 indicates the flash firing status
140
+ if (!empty($exif['Flash']))
141
+ $meta['flash'] = ( $exif['Flash'] & 1 ) ? __('Fired', 'nggallery') : __('Not fired',' nggallery');
142
  }
143
 
144
+ // additional information
145
  if ( isset($this->exif_data['IFD0']) ) {
146
+ $exif = $this->exif_data['IFD0'];
147
+
148
+ if (!empty($exif['Model']))
149
+ $meta['camera'] = $exif['Model'];
150
+ if (!empty($exif['Make']))
151
+ $meta['make'] = $exif['Make'];
152
+ if (!empty($exif['ImageDescription']))
153
+ $meta['title'] = utf8_encode($exif['ImageDescription']);
154
+ if (!empty($exif['Orientation']))
155
+ $meta['Orientation'] = $exif['Orientation'];
156
  }
157
 
158
+ // this is done by Windows
159
  if ( isset($this->exif_data['WINXP']) ) {
160
  $exif = $this->exif_data['WINXP'];
161
 
162
+ if (!empty($exif['Title']) && empty($meta['title']))
163
+ $meta['title'] = utf8_encode($exif['Title']);
164
+ if (!empty($exif['Author']))
165
+ $meta['author'] = utf8_encode($exif['Author']);
166
+ if (!empty($exif['Keywords']))
167
+ $meta['tags'] = utf8_encode($exif['Keywords']);
168
+ if (!empty($exif['Subject']))
169
+ $meta['subject'] = utf8_encode($exif['Subject']);
170
+ if (!empty($exif['Comments']))
171
+ $meta['caption'] = utf8_encode($exif['Comments']);
172
  }
173
 
174
+ $this->exif_array = $meta;
175
+ }
176
 
177
+ // return one element if requested
178
+ if ( $object == true ) {
179
+ $value = isset($this->exif_array[$object]) ? $this->exif_array[$object] : false;
180
+ return $value;
181
+ }
182
 
183
  // on request sanitize the output
184
+ if ( $this->sanitize == true )
185
  array_walk( $this->exif_array , create_function('&$value', '$value = esc_html($value);'));
186
 
187
+ return $this->exif_array;
188
+
189
+ }
190
+
191
+ // convert a fraction string to a decimal
192
+ function exif_frac2dec($str) {
193
+ @list( $n, $d ) = explode( '/', $str );
194
+ if ( !empty($d) )
195
+ return $n / $d;
196
+ return $str;
197
+ }
198
+
199
+ // convert the exif date format to a unix timestamp
200
+ function exif_date2ts($str) {
201
+ // seriously, who formats a date like 'YYYY:MM:DD hh:mm:ss'?
202
+ @list( $date, $time ) = explode( ' ', trim($str) );
203
+ @list( $y, $m, $d ) = explode( ':', $date );
204
+
205
+ return strtotime( "{$y}-{$m}-{$d} {$time}" );
206
+ }
207
+
208
+ /**
209
+ * nggMeta::readIPTC() - IPTC Data Information for EXIF Display
210
+ *
211
+ * @param mixed $output_tag
212
+ * @return IPTC-tags
213
+ */
214
+ function get_IPTC($object = false) {
215
+
216
+ if (!$this->iptc_data)
217
+ return false;
218
+
219
+ if (!is_array($this->iptc_array)){
220
+
221
+ // --------- Set up Array Functions --------- //
222
+ $iptcTags = array (
223
+ "2#005" => 'title',
224
+ "2#007" => 'status',
225
+ "2#012" => 'subject',
226
+ "2#015" => 'category',
227
+ "2#025" => 'keywords',
228
+ "2#055" => 'created_date',
229
+ "2#060" => 'created_time',
230
+ "2#080" => 'author',
231
+ "2#085" => 'position',
232
+ "2#090" => 'city',
233
+ "2#092" => 'location',
234
+ "2#095" => 'state',
235
+ "2#100" => 'country_code',
236
+ "2#101" => 'country',
237
+ "2#105" => 'headline',
238
+ "2#110" => 'credit',
239
+ "2#115" => 'source',
240
+ "2#116" => 'copyright',
241
+ "2#118" => 'contact',
242
+ "2#120" => 'caption'
243
+ );
244
+
245
+ $meta = array();
246
+ foreach ($iptcTags as $key => $value) {
247
+ if (isset ( $this->iptc_data[$key] ) )
248
+ $meta[$value] = trim(utf8_encode(implode(", ", $this->iptc_data[$key])));
249
+
250
+ }
251
+ $this->iptc_array = $meta;
252
+ }
253
+
254
+ // return one element if requested
255
+ if ($object)
256
+ return (isset($this->iptc_array[$object])) ? $this->iptc_array[$object] : NULL;
 
257
 
258
  // on request sanitize the output
259
+ if ( $this->sanitize == true )
260
  array_walk( $this->iptc_array , create_function('&$value', '$value = esc_html($value);'));
261
 
262
+ return $this->iptc_array;
263
+ }
264
+
265
+ /**
266
+ * nggMeta::extract_XMP()
267
+ * get XMP DATA
268
+ * code by Pekka Saarinen http://photography-on-the.net
269
+ *
270
+ * @param mixed $filename
271
+ * @return XML data
272
+ */
273
+ function extract_XMP( $filename ) {
274
+
275
+ //TODO:Require a lot of memory, could be better
276
+ ob_start();
277
+ @readfile($filename);
278
+ $source = ob_get_contents();
279
+ ob_end_clean();
280
+
281
+ $start = strpos( $source, "<x:xmpmeta" );
282
+ $end = strpos( $source, "</x:xmpmeta>" );
283
+ if ((!$start === false) && (!$end === false)) {
284
+ $lenght = $end - $start;
285
+ $xmp_data = substr($source, $start, $lenght+12 );
286
+ unset($source);
287
+ return $xmp_data;
288
+ }
289
+
290
+ unset($source);
291
+ return false;
292
+ }
293
+
294
+ /**
295
+ * nggMeta::get_XMP()
296
+ *
297
+ * @package Taken from http://php.net/manual/en/function.xml-parse-into-struct.php
298
+ * @author Alf Marius Foss Olsen & Alex Rabe
299
+ * @return XML Array or object
300
+ *
301
+ */
302
+ function get_XMP($object = false) {
303
+
304
+ if(!$this->xmp_data)
305
+ return false;
306
+
307
+ if (!is_array($this->xmp_array)){
308
+
309
+ $parser = xml_parser_create();
310
+ xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); // Dont mess with my cAsE sEtTings
311
+ xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); // Dont bother with empty info
312
+ xml_parse_into_struct($parser, $this->xmp_data, $values);
313
+ xml_parser_free($parser);
314
+
315
+ $xmlarray = array(); // The XML array
316
+ $this->xmp_array = array(); // The returned array
317
+ $stack = array(); // tmp array used for stacking
318
+ $list_array = array(); // tmp array for list elements
319
+ $list_element = false; // rdf:li indicator
320
+
321
+ foreach($values as $val) {
322
+
323
+ if($val['type'] == "open") {
324
+ array_push($stack, $val['tag']);
325
+
326
+ } elseif($val['type'] == "close") {
327
+ // reset the compared stack
328
+ if ($list_element == false)
329
+ array_pop($stack);
330
+ // reset the rdf:li indicator & array
331
+ $list_element = false;
332
+ $list_array = array();
333
+
334
+ } elseif($val['type'] == "complete") {
335
+ if ($val['tag'] == "rdf:li") {
336
+ // first go one element back
337
+ if ($list_element == false)
338
+ array_pop($stack);
339
+ $list_element = true;
340
  // do not parse empty tags
341
  if ( empty($val['value']) ) continue;
342
+ // save it in our temp array
343
+ $list_array[] = $val['value'];
344
+ // in the case it's a list element we seralize it
345
+ $value = implode(",", $list_array);
346
+ $this->setArrayValue($xmlarray, $stack, $value);
347
+ } else {
348
+ array_push($stack, $val['tag']);
349
  // do not parse empty tags
350
  if ( !empty($val['value']) )
351
  $this->setArrayValue($xmlarray, $stack, $val['value']);
352
+ array_pop($stack);
353
+ }
354
+ }
355
 
356
+ } // foreach
357
 
358
  // don't parse a empty array
359
  if( empty($xmlarray) || empty($xmlarray['x:xmpmeta']) )
360
  return false;
361
 
362
  // cut off the useless tags
363
+ $xmlarray = $xmlarray['x:xmpmeta']['rdf:RDF']['rdf:Description'];
364
+
365
+ // --------- Some values from the XMP format--------- //
366
+ $xmpTags = array (
367
+ 'xap:CreateDate' => 'created_timestamp',
368
+ 'xap:ModifyDate' => 'last_modfied',
369
+ 'xap:CreatorTool' => 'tool',
370
+ 'dc:format' => 'format',
371
+ 'dc:title' => 'title',
372
+ 'dc:creator' => 'author',
373
+ 'dc:subject' => 'keywords',
374
+ 'dc:description' => 'caption',
375
+ 'photoshop:AuthorsPosition' => 'position',
376
+ 'photoshop:City' => 'city',
377
+ 'photoshop:Country' => 'country'
378
+ );
379
+
380
+ foreach ($xmpTags as $key => $value) {
381
+ // if the kex exist
382
+ if ( isset($xmlarray[$key]) ) {
383
+ switch ($key) {
384
+ case 'xap:CreateDate':
385
+ case 'xap:ModifyDate':
386
+ $this->xmp_array[$value] = date_i18n(get_option('date_format').' '.get_option('time_format'), strtotime($xmlarray[$key]));
387
+ break;
388
+ default :
389
+ $this->xmp_array[$value] = $xmlarray[$key];
390
+ }
391
+ }
392
+ }
393
+
394
+ }
395
+
396
+ // return one element if requested
397
+ if ($object != false )
398
+ return isset($this->xmp_array[$object]) ? $this->xmp_array[$object] : false;
399
 
400
  // on request sanitize the output
401
+ if ( $this->sanitize == true )
402
  array_walk( $this->xmp_array , create_function('&$value', '$value = esc_html($value);'));
403
 
404
+ return $this->xmp_array;
405
+ }
406
 
407
+ function setArrayValue(&$array, $stack, $value) {
408
+ if ($stack) {
409
+ $key = array_shift($stack);
410
  $this->setArrayValue($array[$key], $stack, $value);
411
+ return $array;
412
+ } else {
413
+ $array = $value;
414
+ }
415
+ }
416
+
417
+ /**
418
+ * nggMeta::get_META() - return a meta value form the available list
419
+ *
420
+ * @param string $object
421
+ * @return mixed $value
422
+ */
423
+ function get_META($object = false) {
424
+
425
+ // defined order first look into database, then XMP, IPTC and EXIF.
426
+ if ($value = $this->get_saved_meta($object))
427
+ return $value;
428
+ if ($value = $this->get_XMP($object))
429
+ return $value;
430
+ if ($value = $this->get_IPTC($object))
431
+ return $value;
432
+ if ($value = $this->get_EXIF($object))
433
+ return $value;
434
+
435
+ // nothing found ?
436
+ return false;
437
+ }
438
+
439
+ /**
440
+ * nggMeta::i8n_name() - localize the tag name
441
+ *
442
+ * @param mixed $key
443
+ * @return translated $key
444
+ */
445
+ function i8n_name($key) {
446
+
447
+ $tagnames = array(
448
+ 'aperture' => __('Aperture','nggallery'),
449
+ 'credit' => __('Credit','nggallery'),
450
+ 'camera' => __('Camera','nggallery'),
451
+ 'caption' => __('Caption','nggallery'),
452
+ 'created_timestamp' => __('Date/Time','nggallery'),
453
+ 'copyright' => __('Copyright','nggallery'),
454
+ 'focal_length' => __('Focal length','nggallery'),
455
+ 'iso' => __('ISO','nggallery'),
456
+ 'shutter_speed' => __('Shutter speed','nggallery'),
457
+ 'title' => __('Title','nggallery'),
458
+ 'author' => __('Author','nggallery'),
459
+ 'tags' => __('Tags','nggallery'),
460
+ 'subject' => __('Subject','nggallery'),
461
+ 'make' => __('Make','nggallery'),
462
+ 'status' => __('Edit Status','nggallery'),
463
+ 'category' => __('Category','nggallery'),
464
+ 'keywords' => __('Keywords','nggallery'),
465
+ 'created_date' => __('Date Created','nggallery'),
466
+ 'created_time' => __('Time Created','nggallery'),
467
+ 'position' => __('Author Position','nggallery'),
468
+ 'city' => __('City','nggallery'),
469
+ 'location' => __('Location','nggallery'),
470
+ 'state' => __('Province/State','nggallery'),
471
+ 'country_code' => __('Country code','nggallery'),
472
+ 'country' => __('Country','nggallery'),
473
+ 'headline' => __('Headline','nggallery'),
474
+ 'credit' => __('Credit','nggallery'),
475
+ 'source' => __('Source','nggallery'),
476
+ 'copyright' => __('Copyright Notice','nggallery'),
477
+ 'contact' => __('Contact','nggallery'),
478
+ 'last_modfied' => __('Last modified','nggallery'),
479
+ 'tool' => __('Program tool','nggallery'),
480
+ 'format' => __('Format','nggallery'),
481
+ 'width' => __('Image Width','nggallery'),
482
+ 'height' => __('Image Height','nggallery'),
483
+ 'flash' => __('Flash','nggallery')
484
+ );
485
+
486
+ if ( isset($tagnames[$key]) )
487
  $key = $tagnames[$key];
488
 
489
+ return($key);
490
 
491
+ }
492
 
493
+ /**
494
+ * Return the Timestamp from the image , if possible it's read from exif data
495
+ *
496
+ * @return
497
+ */
498
+ function get_date_time() {
499
 
500
+ $date_time = time();
501
 
502
+ // get exif - data
503
+ if ( isset( $this->exif_data['EXIF']) ) {
504
 
505
  // try to read the date / time from the exif
506
+ foreach (array('DateTimeDigitized', 'DateTimeOriginal', 'FileDateTime') as $key) {
507
+ if (isset($this->exif_data['EXIF'][$key])) {
508
+ $date_time = strtotime($this->exif_data['EXIF'][$key]);
509
+ break;
510
+ }
511
+ }
512
+ } else {
513
+ // if no other date available, get the filetime
514
+ $date_time = @filectime($this->image->imagePath );
515
+ }
516
+
517
+ // Return the MySQL format
518
+ $date_time = date( 'Y-m-d H:i:s', $date_time );
519
+
520
+ return $date_time;
521
+ }
522
+
523
+ /**
524
+ * This function return the most common metadata, via a filter we can add more
525
+ * Reason : GD manipulation removes that options
526
+ *
527
+ * @since V1.4.0
528
+ * @return void
529
+ */
530
+ function get_common_meta() {
531
+ global $wpdb;
532
+
533
+ $meta = array(
534
+ 'aperture' => 0,
535
+ 'credit' => '',
536
+ 'camera' => '',
537
+ 'caption' => '',
538
+ 'created_timestamp' => 0,
539
+ 'copyright' => '',
540
+ 'focal_length' => 0,
541
+ 'iso' => 0,
542
+ 'shutter_speed' => 0,
543
+ 'flash' => 0,
544
+ 'title' => '',
545
+ 'keywords' => ''
546
+ );
547
+
548
+ $meta = apply_filters( 'ngg_read_image_metadata', $meta );
549
+
550
+ // meta should be still an array
551
+ if ( !is_array($meta) )
552
+ return false;
553
+
554
+ foreach ($meta as $key => $value) {
555
+ $meta[$key] = $this->get_META($key);
556
+ }
557
+
558
+ //let's add now the size of the image
559
+ $meta['width'] = $this->size[0];
560
+ $meta['height'] = $this->size[1];
561
+
562
+ return $meta;
563
+ }
 
 
564
 
565
  /**
566
  * If needed sanitize each value before output
571
  $this->sanitize = true;
572
  }
573
 
574
+ }
 
 
nggallery.php CHANGED
@@ -5,7 +5,7 @@ Plugin URI: http://www.nextgen-gallery.com/
5
  Description: A NextGENeration Photo Gallery for WordPress
6
  Author: Photocrati
7
  Author URI: http://www.photocrati.com/
8
- Version: 1.9.12
9
 
10
  Copyright (c) 2007-2011 by Alex Rabe & NextGEN DEV-Team
11
  Copyright (c) 2012 Photocrati Media
@@ -45,7 +45,7 @@ if (!class_exists('E_Clean_Exit')) {
45
  if (!class_exists('nggLoader')) {
46
  class nggLoader {
47
 
48
- var $version = '1.9.12';
49
  var $dbversion = '1.8.1';
50
  var $minimum_WP = '3.5';
51
  var $donators = 'http://www.nextgen-gallery.com/donators.php';
5
  Description: A NextGENeration Photo Gallery for WordPress
6
  Author: Photocrati
7
  Author URI: http://www.photocrati.com/
8
+ Version: 1.9.13
9
 
10
  Copyright (c) 2007-2011 by Alex Rabe & NextGEN DEV-Team
11
  Copyright (c) 2012 Photocrati Media
45
  if (!class_exists('nggLoader')) {
46
  class nggLoader {
47
 
48
+ var $version = '1.9.13';
49
  var $dbversion = '1.8.1';
50
  var $minimum_WP = '3.5';
51
  var $donators = 'http://www.nextgen-gallery.com/donators.php';
readme.txt CHANGED
@@ -202,6 +202,12 @@ For more information, feel free to visit the official website for the NextGEN Ga
202
 
203
  == Changelog ==
204
 
 
 
 
 
 
 
205
  = V1.9.12 - 02.15.2013 =
206
  * Fixed: jQuery Conflict Detection was trying to dequeue irremovable scripts
207
 
@@ -451,4 +457,4 @@ For more information, feel free to visit the official website for the NextGEN Ga
451
  == Upgrade Notice ==
452
 
453
  = 1.5.5 =
454
- * Compatibility issue for post thumbnails with WP2.9 and WP3.0. No Database changes...
202
 
203
  == Changelog ==
204
 
205
+ = V1.9.13 - 06.11.2013 =
206
+ * NEW: Slideshows are now centered to their content area
207
+ * Secured: Ensure that only logged in users can upload images
208
+ * Fixed: Import date is presered are no longer Jan 1 1970
209
+ * Fixed: Removed mention of upgrade.php, which no longer exists
210
+
211
  = V1.9.12 - 02.15.2013 =
212
  * Fixed: jQuery Conflict Detection was trying to dequeue irremovable scripts
213
 
457
  == Upgrade Notice ==
458
 
459
  = 1.5.5 =
460
+ * Compatibility issue for post thumbnails with WP2.9 and WP3.0. No Database changes...