0e49fe4cd4494bc546b72ae66c23981f21fb3a8d
[web/PetoskeyRobotics.git] /
1 <?php
2
3 class E_UploadException extends E_NggErrorException
4 {
5         function __construct($message='', $code=NULL, $previous=NULL)
6         {
7                 if (!$message) $message = "There was a problem uploading the file.";
8                 parent::__construct($message, $code, $previous);
9         }
10 }
11
12 class E_InsufficientWriteAccessException extends E_NggErrorException
13 {
14         function __construct($message=FALSE, $filename=NULL, $code=NULL, $previous=NULL)
15         {
16                 if (!$message) $message = "Could not write to file. Please check filesystem permissions.";
17                 if ($filename) $message .= " Filename: {$filename}";
18                 if (PHP_VERSION_ID >= 50300)
19                         parent::__construct($message, $code, $previous);
20                 else
21                         parent::__construct($message, $code);
22         }
23 }
24
25 class E_NoSpaceAvailableException extends E_NggErrorException
26 {
27         function __construct($message='', $code=NULL, $previous=NULL)
28         {
29                 if (!$message) $message = "You have exceeded your storage capacity. Please remove some files and try again.";
30                 parent::__construct($message, $code, $previous);
31         }
32 }
33  
34 class E_No_Image_Library_Exception extends E_NggErrorException
35 {
36         function __construct($message='', $code=NULL, $previous=NULL)
37         {
38                 if (!$message) $message = "The site does not support the GD Image library. Please ask your hosting provider to enable it.";
39                 parent::__construct($message, $code, $previous);
40         }
41 }
42
43
44 class Mixin_GalleryStorage_Driver_Base extends Mixin
45 {
46         /**
47          * Set correct file permissions (taken from wp core). Should be called
48          * after writing any file
49          *
50          * @class nggAdmin
51          * @param string $filename
52          * @return bool $result
53          */
54         function _chmod($filename = '')
55         {
56                 $stat = @ stat( dirname($filename) );
57                 $perms = $stat['mode'] & 0000666; // Remove execute bits for files
58                 if ( @chmod($filename, $perms) )
59                         return TRUE;
60
61                 return FALSE;
62         }
63
64     /**
65      * Gets the id of a gallery, regardless of whether an integer
66      * or object was passed as an argument
67      * @param mixed $gallery_obj_or_id
68      */
69     function _get_gallery_id($gallery_obj_or_id)
70     {
71         $retval = NULL;
72         $gallery_key = $this->object->_gallery_mapper->get_primary_key_column();
73         if (is_object($gallery_obj_or_id)) {
74             if (isset($gallery_obj_or_id->$gallery_key)) {
75                 $retval = $gallery_obj_or_id->$gallery_key;
76             }
77         }
78         elseif(is_numeric($gallery_obj_or_id)) {
79             $retval = $gallery_obj_or_id;
80         }
81
82         return $retval;
83     }
84
85     /**
86      * Gets the id of an image, regardless of whether an integer
87      * or object was passed as an argument
88      * @param type $image_obj_or_id
89      */
90     function _get_image_id($image_obj_or_id)
91     {
92         $retval = NULL;
93
94         $image_key = $this->object->_image_mapper->get_primary_key_column();
95         if (is_object($image_obj_or_id)) {
96             if (isset($image_obj_or_id->$image_key)) {
97                 $retval = $image_obj_or_id->$image_key;
98             }
99         }
100         elseif (is_numeric($image_obj_or_id)) {
101             $retval = $image_obj_or_id;
102         }
103
104         return $retval;
105     }
106
107     function convert_slashes($path)
108     {
109         $search = array('/', "\\");
110         $replace = array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR);
111
112         return str_replace($search, $replace, $path);
113     }
114
115
116     function delete_directory($abspath)
117     {
118         $retval = FALSE;
119
120         if (@file_exists($abspath)) {
121             $files = scandir($abspath);
122             array_shift($files);
123             array_shift($files);
124             foreach ($files as $file) {
125                 $file_abspath = implode(DIRECTORY_SEPARATOR, array(rtrim($abspath, "/\\"), $file));
126                 if (is_dir($file_abspath)) $this->object->delete_directory($file_abspath);
127                 else unlink($file_abspath);
128             }
129             rmdir($abspath);
130             $retval = @file_exists($abspath);
131         }
132
133         return $retval;
134     }
135
136     /**
137      * Backs up an image file
138      * @param int|object $image
139      */
140     function backup_image($image)
141     {
142         $retval = FALSE;
143
144         if (($image_path = $this->object->get_image_abspath($image))) {
145             $retval = copy($image_path, $this->object->get_backup_abspath($image));
146         }
147
148         return $retval;
149     }
150
151     /**
152      * Copies images into another gallery
153      * @param array $images
154      * @param int|object $gallery
155      * @param boolean $db optionally only copy the image files
156      * @param boolean $move move the image instead of copying
157      */
158     function copy_images($images, $gallery, $db=TRUE, $move=FALSE)
159     {
160         $retval = FALSE;
161
162         // Ensure we have a valid gallery
163         if (($gallery = $this->object->_get_gallery_id($gallery))) {
164             $gallery_path = $this->object->get_gallery_abspath($gallery);
165             $image_key = $this->object->_image_mapper->get_primary_key_column();
166             $retval = TRUE;
167
168             // Iterate through each image to copy...
169             foreach ($images as $image) {
170
171                 // Copy each image size
172                 foreach ($this->object->get_image_sizes() as $size) {
173                     $image_path = $this->object->get_image_abspath($image, $size);
174                     $dst = implode(DIRECTORY_SEPARATOR, array($gallery_path, basename($image_path)));
175                     $success = $move ? move($image_path, $dst) : copy($image_path, $dst);
176                     if (!$success) $retval = FALSE;
177                 }
178
179                 // Copy the db entry
180                 if ($db) {
181                     if (is_numeric($image)) $this->object->_image_mapper($image);
182                     unset($image->$image_key);
183                     $image->galleryid = $gallery;
184                 }
185             }
186         }
187
188         return $retval;
189     }
190
191     /**
192      * Empties the gallery cache directory of content
193      */
194     function flush_cache($gallery)
195     {
196         $cache = $this->object->get_registry()->get_utility('I_Cache');
197         $cache->flush_directory($this->object->get_cache_abspath($gallery));
198     }
199
200     /**
201      * Gets the absolute path of the backup of an original image
202      * @param string $image
203      */
204     function get_backup_abspath($image)
205     {
206         $retval = NULL;
207
208         if (($image_path = $this->object->get_image_abspath($image))) {
209             $retval = $image_path.'_backup';
210         }
211
212         return $retval;
213     }
214
215     /**
216      * Returns the absolute path to the cache directory of a gallery.
217      *
218      * Without the gallery parameter the legacy (pre 2.0) shared directory is returned.
219      *
220      * @param int|stdClass|C_Gallery $gallery (optional)
221      * @return string Absolute path to cache directory
222      */
223     function get_cache_abspath($gallery = FALSE)
224     {
225         $retval = NULL;
226
227         if (FALSE == $gallery)
228         {
229             $gallerypath = C_NextGen_Settings::get_instance()->gallerypath;
230             $retval = implode(DIRECTORY_SEPARATOR, array(
231                rtrim(C_Fs::get_instance()->get_document_root('gallery'), "/\\"),
232                rtrim($gallerypath, "/\\"),
233                'cache'
234             ));
235         }
236         else {
237             if (is_numeric($gallery))
238             {
239                 $gallery = $this->object->_gallery_mapper->find($gallery);
240             }
241             $retval = rtrim(implode(DIRECTORY_SEPARATOR, array($this->object->get_gallery_abspath($gallery), 'dynamic')), "/\\");
242         }
243
244         return $retval;
245     }
246
247     /**
248          * Gets the absolute path where the full-sized image is stored
249          * @param int|object $image
250          */
251         function get_full_abspath($image)
252         {
253                 return $this->object->get_image_abspath($image, 'full');
254         }
255
256     /**
257      * Alias to get_image_dimensions()
258      * @param int|object $image
259      * @return array
260      */
261     function get_full_dimensions($image)
262     {
263         return $this->object->get_image_dimensions($image, 'full');
264     }
265
266     /**
267      * Alias to get_image_html()
268      * @param int|object $image
269      * @return string
270      */
271     function get_full_html($image)
272     {
273         return $this->object->get_image_html($image, 'full');
274     }
275
276     /**
277      * Alias for get_original_url()
278      *
279      * @param int|stdClass|C_Image $image
280      * @return string
281      */
282     function get_full_url($image, $check_existance=FALSE)
283     {
284         return $this->object->get_image_url($image, 'full', $check_existance);
285     }
286
287     /**
288      * Gets the dimensions for a particular-sized image
289      *
290      * @param int|object $image
291      * @param string $size
292      * @return array
293      */
294     function get_image_dimensions($image, $size='full')
295     {
296                         $retval = NULL;
297
298         // If an image id was provided, get the entity
299         if (is_numeric($image)) $image = $this->object->_image_mapper->find($image);
300
301         // Ensure we have a valid image
302         if ($image) {
303
304             // Adjust size parameter
305             switch ($size) {
306                 case 'original':
307                     $size = 'full';
308                     break;
309                 case 'thumbnails':
310                 case 'thumbnail':
311                 case 'thumb':
312                 case 'thumbs':
313                     $size = 'thumbnail';
314                     break;
315             }
316
317             // Image dimensions are stored in the $image->meta_data
318             // property for all implementations
319             if (isset($image->meta_data) && isset($image->meta_data[$size])) {
320                 $retval = $image->meta_data[$size];
321             }
322
323                                 // Didn't exist for meta data. We'll have to compute
324                                 // dimensions in the meta_data after computing? This is most likely
325                                 // due to a dynamic image size being calculated for the first time
326                                 else {
327                                 
328                                         $abspath = $this->object->get_image_abspath($image, $size);
329                                 
330                                         if (@file_exists($abspath))
331                                         {
332                                                 $dims = getimagesize($abspath);
333                                                 
334                                                 if ($dims) {
335                                                         $retval['width']        = $dims[0];
336                                                         $retval['height']       = $dims[1];
337                                                 }
338                                         }
339                                 }
340       }
341
342         return $retval;
343     }
344
345     /**
346      * Gets the HTML for an image
347      * @param int|object $image
348      * @param string $size
349      * @return string
350      */
351     function get_image_html($image, $size='full', $attributes=array())
352     {
353         $retval = "";
354
355         if (is_numeric($image)) $image = $this->object->_image_mapper->find($image);
356
357         if ($image) {
358
359                         // Set alt text if not already specified
360                         if (!isset($attributes['alttext'])) {
361                                 $attributes['alt'] = esc_attr($image->alttext);
362                         }
363
364                         // Set the title if not already set
365                         if (!isset($attributes['title'])) {
366                                 $attributes['title'] = esc_attr($image->alttext);
367                         }
368
369                         // Set the dimensions if not set already
370                         if (!isset($attributes['width']) OR !isset($attributes['height'])) {
371                                 $dimensions = $this->object->get_image_dimensions($image, $size);
372                                 if (!isset($attributes['width'])) {
373                                         $attributes['width'] = $dimensions['width'];
374                                 }
375                                 if (!isset($attributes['height'])) {
376                                         $attributes['height'] = $dimensions['height'];
377                                 }
378                         }
379
380                         // Set the url if not already specified
381                         if (!isset($attributes['src'])) {
382                                 $attributes['src'] = $this->object->get_image_url($image, $size);
383                         }
384
385                         // Format attributes
386                         $attribs = array();
387                         foreach ($attributes as $attrib => $value) $attribs[] = "{$attrib}=\"{$value}\"";
388                         $attribs = implode(" ", $attribs);
389
390                         // Return HTML string
391                         $retval = "<img {$attribs} />";
392         }
393
394         return $retval;
395     }
396
397     /**
398      * An alias for get_full_abspath()
399      * @param int|object $image
400      */
401     function get_original_abspath($image, $check_existance=FALSE)
402     {
403         return $this->object->get_image_abspath($image, 'full', $check_existance);
404     }
405
406     /**
407      * Alias to get_image_dimensions()
408      * @param int|object $image
409      * @return array
410      */
411     function get_original_dimensions($image)
412     {
413         return $this->object->get_image_dimensions($image, 'full');
414     }
415
416     /**
417      * Alias to get_image_html()
418      * @param int|object $image
419      * @return string
420      */
421     function get_original_html($image)
422     {
423         return $this->object->get_image_html($image, 'full');
424     }
425
426     /**
427      * Gets the url to the original-sized image
428      * @param int|stdClass|C_Image $image
429      * @return string
430      */
431     function get_original_url($image, $check_existance=FALSE)
432     {
433         return $this->object->get_image_url($image, 'full', $check_existance);
434     }
435
436         /**
437          * Gets the upload path, optionally for a particular gallery
438          * @param int|C_Gallery|stdClass $gallery
439          */
440         function get_upload_relpath($gallery=FALSE)
441         {
442                 $fs = C_Fs::get_instance();
443
444         $retval = str_replace(
445             $fs->get_document_root('gallery'),
446             '',
447             $this->object->get_upload_abspath($gallery)
448         );
449
450                 return DIRECTORY_SEPARATOR.ltrim($retval, "/\\");
451         }
452
453         /**
454          * Moves images from to another gallery
455          * @param array $images
456          * @param int|object $gallery
457          * @param boolean $db optionally only move the image files, not the db entries
458          * @return boolean
459          */
460         function move_images($images, $gallery, $db=TRUE)
461         {
462                 return $this->object->copy_images($images, $gallery, $db, TRUE);
463         }
464
465     function is_image_file()
466     {
467         $retval = FALSE;
468
469         if ((isset($_FILES['file']) && $_FILES['file']['error'] == 0)) {
470             $file_info = $_FILES['file'];
471             $filename  = $_FILES['file']['tmp_name'];
472
473             if (isset($file_info['type'])) {
474                 $type = strtolower($file_info['type']);;
475                 $valid_types = array(
476                     'image/gif',
477                     'image/jpg',
478                     'image/jpeg',
479                     'image/pjpeg',
480                     'image/png',
481                 );
482                 $valid_regex = '/\.(jpg|jpeg|gif|png)$/';
483
484                 // Is this a valid type?
485                 if (in_array($type, $valid_types)) {
486
487                     // If we can, we'll verify the mime type
488                     if (function_exists('exif_imagetype')) {
489                         if (($image_type = @exif_imagetype($filename)) !== FALSE) {
490                             $retval = in_array(image_type_to_mime_type($image_type), $valid_types);
491                         }
492                     }
493
494                     else {
495                         $file_info = @getimagesize($filename);
496                         if (isset($file_info[2])) {
497                             $retval = in_array(image_type_to_mime_type($file_info[2]), $valid_types);
498                         }
499
500                         // We'll assume things are ok as there isn't much else we can do
501                         else $retval = TRUE;
502                     }
503                 }
504
505                 // Is this a valid extension?
506                 // TODO: Should we remove this?
507                 else if (strpos($type, 'octet-stream') !== FALSE && preg_match($valid_regex, $type)) {
508                     $retval = TRUE;
509                 }
510             }
511         }
512
513         return $retval;
514     }
515
516
517     function is_zip()
518     {
519         $retval = FALSE;
520         
521         if ((isset($_FILES['file']) && $_FILES['file']['error'] == 0)) {
522             $file_info = $_FILES['file'];
523             
524             if (isset($file_info['type'])) {
525                 $type = $file_info['type'];
526                 $type_parts = explode('/', $type);
527                 
528                 if (strtolower($type_parts[0]) == 'application') {
529                         $spec = $type_parts[1];
530                         $spec_parts = explode('-', $spec);
531                         $spec_parts = array_map('strtolower', $spec_parts);
532                         
533                         if (in_array($spec, array('zip', 'octet-stream')) || in_array('zip', $spec_parts)) {
534                                 $retval = true;
535                         }
536                 }
537             }
538         }
539
540         return $retval;
541     }
542
543     function upload_zip($gallery_id)
544     {
545         $memory_limit = intval(ini_get('memory_limit'));
546         if (!extension_loaded('suhosin') && $memory_limit < 256) @ini_set('memory_limit', '256M');
547
548         $retval = FALSE;
549
550         if ($this->object->is_zip()) {
551             $fs = $this->get_registry()->get_utility('I_Fs');
552
553             // Uses the WordPress ZIP abstraction API
554             include_once($fs->join_paths(ABSPATH, 'wp-admin', 'includes', 'file.php'));
555             WP_Filesystem();
556             
557             // Ensure that we truly have the gallery id
558             $gallery_id = $this->_get_gallery_id($gallery_id);
559             
560             $zipfile    = $_FILES['file']['tmp_name'];
561             $dest_path = implode(DIRECTORY_SEPARATOR, array(
562                rtrim(get_temp_dir(), "/\\"),
563                'unpacked-'.basename($zipfile)
564             ));
565
566             wp_mkdir_p($dest_path);
567             
568             if ((unzip_file($zipfile, $dest_path) === TRUE)) {
569                         $dest_dir = $dest_path . DIRECTORY_SEPARATOR;
570                 $files = glob($dest_dir . '*');
571                 $size = 0;
572                 
573                 foreach ($files as $file) {
574                         if (is_file($dest_dir . $file)) {
575                                 $size += filesize($dest_dir . $file);
576                         }
577                 }
578                 
579                 if ($size == 0) {
580                                 $this->object->delete_directory($dest_path);
581                                 
582                                                                         $destination = wp_upload_dir();
583                                                                         $destination_path = $destination['basedir'];
584                                                       $dest_path = implode(DIRECTORY_SEPARATOR, array(
585                                                          rtrim($destination_path, "/\\"),
586                                                          'unpacked-' . basename($zipfile)
587                                                       ));
588
589                                                       wp_mkdir_p($dest_path);
590                                                       
591                                 if ((unzip_file($zipfile, $dest_path) === TRUE)) {
592                                 $retval = $this->object->import_gallery_from_fs($dest_path, $gallery_id);
593                                 }
594                 }
595                 else {
596                         $retval = $this->object->import_gallery_from_fs($dest_path, $gallery_id);
597                 }
598             }
599             
600             $this->object->delete_directory($dest_path);
601         }
602
603         if (!extension_loaded('suhosin')) @ini_set('memory_limit', $memory_limit.'M');
604
605         return $retval;
606     }
607
608         function is_current_user_over_quota()
609         {
610                 $retval = FALSE;
611                 $settings = C_NextGen_Settings::get_instance();
612
613                 if ((is_multisite()) && $settings->get('wpmuQuotaCheck')) {
614                         require_once(ABSPATH . 'wp-admin/includes/ms.php');
615                         $retval = upload_is_user_over_quota(FALSE);
616                 }
617
618                 return $retval;
619         }
620
621
622         /**
623          * Uploads base64 file to a gallery
624          * @param int|stdClass|C_Gallery $gallery
625          * @param $data base64-encoded string of data representing the image
626          * @param type $filename specifies the name of the file
627          * @return C_Image
628          */
629         function upload_base64_image($gallery, $data, $filename=FALSE, $image_id=FALSE)
630         {
631         $settings = C_NextGen_Settings::get_instance();
632         $memory_limit = intval(ini_get('memory_limit'));
633         if (!extension_loaded('suhosin') && $memory_limit < 256) @ini_set('memory_limit', '256M');
634
635                 $retval         = NULL;
636                 if (($gallery_id = $this->object->_get_gallery_id($gallery))) {
637
638                         if ($this->object->is_current_user_over_quota()) {
639                                 $message = sprintf(__('Sorry, you have used your space allocation. Please delete some files to upload more files.', 'nggallery'));
640                                 throw new E_NoSpaceAvailableException($message);
641                         }
642
643                         // Get path information. The use of get_upload_abspath() might
644                         // not be the best for some drivers. For example, if using the
645                         // WordPress Media Library for uploading, then the wp_upload_bits()
646                         // function should perhaps be used
647                         $upload_dir = $this->object->get_upload_abspath($gallery);
648
649                         // Perhaps a filename was given instead of base64 data?
650             if (preg_match("#/\\\\#", $data[0]) && @file_exists($data)) {
651                                 if (!$filename) $filename = basename($data);
652                                 $data = file_get_contents($data);
653                         }
654
655                         // Determine filenames
656                         $original_filename = $filename;
657                         $filename = $filename ? sanitize_file_name($original_filename) : uniqid('nextgen-gallery');
658                         if (preg_match("/\-(png|jpg|gif|jpeg)$/i", $filename, $match)) {
659                                 $filename = str_replace($match[0], '.'.$match[1], $filename);
660                         }
661
662             $abs_filename = implode(DIRECTORY_SEPARATOR, array($upload_dir, $filename));
663
664             // Prevent duplicate filenames: check if the filename exists and
665             // begin appending '-i' until we find an open slot
666             if (!ini_get('safe_mode') && @file_exists($abs_filename))
667             {
668                 $file_exists = TRUE;
669                 $i = 0;
670                 do {
671                     $i++;
672                     $parts = explode('.', $filename);
673                     $extension = array_pop($parts);
674                     $new_filename = implode('.', $parts) . '-' . $i . '.' . $extension;
675                     $new_abs_filename = implode(DIRECTORY_SEPARATOR, array($upload_dir, $new_filename));
676                     if (!@file_exists($new_abs_filename))
677                     {
678                         $file_exists = FALSE;
679                         $filename = $new_filename;
680                         $abs_filename = $new_abs_filename;
681                     }
682                 } while ($file_exists == TRUE);
683             }
684
685                         // Create or retrieve the image object
686                         $image  = NULL;
687                         if ($image_id) {
688                                 $image  = $this->object->_image_mapper->find($image_id, TRUE);
689                                 unset($image->meta_data['saved']);
690                         }
691                         if (!$image) $image = $this->object->_image_mapper->create();
692                         $retval = $image;
693                         
694                         // Create or update the database record
695                         $image->alttext         = basename($original_filename, '.' . pathinfo($original_filename, PATHINFO_EXTENSION));
696                         $image->galleryid       = $this->object->_get_gallery_id($gallery);
697                         $image->filename        = $filename;
698                         $image->image_slug = nggdb::get_unique_slug( sanitize_title_with_dashes( $image->alttext ), 'image' );
699                         $image_key                      = $this->object->_image_mapper->get_primary_key_column();
700
701             // If we can't write to the directory, then there's no point in continuing
702             if (!@file_exists($upload_dir)) @wp_mkdir_p($upload_dir);
703             if (!is_writable($upload_dir)) {
704                 throw new E_InsufficientWriteAccessException(
705                     FALSE, $upload_dir, FALSE
706                 );
707             }
708
709                         // Save the image
710                         if (($image_id = $this->object->_image_mapper->save($image))) {
711                                 try {
712                                         // Try writing the image
713                                         $fp = fopen($abs_filename, 'w');
714                                         fwrite($fp, $data);
715                                         fclose($fp);
716
717                     if ($settings->imgBackup)
718                         $this->object->backup_image($image);
719
720                     if ($settings->imgAutoResize)
721                         $this->object->generate_image_clone(
722                             $abs_filename,
723                             $abs_filename,
724                             $this->object->get_image_size_params($image_id, 'full')
725                         );
726
727                     // Ensure that fullsize dimensions are added to metadata array
728                     $dimensions = getimagesize($abs_filename);
729                     $full_meta = array(
730                         'width'         =>      $dimensions[0],
731                         'height'        =>      $dimensions[1]
732                     );
733                     if (!isset($image->meta_data) OR (is_string($image->meta_data) && strlen($image->meta_data) == 0)) {
734                         $image->meta_data = array();
735                     }
736                     $image->meta_data = array_merge($image->meta_data, $full_meta);
737                     $image->meta_data['full'] = $full_meta;
738
739                                         // Generate a thumbnail for the image
740                                         $this->object->generate_thumbnail($image);
741
742                     // Set gallery preview image if missing
743                     $this->object->get_registry()->get_utility('I_Gallery_Mapper')->set_preview_image($gallery, $image_id, TRUE);
744
745                                         // Notify other plugins that an image has been added
746                                         do_action('ngg_added_new_image', $image);
747
748                                         // delete dirsize after adding new images
749                                         delete_transient( 'dirsize_cache' );
750
751                                         // Seems redundant to above hook. Maintaining for legacy purposes
752                                         do_action(
753                                                 'ngg_after_new_images_added',
754                                                 $gallery_id,
755                                                 array($image->$image_key)
756                                         );
757                                 }
758                                 catch(E_No_Image_Library_Exception $ex) {
759                                                 throw $ex;
760                                 }
761                                 catch(E_Clean_Exit $ex) {
762                                         // pass
763                                 }
764                                 catch(Exception $ex) {
765                                         throw new E_InsufficientWriteAccessException(
766                                                 FALSE, $abs_filename, FALSE, $ex
767                                         );
768                                 }
769                         }
770             else throw new E_InvalidEntityException();
771                 }
772                 else throw new E_EntityNotFoundException();
773
774         if (!extension_loaded('suhosin')) @ini_set('memory_limit', $memory_limit.'M');
775
776                 return $retval;
777         }
778
779     function import_gallery_from_fs($abspath, $gallery_id=FALSE, $move_files=TRUE)
780     {
781         $retval = FALSE;
782         if (@file_exists($abspath)) {
783
784             // Ensure that this folder has images
785             $files_all = scandir($abspath);
786             $files = array();
787             
788             // first perform some filtering on file list
789             foreach ($files_all as $file)
790             {
791                 if ($file == '.' || $file == '..')
792                         continue;
793                         
794                 $files[] = $file;
795             }
796             
797             if (!empty($files)) {
798
799                 // Get needed utilities
800                 $fs = $this->get_registry()->get_utility('I_Fs');
801                 $gallery_mapper = $this->get_registry()->get_utility('I_Gallery_Mapper');
802
803                 // Sometimes users try importing a directory, which actually has all images under another directory
804                 $first_file_abspath = $fs->join_paths($abspath, $files[0]);
805                 if (is_dir($first_file_abspath) && count($files) == 1) return $this->import_gallery_from_fs($first_file_abspath, $gallery_id, $move_files);
806
807                 // If no gallery has been specified, then use the directory name as the gallery name
808                 if (!$gallery_id) {
809                     // Create the gallery
810                     $gallery = $gallery_mapper->create(array(
811                         'title'         =>  basename($abspath),
812                     ));
813                     
814                     if (!$move_files) {
815                         $gallery->path = str_ireplace(ABSPATH, '', $abspath);
816                     }
817
818                     // Save the gallery
819                     if ($gallery->save()) $gallery_id = $gallery->id();
820                 }
821
822                 // Ensure that we have a gallery id
823                 if ($gallery_id) {
824                     $retval = array('gallery_id' => $gallery_id, 'image_ids' => array());
825                     foreach ($files as $file) {
826                         if (!preg_match("/\.(jpg|jpeg|gif|png)/i", $file)) continue;
827                         $file_abspath = $fs->join_paths($abspath, $file);
828                         $image = null;
829                         
830                         if ($move_files) {
831                                       $image = $this->object->upload_base64_image(
832                                           $gallery_id,
833                                           file_get_contents($file_abspath),
834                                           str_replace(' ', '_', $file)
835                                       );
836                         }
837                         else {
838                                                                                                         // Create the database record ... TODO cleanup, some duplication here from upload_base64_image
839                                                                                                         $factory = $this->object->get_registry()->get_utility('I_Component_Factory');
840                                                                                                         $image = $factory->create('image');
841                                                                                                         $image->alttext         = sanitize_title_with_dashes(basename($file_abspath, '.' . pathinfo($file_abspath, PATHINFO_EXTENSION)));
842                                                                                                         $image->galleryid       = $this->object->_get_gallery_id($gallery_id);
843                                                                                                         $image->filename        = basename($file_abspath);
844                                                                                                         $image->image_slug = nggdb::get_unique_slug( sanitize_title_with_dashes( $image->alttext ), 'image' );
845                                                                                                         $image_key                      = $this->object->_image_mapper->get_primary_key_column();
846                                                                                                         $abs_filename = $file_abspath;
847
848                                                                                                         if (($image_id = $this->object->_image_mapper->save($image))) {
849                                                                                                                 try {
850                                                                                                                         // backup and image resizing should have already been performed, better to avoid
851 #                                                                                                                       if ($settings->imgBackup)
852 #                                                                                                                           $this->object->backup_image($image);
853
854 #                                                                                                                       if ($settings->imgAutoResize)
855 #                                                                                                                           $this->object->generate_image_clone(
856 #                                                                                                                               $abs_filename,
857 #                                                                                                                               $abs_filename,
858 #                                                                                                                               $this->object->get_image_size_params($image_id, 'full')
859 #                                                                                                                           );
860
861                                                                                                                         // Ensure that fullsize dimensions are added to metadata array
862                                                                                                                         $dimensions = getimagesize($abs_filename);
863                                                                                                                         $full_meta = array(
864                                                                                                                             'width'             =>      $dimensions[0],
865                                                                                                                             'height'    =>      $dimensions[1]
866                                                                                                                         );
867                                                                                                                         if (!isset($image->meta_data) OR (is_string($image->meta_data) && strlen($image->meta_data) == 0)) {
868                                                                                                                             $image->meta_data = array();
869                                                                                                                         }
870                                                                                                                         $image->meta_data = array_merge($image->meta_data, $full_meta);
871                                                                                                                         $image->meta_data['full'] = $full_meta;
872
873                                                                                                                         // Generate a thumbnail for the image
874                                                                                                                         $this->object->generate_thumbnail($image);
875
876                                                                                                                         // Set gallery preview image if missing
877                                                                                                                         $this->object->get_registry()->get_utility('I_Gallery_Mapper')->set_preview_image($gallery, $image_id, TRUE);
878
879                                                                                                                         // Notify other plugins that an image has been added
880                                                                                                                         do_action('ngg_added_new_image', $image);
881
882                                                                                                                         // delete dirsize after adding new images
883                                                                                                                         delete_transient( 'dirsize_cache' );
884
885                                                                                                                         // Seems redundant to above hook. Maintaining for legacy purposes
886                                                                                                                         do_action(
887                                                                                                                                 'ngg_after_new_images_added',
888                                                                                                                                 $gallery_id,
889                                                                                                                                 array($image->$image_key)
890                                                                                                                         );
891                                                                                                                 }
892                                                                                                                 catch(Exception $ex) {
893                                                                                                                         throw new E_InsufficientWriteAccessException(
894                                                                                                                                 FALSE, $abs_filename, FALSE, $ex
895                                                                                                                         );
896                                                                                                                 }
897                                                                                                         }
898                                                                                                         else throw new E_InvalidEntityException();
899                         }
900                                                         
901                       $retval['image_ids'][] = $image->{$image->id_field};
902                     }
903
904                     // Add the gallery name to the result
905                     $gallery = $gallery_mapper->find($gallery_id);
906                     $retval['gallery_name'] = $gallery->title;
907                     unset($gallery);
908                 }
909             }
910         }
911
912         return $retval;
913     }
914
915         function get_image_format_list()
916         {
917                 $format_list = array(IMAGETYPE_GIF => 'gif', IMAGETYPE_JPEG => 'jpg', IMAGETYPE_PNG => 'png');
918
919                 return $format_list;
920         }
921
922         /**
923          * Returns an array of properties of a resulting clone image if and when generated
924          * @param string $image_path
925          * @param string $clone_path
926          * @param array $params
927          * @return array
928          */
929         function calculate_image_clone_result($image_path, $clone_path, $params)
930         {
931                 $width      = isset($params['width'])      ? $params['width']      : NULL;
932                 $height     = isset($params['height'])     ? $params['height']     : NULL;
933                 $quality    = isset($params['quality'])    ? $params['quality']    : NULL;
934                 $type       = isset($params['type'])       ? $params['type']       : NULL;
935                 $crop       = isset($params['crop'])       ? $params['crop']       : NULL;
936                 $watermark  = isset($params['watermark'])  ? $params['watermark']  : NULL;
937                 $rotation   = isset($params['rotation'])   ? $params['rotation']   : NULL;
938                 $reflection = isset($params['reflection']) ? $params['reflection'] : NULL;
939                 $crop_frame = isset($params['crop_frame']) ? $params['crop_frame'] : NULL;
940                 $result  = NULL;
941
942                 // Ensure we have a valid image
943                 if ($image_path && @file_exists($image_path))
944                 {
945                         // Ensure target directory exists, but only create 1 subdirectory
946                         $image_dir = dirname($image_path);
947                         $clone_dir = dirname($clone_path);
948                         $image_extension = pathinfo($image_path, PATHINFO_EXTENSION);
949                         $image_extension_str = null;
950                         $clone_extension = pathinfo($clone_path, PATHINFO_EXTENSION);
951                         $clone_extension_str = null;
952
953                         if ($image_extension != null)
954                         {
955                                 $image_extension_str = '.' . $image_extension;
956                         }
957
958                         if ($clone_extension != null)
959                         {
960                                 $clone_extension_str = '.' . $clone_extension;
961                         }
962
963                         $image_basename = basename($image_path, $image_extension_str);
964                         $clone_basename = basename($clone_path, $clone_extension_str);
965                         // We use a default suffix as passing in null as the suffix will make WordPress use a default
966                         $clone_suffix = null;
967                         $format_list = $this->object->get_image_format_list();
968                         $clone_format = null; // format is determined below and based on $type otherwise left to null
969
970                         // suffix is only used to reconstruct paths for image_resize function
971                         if (strpos($clone_basename, $image_basename) === 0)
972                         {
973                                 $clone_suffix = substr($clone_basename, strlen($image_basename));
974                         }
975
976                         if ($clone_suffix != null && $clone_suffix[0] == '-')
977                         {
978                                 // WordPress adds '-' on its own
979                                 $clone_suffix = substr($clone_suffix, 1);
980                         }
981
982             // Get original image dimensions
983                         $dimensions = getimagesize($image_path);
984
985                         if ($width == null && $height == null) {
986                                 if ($dimensions != null) {
987
988                                         if ($width == null) {
989                                                 $width = $dimensions[0];
990                                         }
991
992                                         if ($height == null) {
993                                                 $height = $dimensions[1];
994                                         }
995                                 }
996                                 else {
997                                         // XXX Don't think there's any other option here but to fail miserably...use some hard-coded defaults maybe?
998                                         return null;
999                                 }
1000                         }
1001
1002                         if ($dimensions != null) {
1003                                 $dimensions_ratio = $dimensions[0] / $dimensions[1];
1004
1005                                 if ($width == null) {
1006                                         $width = (int) round($height * $dimensions_ratio);
1007
1008                                         if ($width == ($dimensions[0] - 1))
1009                                         {
1010                                                 $width = $dimensions[0];
1011                                         }
1012                                 }
1013                                 else if ($height == null) {
1014                                         $height = (int) round($width / $dimensions_ratio);
1015
1016                                         if ($height == ($dimensions[1] - 1))
1017                                         {
1018                                                 $height = $dimensions[1];
1019                                         }
1020                                 }
1021
1022                                 if ($width > $dimensions[0]) {
1023                                         $width = $dimensions[0];
1024                                 }
1025
1026                                 if ($height > $dimensions[1]) {
1027                                         $height = $dimensions[1];
1028                                 }
1029
1030                                 $image_format = $dimensions[2];
1031
1032                                 if ($type != null)
1033                                 {
1034                                         if (is_string($type))
1035                                         {
1036                                                 $type = strtolower($type);
1037
1038                                                 // Indexes in the $format_list array correspond to IMAGETYPE_XXX values appropriately
1039                                                 if (($index = array_search($type, $format_list)) !== false)
1040                                                 {
1041                                                         $type = $index;
1042
1043                                                         if ($type != $image_format)
1044                                                         {
1045                                                                 // Note: this only changes the FORMAT of the image but not the extension
1046                                                                 $clone_format = $type;
1047                                                         }
1048                                                 }
1049                                         }
1050                                 }
1051                         }
1052
1053                         if ($width == null || $height == null) {
1054                                 // Something went wrong...
1055                                 return null;
1056                         }
1057
1058                         $result['clone_path'] = $clone_path;
1059                         $result['clone_directory'] = $clone_dir;
1060                         $result['clone_suffix'] = $clone_suffix;
1061                         $result['clone_format'] = $clone_format;
1062                         $result['base_width'] = $dimensions[0];
1063                         $result['base_height'] = $dimensions[1];
1064
1065                         // image_resize() has limitations:
1066                         // - no easy crop frame support
1067                         // - fails if the dimensions are unchanged
1068                         // - doesn't support filename prefix, only suffix so names like thumbs_original_name.jpg for $clone_path are not supported
1069                         //   also suffix cannot be null as that will make WordPress use a default suffix...we could use an object that returns empty string from __toString() but for now just fallback to ngg generator
1070             if (FALSE) { // disabling the WordPress method for Iteration #6
1071 //                      if (($crop_frame == null || !$crop) && ($dimensions[0] != $width && $dimensions[1] != $height) && $clone_suffix != null)
1072                                 $result['method'] = 'wordpress';
1073
1074                                 $new_dims = image_resize_dimensions($dimensions[0], $dimensions[1], $width, $height, $crop);
1075
1076                                 if ($new_dims) {
1077                                         list($dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) = $new_dims;
1078
1079                                         $width = $dst_w;
1080                                         $height = $dst_h;
1081                                 }
1082                                 else {
1083                                         $result['error'] = new WP_Error( 'error_getting_dimensions', __('Could not calculate resized image dimensions') );
1084                                 }
1085                         }
1086                         else
1087                         {
1088                                 $result['method'] = 'nextgen';
1089                                 $original_width = $dimensions[0];
1090                                 $original_height = $dimensions[1];
1091                                 $original_ratio = $original_width / $original_height;
1092
1093                                 $aspect_ratio = $width / $height;
1094
1095                                 $orig_ratio_x = $original_width / $width;
1096                                 $orig_ratio_y = $original_height / $height;
1097
1098                                 if ($crop)
1099                                 {
1100                                         $algo = 'shrink'; // either 'adapt' or 'shrink'
1101
1102                                         if ($crop_frame != null)
1103                                         {
1104                                                 $crop_x = (int) round($crop_frame['x']);
1105                                                 $crop_y = (int) round($crop_frame['y']);
1106                                                 $crop_width = (int) round($crop_frame['width']);
1107                                                 $crop_height = (int) round($crop_frame['height']);
1108                                                 $crop_final_width = (int) round($crop_frame['final_width']);
1109                                                 $crop_final_height = (int) round($crop_frame['final_height']);
1110
1111                                                 $crop_width_orig = $crop_width;
1112                                                 $crop_height_orig = $crop_height;
1113
1114                                                 $crop_factor_x = $crop_width / $crop_final_width;
1115                                                 $crop_factor_y = $crop_height / $crop_final_height;
1116
1117                                                 $crop_ratio_x = $crop_width / $width;
1118                                                 $crop_ratio_y = $crop_height / $height;
1119
1120                                                 if ($algo == 'adapt')
1121                                                 {
1122                                                         // XXX not sure about this...don't use for now
1123 #                                                       $crop_width = (int) round($width * $crop_factor_x);
1124 #                                                       $crop_height = (int) round($height * $crop_factor_y);
1125                                                 }
1126                                                 else if ($algo == 'shrink')
1127                                                 {
1128                                                         if ($crop_ratio_x < $crop_ratio_y)
1129                                                         {
1130                                                                 $crop_width = max($crop_width, $width);
1131                                                                 $crop_height = (int) round($crop_width / $aspect_ratio);
1132                                                         }
1133                                                         else
1134                                                         {
1135                                                                 $crop_height = max($crop_height, $height);
1136                                                                 $crop_width = (int) round($crop_height * $aspect_ratio);
1137                                                         }
1138
1139                                                         if ($crop_width == ($crop_width_orig - 1))
1140                                                         {
1141                                                                 $crop_width = $crop_width_orig;
1142                                                         }
1143
1144                                                         if ($crop_height == ($crop_height_orig - 1))
1145                                                         {
1146                                                                 $crop_height = $crop_height_orig;
1147                                                         }
1148                                                 }
1149
1150                                                 $crop_diff_x = (int) round(($crop_width_orig - $crop_width) / 2);
1151                                                 $crop_diff_y = (int) round(($crop_height_orig - $crop_height) / 2);
1152
1153                                                 $crop_x += $crop_diff_x;
1154                                                 $crop_y += $crop_diff_y;
1155
1156                                                 $crop_max_x = ($crop_x + $crop_width);
1157                                                 $crop_max_y = ($crop_y + $crop_height);
1158
1159                                                 // Check if we're overflowing borders
1160                                                 //
1161                                                 if ($crop_x < 0)
1162                                                 {
1163                                                         $crop_x = 0;
1164                                                 }
1165                                                 else if ($crop_max_x > $original_width)
1166                                                 {
1167                                                         $crop_x -= ($crop_max_x - $original_width);
1168                                                 }
1169
1170                                                 if ($crop_y < 0)
1171                                                 {
1172                                                         $crop_y = 0;
1173                                                 }
1174                                                 else if ($crop_max_y > $original_height)
1175                                                 {
1176                                                         $crop_y -= ($crop_max_y - $original_height);
1177                                                 }
1178                                         }
1179                                         else
1180                                         {
1181                                                 if ($orig_ratio_x < $orig_ratio_y)
1182                                                 {
1183                                                         $crop_width = $original_width;
1184                                                         $crop_height = (int) round($height * $orig_ratio_x);
1185
1186                                                 }
1187                                                 else
1188                                                 {
1189                                                         $crop_height = $original_height;
1190                                                         $crop_width = (int) round($width * $orig_ratio_y);
1191                                                 }
1192
1193                                                 if ($crop_width == ($width - 1))
1194                                                 {
1195                                                         $crop_width = $width;
1196                                                 }
1197
1198                                                 if ($crop_height == ($height - 1))
1199                                                 {
1200                                                         $crop_height = $height;
1201                                                 }
1202
1203                                                 $crop_x = (int) round(($original_width - $crop_width) / 2);
1204                                                 $crop_y = (int) round(($original_height - $crop_height) / 2);
1205                                         }
1206
1207                                         $result['crop_area'] = array('x' => $crop_x, 'y' => $crop_y, 'width' => $crop_width, 'height' => $crop_height);
1208                                 }
1209                                 else {
1210                                         // Just constraint dimensions to ensure there's no stretching or deformations
1211                                         list($width, $height) = wp_constrain_dimensions($original_width, $original_height, $width, $height);
1212                                 }
1213                         }
1214
1215                         $result['width'] = $width;
1216                         $result['height'] = $height;
1217                         $result['quality'] = $quality;
1218
1219                         $real_width = $width;
1220                         $real_height = $height;
1221
1222                         if ($rotation && in_array(abs($rotation), array(90, 270)))
1223                         {
1224                                 $real_width = $height;
1225                                 $real_height = $width;
1226                         }
1227
1228                         if ($reflection)
1229                         {
1230                                 // default for nextgen was 40%, this is used in generate_image_clone as well
1231                                 $reflection_amount = 40;
1232                                 // Note, round() would probably be best here but using the same code that C_NggLegacy_Thumbnail uses for compatibility
1233         $reflection_height = intval($real_height * ($reflection_amount / 100));
1234         $real_height = $real_height + $reflection_height;
1235                         }
1236
1237                         $result['real_width'] = $real_width;
1238                         $result['real_height'] = $real_height;
1239                 }
1240
1241                 return $result;
1242         }
1243
1244         /**
1245          * Returns an array of dimensional properties (width, height, real_width, real_height) of a resulting clone image if and when generated
1246          * @param string $image_path
1247          * @param string $clone_path
1248          * @param array $params
1249          * @return array
1250          */
1251         function calculate_image_clone_dimensions($image_path, $clone_path, $params)
1252         {
1253                 $retval = null;
1254                 $result = $this->object->calculate_image_clone_result($image_path, $clone_path, $params);
1255
1256                 if ($result != null) {
1257                         $retval = array(
1258                                 'width' => $result['width'],
1259                                 'height' => $result['height'],
1260                                 'real_width' => $result['real_width'],
1261                                 'real_height' => $result['real_height']
1262                         );
1263                 }
1264
1265                 return $retval;
1266         }
1267
1268         /**
1269          * Generates a "clone" for an existing image, the clone can be altered using the $params array
1270          * @param string $image_path
1271          * @param string $clone_path
1272          * @param array $params
1273          * @return object
1274          */
1275         function generate_image_clone($image_path, $clone_path, $params)
1276         {
1277                 $width      = isset($params['width'])      ? $params['width']      : NULL;
1278                 $height     = isset($params['height'])     ? $params['height']     : NULL;
1279                 $quality    = isset($params['quality'])    ? $params['quality']    : NULL;
1280                 $type       = isset($params['type'])       ? $params['type']       : NULL;
1281                 $crop       = isset($params['crop'])       ? $params['crop']       : NULL;
1282                 $watermark  = isset($params['watermark'])  ? $params['watermark']  : NULL;
1283                 $reflection = isset($params['reflection']) ? $params['reflection'] : NULL;
1284                 $rotation   = isset($params['rotation']) ? $params['rotation'] : NULL;
1285                 $flip   = isset($params['flip']) ? $params['flip'] : NULL;
1286                 $crop_frame = isset($params['crop_frame']) ? $params['crop_frame'] : NULL;
1287                 $destpath   = NULL;
1288                 $thumbnail  = NULL;
1289                 $quality        = 100;
1290
1291         // Do this before anything else can modify the original -- $detailed_size
1292         // may hold IPTC metadata we need to write to our clone
1293         $size = getimagesize($image_path, $detailed_size);
1294
1295                 $result = $this->object->calculate_image_clone_result($image_path, $clone_path, $params);
1296
1297                 // XXX this should maybe be removed and extra settings go into $params?
1298                 $settings = C_NextGen_Settings::get_instance();
1299
1300                 // Ensure we have a valid image
1301                 if ($image_path && @file_exists($image_path) && $result != null && !isset($result['error']))
1302                 {
1303                         $image_dir = dirname($image_path);
1304                         $clone_path = $result['clone_path'];
1305                         $clone_dir = $result['clone_directory'];
1306                         $clone_suffix = $result['clone_suffix'];
1307                         $clone_format = $result['clone_format'];
1308                         $format_list = $this->object->get_image_format_list();
1309
1310                         // Ensure target directory exists, but only create 1 subdirectory
1311                         if (!@file_exists($clone_dir))
1312                         {
1313                                 if (strtolower(realpath($image_dir)) != strtolower(realpath($clone_dir)))
1314                                 {
1315                                         if (strtolower(realpath($image_dir)) == strtolower(realpath(dirname($clone_dir))))
1316                                         {
1317                                                 wp_mkdir_p($clone_dir);
1318                                         }
1319                                 }
1320                         }
1321
1322                         $method = $result['method'];
1323                         $width = $result['width'];
1324                         $height = $result['height'];
1325                         $quality = $result['quality'];
1326                         
1327                         if ($quality == null)
1328                         {
1329                                 $quality = 100;
1330                         }
1331
1332                         if ($method == 'wordpress')
1333                         {
1334                 $original = wp_get_image_editor($image_path);
1335                 $destpath = $clone_path;
1336                 if (!is_wp_error($original))
1337                 {
1338                     $original->resize($width, $height, $crop);
1339                     $original->set_quality($quality);
1340                     $original->save($clone_path);
1341                 }
1342                         }
1343                         else if ($method == 'nextgen')
1344                         {
1345                                 $destpath = $clone_path;
1346                                 $thumbnail = new C_NggLegacy_Thumbnail($image_path, true);
1347                 if (!$thumbnail->error) {
1348                     if ($crop) {
1349                         $crop_area = $result['crop_area'];
1350                         $crop_x = $crop_area['x'];
1351                         $crop_y = $crop_area['y'];
1352                         $crop_width = $crop_area['width'];
1353                         $crop_height = $crop_area['height'];
1354
1355                         $thumbnail->crop($crop_x, $crop_y, $crop_width, $crop_height);
1356                     }
1357
1358                     $thumbnail->resize($width, $height);
1359                 }
1360                 else $thumbnail = NULL;
1361                         }
1362
1363                         // We successfully generated the thumbnail
1364                         if (is_string($destpath) && (@file_exists($destpath) || $thumbnail != null))
1365                         {
1366                                 if ($clone_format != null)
1367                                 {
1368                                         if (isset($format_list[$clone_format]))
1369                                         {
1370                                                 $clone_format_extension = $format_list[$clone_format];
1371                                                 $clone_format_extension_str = null;
1372
1373                                                 if ($clone_format_extension != null)
1374                                                 {
1375                                                         $clone_format_extension_str = '.' . $clone_format_extension;
1376                                                 }
1377
1378                                                 $destpath_info = pathinfo($destpath);
1379                                                 $destpath_extension = $destpath_info['extension'];
1380                                                 $destpath_extension_str = null;
1381
1382                                                 if ($destpath_extension != null)
1383                                                 {
1384                                                         $destpath_extension_str = '.' . $destpath_extension;
1385                                                 }
1386
1387                                                 if (strtolower($destpath_extension) != strtolower($clone_format_extension))
1388                                                 {
1389                                                         $destpath_dir = $destpath_info['dirname'];
1390                                                         $destpath_basename = $destpath_info['filename'];
1391                                                         $destpath_new = $destpath_dir . DIRECTORY_SEPARATOR . $destpath_basename . $clone_format_extension_str;
1392
1393                                                         if ((@file_exists($destpath) && rename($destpath, $destpath_new)) || $thumbnail != null)
1394                                                         {
1395                                                                 $destpath = $destpath_new;
1396                                                         }
1397                                                 }
1398                                         }
1399                                 }
1400
1401                                 if (is_null($thumbnail))
1402                                 {
1403                                         $thumbnail = new C_NggLegacy_Thumbnail($destpath, true);
1404                                 }
1405                                 else
1406                                 {
1407                                         $thumbnail->fileName = $destpath;
1408                                 }
1409
1410                                 // This is quite odd, when watermark equals int(0) it seems all statements below ($watermark == 'image') and ($watermark == 'text') both evaluate as true
1411                                 // so we set it at null if it evaluates to any null-like value
1412                                 if ($watermark == null)
1413                                 {
1414                                         $watermark = null;
1415                                 }
1416                                 
1417                                 if ($watermark == 1 || $watermark === true)
1418                                 {
1419                                         if (in_array(strval($settings->wmType), array('image', 'text')))
1420                                         {
1421                                                 $watermark = $settings->wmType;
1422                                         }
1423                                         else
1424                                         {
1425                                                 $watermark = 'text';
1426                                         }
1427                                 }
1428                                 
1429                                 $watermark = strval($watermark);
1430
1431                                 if ($watermark == 'image')
1432                                 {
1433                                         $thumbnail->watermarkImgPath = $settings['wmPath'];
1434                                         $thumbnail->watermarkImage($settings['wmPos'], $settings['wmXpos'], $settings['wmYpos']);
1435                                 }
1436                                 else if ($watermark == 'text')
1437                                 {
1438                                         $thumbnail->watermarkText = $settings['wmText'];
1439                                         $thumbnail->watermarkCreateText($settings['wmColor'], $settings['wmFont'], $settings['wmSize'], $settings['wmOpaque']);
1440                                         $thumbnail->watermarkImage($settings['wmPos'], $settings['wmXpos'], $settings['wmYpos']);
1441                                 }
1442
1443                                 if ($rotation && in_array(abs($rotation), array(90, 180, 270)))
1444                                 {
1445                                         $thumbnail->rotateImageAngle($rotation);
1446                                 }
1447
1448                                 $flip = strtolower($flip);
1449
1450                                 if ($flip && in_array($flip, array('h', 'v', 'hv')))
1451                                 {
1452                                         $flip_h = in_array($flip, array('h', 'hv'));
1453                                         $flip_v = in_array($flip, array('v', 'hv'));
1454
1455                                         $thumbnail->flipImage($flip_h, $flip_v);
1456                                 }
1457
1458                                 if ($reflection)
1459                                 {
1460                                         $thumbnail->createReflection(40, 40, 50, FALSE, '#a4a4a4');
1461                                 }
1462
1463                                 if ($clone_format != null && isset($format_list[$clone_format]))
1464                                 {
1465                                         // Force format
1466                                         $thumbnail->format = strtoupper($format_list[$clone_format]);
1467                                 }
1468
1469                                 $thumbnail->save($destpath, $quality);
1470
1471                 // IF the original contained IPTC metadata we should attempt to copy it
1472                 if (isset($detailed_size['APP13']) && function_exists('iptcembed'))
1473                 {
1474                     $metadata = @iptcembed($detailed_size['APP13'], $destpath);
1475                     $fp = @fopen($destpath, 'wb');
1476                     @fwrite($fp, $metadata);
1477                     @fclose($fp);
1478                 }
1479                         }
1480                 }
1481
1482                 return $thumbnail;
1483         }
1484 }
1485
1486 class C_GalleryStorage_Driver_Base extends C_GalleryStorage_Base
1487 {
1488     public static $_instances = array();
1489
1490         function define($context)
1491         {
1492                 parent::define($context);
1493                 $this->add_mixin('Mixin_GalleryStorage_Driver_Base');
1494                 $this->implement('I_GalleryStorage_Driver');
1495         }
1496
1497         function initialize()
1498         {
1499                 parent::initialize();
1500                 $this->_gallery_mapper = $this->get_registry()->get_utility('I_Gallery_Mapper');
1501                 $this->_image_mapper = $this->get_registry()->get_utility('I_Image_Mapper');
1502         }
1503
1504     public static function get_instance($context = False)
1505     {
1506         if (!isset(self::$_instances[$context]))
1507         {
1508             self::$_instances[$context] = new C_GalleryStorage_Driver_Base($context);
1509         }
1510         return self::$_instances[$context];
1511     }
1512
1513
1514         /**
1515          * Gets the class name of the driver used
1516          * @return string
1517          */
1518         function get_driver_class_name()
1519         {
1520                 return get_called_class();
1521         }
1522 }