1<?php
2/**
3 * Copyright since 2007 PrestaShop SA and Contributors
4 * PrestaShop is an International Registered Trademark & Property of PrestaShop SA
5 *
6 * NOTICE OF LICENSE
7 *
8 * This source file is subject to the Open Software License (OSL 3.0)
9 * that is bundled with this package in the file LICENSE.md.
10 * It is also available through the world-wide-web at this URL:
11 * https://opensource.org/licenses/OSL-3.0
12 * If you did not receive a copy of the license and are unable to
13 * obtain it through the world-wide-web, please send an email
14 * to license@prestashop.com so we can send you a copy immediately.
15 *
16 * DISCLAIMER
17 *
18 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
19 * versions in the future. If you wish to customize PrestaShop for your
20 * needs please refer to https://devdocs.prestashop.com/ for more information.
21 *
22 * @author    PrestaShop SA and Contributors <contact@prestashop.com>
23 * @copyright Since 2007 PrestaShop SA and Contributors
24 * @license   https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
25 */
26class WebserviceSpecificManagementImagesCore implements WebserviceSpecificManagementInterface
27{
28    /** @var WebserviceOutputBuilder */
29    protected $objOutput;
30    protected $output;
31
32    /** @var WebserviceRequest */
33    protected $wsObject;
34
35    /**
36     * @var string The extension of the image to display
37     */
38    protected $imgExtension;
39
40    /**
41     * @var array The type of images (general, categories, manufacturers, suppliers, stores...)
42     */
43    protected $imageTypes = [
44        'general' => [
45            'header' => [],
46            'mail' => [],
47            'invoice' => [],
48            'store_icon' => [],
49        ],
50        'products' => [],
51        'categories' => [],
52        'manufacturers' => [],
53        'suppliers' => [],
54        'stores' => [],
55        'customizations' => [],
56    ];
57
58    /**
59     * @var string The image type (product, category, general,...)
60     */
61    protected $imageType = null;
62
63    /**
64     * @var int The maximum size supported when uploading images, in bytes
65     */
66    protected $imgMaxUploadSize = 3000000;
67
68    /**
69     * @var array The list of supported mime types
70     */
71    protected $acceptedImgMimeTypes = ['image/gif', 'image/jpg', 'image/jpeg', 'image/pjpeg', 'image/png', 'image/x-png'];
72
73    /**
74     * @var string The product image declination id
75     */
76    protected $productImageDeclinationId = null;
77
78    /**
79     * @var bool If the current image management has to manage a "default" image (i.e. "No product available")
80     */
81    protected $defaultImage = false;
82
83    /**
84     * @var string The file path of the image to display. If not null, the image will be displayed, even if the XML output was not empty
85     */
86    public $imgToDisplay = null;
87    public $imageResource = null;
88
89    /* ------------------------------------------------
90     * GETTERS & SETTERS
91     * ------------------------------------------------ */
92
93    /**
94     * @param WebserviceOutputBuilder $obj
95     *
96     * @return WebserviceSpecificManagementInterface
97     */
98    public function setObjectOutput(WebserviceOutputBuilderCore $obj)
99    {
100        $this->objOutput = $obj;
101
102        return $this;
103    }
104
105    public function getObjectOutput()
106    {
107        return $this->objOutput;
108    }
109
110    public function setWsObject(WebserviceRequestCore $obj)
111    {
112        $this->wsObject = $obj;
113
114        return $this;
115    }
116
117    public function getWsObject()
118    {
119        return $this->wsObject;
120    }
121
122    /*
123    * This method need $this->imgToDisplay to be set if output don't needs to be XML
124    */
125    public function getContent()
126    {
127        if ($this->output != '') {
128            return $this->objOutput->getObjectRender()->overrideContent($this->output);
129        } elseif ($this->imgToDisplay) {
130            // display image content if needed
131            if (empty($this->imgExtension)) {
132                $imginfo = getimagesize($this->imgToDisplay);
133                $this->imgExtension = image_type_to_extension($imginfo[2], false);
134            }
135            $imageResource = false;
136            $types = [
137                'jpg' => [
138                    'function' => 'imagecreatefromjpeg',
139                    'Content-Type' => 'image/jpeg',
140                ],
141                'jpeg' => [
142                    'function' => 'imagecreatefromjpeg',
143                    'Content-Type' => 'image/jpeg',
144                ],
145                'png' => ['function' => 'imagecreatefrompng',
146                    'Content-Type' => 'image/png',
147                ],
148                'gif' => [
149                    'function' => 'imagecreatefromgif',
150                    'Content-Type' => 'image/gif',
151                ],
152            ];
153            if (array_key_exists($this->imgExtension, $types)) {
154                $imageResource = @$types[$this->imgExtension]['function']($this->imgToDisplay);
155            }
156
157            if (!$imageResource) {
158                throw new WebserviceException(sprintf('Unable to load the image "%s"', str_replace(_PS_ROOT_DIR_, '[SHOP_ROOT_DIR]', $this->imgToDisplay)), [47, 500]);
159            } else {
160                if (array_key_exists($this->imgExtension, $types)) {
161                    $this->objOutput->setHeaderParams('Content-Type', $types[$this->imgExtension]['Content-Type']);
162                }
163
164                return file_get_contents($this->imgToDisplay);
165            }
166        }
167    }
168
169    public function manage()
170    {
171        $this->manageImages();
172
173        return $this->wsObject->getOutputEnabled();
174    }
175
176    /**
177     * Management of images URL segment.
178     *
179     * @return bool
180     *
181     * @throws WebserviceException
182     */
183    protected function manageImages()
184    {
185        /*
186         * available cases api/... :
187         *
188         *   images ("types_list") (N-1)
189         *   	GET    (xml)
190         *   images/general ("general_list") (N-2)
191         *   	GET    (xml)
192         *   images/general/[header,+] ("general") (N-3)
193         *   	GET    (bin)
194         *   	PUT    (bin)
195         *
196         *
197         *   images/[categories,+] ("normal_list") (N-2) ([categories,+] = categories, manufacturers, ...)
198         *   	GET    (xml)
199         *   images/[categories,+]/[1,+] ("normal") (N-3)
200         *   	GET    (bin)
201         *   	PUT    (bin)
202         *   	DELETE
203         *   	POST   (bin) (if image does not exists)
204         *   images/[categories,+]/[1,+]/[small,+] ("normal_resized") (N-4)
205         *   	GET    (bin)
206         *   images/[categories,+]/default ("display_list_of_langs") (N-3)
207         *   	GET    (xml)
208         *   images/[categories,+]/default/[en,+] ("normal_default_i18n")  (N-4)
209         *   	GET    (bin)
210         *   	POST   (bin) (if image does not exists)
211         *      PUT    (bin)
212         *      DELETE
213         *   images/[categories,+]/default/[en,+]/[small,+] ("normal_default_i18n_resized")  (N-5)
214         *   	GET    (bin)
215         *
216         *   images/product ("product_list")  (N-2)
217         *   	GET    (xml) (list of image)
218         *   images/product/[1,+] ("product_description")  (N-3)
219         *   	GET    (xml) (legend, declinations, xlink to images/product/[1,+]/bin)
220         *   images/product/[1,+]/bin ("product_bin")  (N-4)
221         *   	GET    (bin)
222         *      POST   (bin) (if image does not exists)
223         *   images/product/[1,+]/[1,+] ("product_declination")  (N-4)
224         *   	GET    (bin)
225         *   	POST   (xml) (legend)
226         *   	PUT    (xml) (legend)
227         *      DELETE
228         *   images/product/[1,+]/[1,+]/bin ("product_declination_bin") (N-5)
229         *   	POST   (bin) (if image does not exists)
230         *   	GET    (bin)
231         *   	PUT    (bin)
232         *   images/product/[1,+]/[1,+]/[small,+] ("product_declination_resized") (N-5)
233         *   	GET    (bin)
234         *   images/product/default ("product_default") (N-3)
235         *   	GET    (bin)
236         *   images/product/default/[en,+] ("product_default_i18n") (N-4)
237         *   	GET    (bin)
238         *      POST   (bin)
239         *      PUT   (bin)
240         *      DELETE
241         *   images/product/default/[en,+]/[small,+] ("product_default_i18n_resized") (N-5)
242         * 		GET    (bin)
243         *
244         */
245
246        /* Declinated
247         *ok    GET    (bin)
248         *ok images/product ("product_list")  (N-2)
249         *ok	GET    (xml) (list of image)
250         *ok images/product/[1,+] ("product_description")  (N-3)
251         *   	GET    (xml) (legend, declinations, xlink to images/product/[1,+]/bin)
252         *ok images/product/[1,+]/bin ("product_bin")  (N-4)
253         *ok 	GET    (bin)
254         *      POST   (bin) (if image does not exists)
255         *ok images/product/[1,+]/[1,+] ("product_declination")  (N-4)
256         *ok 	GET    (bin)
257         *   	POST   (xml) (legend)
258         *   	PUT    (xml) (legend)
259         *      DELETE
260         *ok images/product/[1,+]/[1,+]/bin ("product_declination_bin") (N-5)
261         *   	POST   (bin) (if image does not exists)
262         *ok 	GET    (bin)
263         *   	PUT    (bin)
264         *   images/product/[1,+]/[1,+]/[small,+] ("product_declination_resized") (N-5)
265         *ok 	GET    (bin)
266         *ok images/product/default ("product_default") (N-3)
267         *ok 	GET    (bin)
268         *ok images/product/default/[en,+] ("product_default_i18n") (N-4)
269         *ok 	GET    (bin)
270         *      POST   (bin)
271         *      PUT   (bin)
272         *      DELETE
273         *ok images/product/default/[en,+]/[small,+] ("product_default_i18n_resized") (N-5)
274         *ok	GET    (bin)
275         *
276         * */
277
278        // Pre configuration...
279        if (isset($this->wsObject->urlSegment)) {
280            for ($i = 1; $i < 6; ++$i) {
281                if (count($this->wsObject->urlSegment) == $i) {
282                    $this->wsObject->urlSegment[$i] = '';
283                }
284            }
285        }
286
287        $this->imageType = $this->wsObject->urlSegment[1];
288
289        switch ($this->wsObject->urlSegment[1]) {
290            // general images management : like header's logo, invoice logo, etc...
291            case 'general':
292                return $this->manageGeneralImages();
293
294                break;
295            // normal images management : like the most entity images (categories, manufacturers..)...
296            case 'categories':
297            case 'manufacturers':
298            case 'suppliers':
299            case 'stores':
300                switch ($this->wsObject->urlSegment[1]) {
301                    case 'categories':
302                        $directory = _PS_CAT_IMG_DIR_;
303
304                        break;
305                    case 'manufacturers':
306                        $directory = _PS_MANU_IMG_DIR_;
307
308                        break;
309                    case 'suppliers':
310                        $directory = _PS_SUPP_IMG_DIR_;
311
312                        break;
313                    case 'stores':
314                        $directory = _PS_STORE_IMG_DIR_;
315
316                        break;
317                }
318
319                return $this->manageDeclinatedImages($directory);
320
321                break;
322
323            // product image management : many image for one entity (product)
324            case 'products':
325                return $this->manageProductImages();
326
327                break;
328            case 'customizations':
329                return $this->manageCustomizationImages();
330
331                break;
332            // images root node management : many image for one entity (product)
333            case '':
334                $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image_types', []);
335                foreach (array_keys($this->imageTypes) as $image_type_name) {
336                    $more_attr = [
337                        'xlink_resource' => $this->wsObject->wsUrl . $this->wsObject->urlSegment[0] . '/' . $image_type_name,
338                        'get' => 'true', 'put' => 'false', 'post' => 'false', 'delete' => 'false', 'head' => 'true',
339                        'upload_allowed_mimetypes' => implode(', ', $this->acceptedImgMimeTypes),
340                    ];
341                    $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader($image_type_name, [], $more_attr, false);
342                }
343                $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('image_types', []);
344
345                return true;
346
347                break;
348            default:
349                $exception = new WebserviceException(sprintf('Image of type "%s" does not exist', $this->wsObject->urlSegment[1]), [48, 400]);
350
351                throw $exception->setDidYouMean($this->wsObject->urlSegment[1], array_keys($this->imageTypes));
352        }
353    }
354
355    /**
356     * Management of general images.
357     *
358     * @return bool
359     *
360     * @throws WebserviceException
361     */
362    protected function manageGeneralImages()
363    {
364        $path = '';
365        $alternative_path = '';
366        switch ($this->wsObject->urlSegment[2]) {
367            // Set the image path on display in relation to the header image
368            case 'header':
369                if (in_array($this->wsObject->method, ['GET', 'HEAD', 'PUT'])) {
370                    $path = _PS_IMG_DIR_ . Configuration::get('PS_LOGO');
371                } else {
372                    throw new WebserviceException('This method is not allowed with general image resources.', [49, 405]);
373                }
374
375                break;
376
377            // Set the image path on display in relation to the mail image
378            case 'mail':
379                if (in_array($this->wsObject->method, ['GET', 'HEAD', 'PUT'])) {
380                    $path = _PS_IMG_DIR_ . Configuration::get('PS_LOGO_MAIL');
381                    $alternative_path = _PS_IMG_DIR_ . Configuration::get('PS_LOGO');
382                } else {
383                    throw new WebserviceException('This method is not allowed with general image resources.', [50, 405]);
384                }
385
386                break;
387
388            // Set the image path on display in relation to the invoice image
389            case 'invoice':
390                if (in_array($this->wsObject->method, ['GET', 'HEAD', 'PUT'])) {
391                    $path = _PS_IMG_DIR_ . Configuration::get('PS_LOGO_INVOICE');
392                    $alternative_path = _PS_IMG_DIR_ . Configuration::get('PS_LOGO');
393                } else {
394                    throw new WebserviceException('This method is not allowed with general image resources.', [51, 405]);
395                }
396
397                break;
398
399            // Set the image path on display in relation to the icon store image
400            case 'store_icon':
401                if (in_array($this->wsObject->method, ['GET', 'HEAD', 'PUT'])) {
402                    $path = _PS_IMG_DIR_ . Configuration::get('PS_STORES_ICON');
403                    $this->imgExtension = 'gif';
404                } else {
405                    throw new WebserviceException('This method is not allowed with general image resources.', [52, 405]);
406                }
407
408                break;
409
410            // List the general image types
411            case '':
412                $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('general_image_types', []);
413                foreach (array_keys($this->imageTypes['general']) as $general_image_type_name) {
414                    $more_attr = [
415                        'xlink_resource' => $this->wsObject->wsUrl . $this->wsObject->urlSegment[0] . '/' . $this->wsObject->urlSegment[1] . '/' . $general_image_type_name,
416                        'get' => 'true', 'put' => 'true', 'post' => 'false', 'delete' => 'false', 'head' => 'true',
417                        'upload_allowed_mimetypes' => implode(', ', $this->acceptedImgMimeTypes),
418                    ];
419                    $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader($general_image_type_name, [], $more_attr, false);
420                }
421                $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('general_image_types', []);
422
423                return true;
424
425                break;
426
427            // If the image type does not exist...
428            default:
429                $exception = new WebserviceException(sprintf('General image of type "%s" does not exist', $this->wsObject->urlSegment[2]), [53, 400]);
430
431                throw $exception->setDidYouMean($this->wsObject->urlSegment[2], array_keys($this->imageTypes['general']));
432        }
433        // The general image type is valid, now we try to do action in relation to the method
434        switch ($this->wsObject->method) {
435            case 'GET':
436            case 'HEAD':
437                $this->imgToDisplay = ($path != '' && file_exists($path) && is_file($path)) ? $path : $alternative_path;
438
439                return true;
440
441                break;
442            case 'PUT':
443                if ($this->writePostedImageOnDisk($path, null, null)) {
444                    if ($this->wsObject->urlSegment[2] == 'header') {
445                        $logo_name = Configuration::get('PS_LOGO') ? Configuration::get('PS_LOGO') : 'logo.jpg';
446                        list($width, $height, $type, $attr) = getimagesize(_PS_IMG_DIR_ . $logo_name);
447                        Configuration::updateValue('SHOP_LOGO_WIDTH', (int) round($width));
448                        Configuration::updateValue('SHOP_LOGO_HEIGHT', (int) round($height));
449                    }
450                    $this->imgToDisplay = $path;
451
452                    return true;
453                } else {
454                    throw new WebserviceException('Error while copying image to the directory', [54, 400]);
455                }
456
457                break;
458        }
459    }
460
461    protected function manageDefaultDeclinatedImages($directory, $normal_image_sizes)
462    {
463        $this->defaultImage = true;
464        // Get the language iso code list
465        $lang_list = Language::getIsoIds(true);
466        $langs = [];
467        $default_lang = Configuration::get('PS_LANG_DEFAULT');
468        foreach ($lang_list as $lang) {
469            if ($lang['id_lang'] == $default_lang) {
470                $default_lang = $lang['iso_code'];
471            }
472            $langs[] = $lang['iso_code'];
473        }
474
475        // Display list of languages
476        if ($this->wsObject->urlSegment[3] == '' && $this->wsObject->method == 'GET') {
477            $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('languages', []);
478            foreach ($lang_list as $lang) {
479                $more_attr = [
480                    'xlink_resource' => $this->wsObject->wsUrl . 'images/' . $this->imageType . '/default/' . $lang['iso_code'],
481                    'get' => 'true', 'put' => 'true', 'post' => 'true', 'delete' => 'true', 'head' => 'true',
482                    'upload_allowed_mimetypes' => implode(', ', $this->acceptedImgMimeTypes),
483                    'iso' => $lang['iso_code'],
484                ];
485                $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('language', [], $more_attr, false);
486            }
487
488            $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('languages', []);
489
490            return true;
491        } else {
492            $lang_iso = $this->wsObject->urlSegment[3];
493            $image_size = $this->wsObject->urlSegment[4];
494            if ($image_size != '') {
495                $filename = $directory . $lang_iso . '-default-' . $image_size . '.jpg';
496            } else {
497                $filename = $directory . $lang_iso . '.jpg';
498            }
499            $filename_exists = file_exists($filename);
500
501            return $this->manageDeclinatedImagesCRUD($filename_exists, $filename, $normal_image_sizes, $directory); // @todo : [feature] @see todo#1
502        }
503    }
504
505    protected function manageListDeclinatedImages($directory, $normal_image_sizes)
506    {
507        // Check if method is allowed
508        if ($this->wsObject->method != 'GET') {
509            throw new WebserviceException('This method is not allowed for listing category images.', [55, 405]);
510        }
511
512        $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image_types', []);
513        foreach ($normal_image_sizes as $image_size) {
514            $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image_type', [], ['id' => $image_size['id_image_type'], 'name' => $image_size['name'], 'xlink_resource' => $this->wsObject->wsUrl . 'image_types/' . $image_size['id_image_type']], false);
515        }
516        $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('image_types', []);
517        $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('images', []);
518
519        if ($this->imageType == 'products') {
520            $ids = [];
521            $images = Image::getAllImages();
522            foreach ($images as $image) {
523                $ids[] = $image['id_product'];
524            }
525            $ids = array_unique($ids, SORT_NUMERIC);
526            asort($ids);
527            foreach ($ids as $id) {
528                $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image', [], ['id' => $id, 'xlink_resource' => $this->wsObject->wsUrl . 'images/' . $this->imageType . '/' . $id], false);
529            }
530        } else {
531            $nodes = scandir($directory, SCANDIR_SORT_NONE);
532            foreach ($nodes as $node) {
533                // avoid too much preg_match...
534                if ($node != '.' && $node != '..' && $node != '.svn') {
535                    if ($this->imageType != 'products') {
536                        preg_match('/^(\d+)\.jpg*$/Ui', $node, $matches);
537                        if (isset($matches[1])) {
538                            $id = $matches[1];
539                            $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image', [], ['id' => $id, 'xlink_resource' => $this->wsObject->wsUrl . 'images/' . $this->imageType . '/' . $id], false);
540                        }
541                    }
542                }
543            }
544        }
545        $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('images', []);
546
547        return true;
548    }
549
550    protected function manageEntityDeclinatedImages($directory, $normal_image_sizes)
551    {
552        $normal_image_size_names = [];
553        foreach ($normal_image_sizes as $normal_image_size) {
554            $normal_image_size_names[] = $normal_image_size['name'];
555        }
556        // If id is detected
557        $object_id = $this->wsObject->urlSegment[2];
558        if (!Validate::isUnsignedId($object_id)) {
559            throw new WebserviceException('The image id is invalid. Please set a valid id or the "default" value', [60, 400]);
560        }
561
562        // For the product case
563        if ($this->imageType == 'products') {
564            // Get available image ids
565            $available_image_ids = [];
566
567            // New Behavior
568            foreach (Language::getIDs() as $id_lang) {
569                foreach (Image::getImages($id_lang, $object_id) as $image) {
570                    $available_image_ids[] = $image['id_image'];
571                }
572            }
573            $available_image_ids = array_unique($available_image_ids, SORT_NUMERIC);
574
575            // If an image id is specified
576            if ($this->wsObject->urlSegment[3] != '') {
577                if ($this->wsObject->urlSegment[3] == 'bin') {
578                    $current_product = new Product($object_id);
579                    $this->wsObject->urlSegment[3] = $current_product->getCoverWs();
580                }
581                if (!Validate::isUnsignedId($object_id) || !in_array($this->wsObject->urlSegment[3], $available_image_ids)) {
582                    throw new WebserviceException('This image id does not exist', [57, 400]);
583                } else {
584                    // Check for new image system
585                    $image_id = $this->wsObject->urlSegment[3];
586                    $path = implode('/', str_split((string) $image_id));
587                    $image_size = $this->wsObject->urlSegment[4];
588
589                    if (file_exists($directory . $path . '/' . $image_id . (strlen($this->wsObject->urlSegment[4]) > 0 ? '-' . $this->wsObject->urlSegment[4] : '') . '.jpg')) {
590                        $filename = $directory . $path . '/' . $image_id . (strlen($this->wsObject->urlSegment[4]) > 0 ? '-' . $this->wsObject->urlSegment[4] : '') . '.jpg';
591                        $orig_filename = $directory . $path . '/' . $image_id . '.jpg';
592                    } else {
593                        // else old system or not exists
594
595                        $orig_filename = $directory . $object_id . '-' . $image_id . '.jpg';
596                        $filename = $directory . $object_id . '-' . $image_id . '-' . $image_size . '.jpg';
597                    }
598                }
599            } elseif ($this->wsObject->method == 'GET' || $this->wsObject->method == 'HEAD') {
600                // display the list of declinated images
601                if ($available_image_ids) {
602                    $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image', [], ['id' => $object_id]);
603                    foreach ($available_image_ids as $available_image_id) {
604                        $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('declination', [], ['id' => $available_image_id, 'xlink_resource' => $this->wsObject->wsUrl . 'images/' . $this->imageType . '/' . $object_id . '/' . $available_image_id], false);
605                    }
606                    $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('image', []);
607                } else {
608                    $this->objOutput->setStatus(404);
609                    $this->wsObject->setOutputEnabled(false);
610
611                    return true;
612                }
613            }
614        } else {
615            // for all other cases
616            $orig_filename = $directory . $object_id . '.jpg';
617            $image_size = $this->wsObject->urlSegment[3];
618            $filename = $directory . $object_id . '-' . $image_size . '.jpg';
619        }
620
621        // in case of declinated images list of a product is get
622        if ($this->output != '') {
623            return true;
624        } elseif (isset($image_size) && $image_size != '') {
625            // If a size was given try to display it
626
627            // Check the given size
628            if ($this->imageType == 'products' && $image_size == 'bin') {
629                $filename = $directory . $object_id . '-' . $image_id . '.jpg';
630            } elseif (!in_array($image_size, $normal_image_size_names)) {
631                $exception = new WebserviceException('This image size does not exist', [58, 400]);
632
633                throw $exception->setDidYouMean($image_size, $normal_image_size_names);
634            }
635            if (!file_exists($filename)) {
636                throw new WebserviceException('This image does not exist on disk', [59, 500]);
637            }
638
639            // Display the resized specific image
640            $this->imgToDisplay = $filename;
641
642            return true;
643        } elseif (isset($orig_filename)) {
644            // Management of the original image (GET, PUT, POST, DELETE)
645            $orig_filename_exists = file_exists($orig_filename);
646
647            return $this->manageDeclinatedImagesCRUD($orig_filename_exists, $orig_filename, $normal_image_sizes, $directory);
648        } else {
649            return $this->manageDeclinatedImagesCRUD(false, '', $normal_image_sizes, $directory);
650        }
651    }
652
653    /**
654     * Management of normal images (as categories, suppliers, manufacturers and stores).
655     *
656     * @param string $directory the file path of the root of the images folder type
657     *
658     * @return bool
659     */
660    protected function manageDeclinatedImages($directory)
661    {
662        // Get available image sizes for the current image type
663        $normal_image_sizes = ImageType::getImagesTypes($this->imageType);
664        switch ($this->wsObject->urlSegment[2]) {
665            // Match the default images
666            case 'default':
667                return $this->manageDefaultDeclinatedImages($directory, $normal_image_sizes);
668
669                break;
670            // Display the list of images
671            case '':
672                return $this->manageListDeclinatedImages($directory, $normal_image_sizes);
673
674                break;
675            default:
676                return $this->manageEntityDeclinatedImages($directory, $normal_image_sizes);
677
678                break;
679        }
680    }
681
682    protected function manageProductImages()
683    {
684        $this->manageDeclinatedImages(_PS_PROD_IMG_DIR_);
685    }
686
687    protected function getCustomizations()
688    {
689        $customizations = [];
690        if (!$results = Db::getInstance()->executeS('
691			SELECT DISTINCT c.`id_customization`
692			FROM `' . _DB_PREFIX_ . 'customization` c
693			NATURAL JOIN `' . _DB_PREFIX_ . 'customization_field` cf
694			WHERE c.`id_cart` = ' . (int) $this->wsObject->urlSegment[2] . '
695			AND type = 0')) {
696            return [];
697        }
698        foreach ($results as $result) {
699            $customizations[] = $result['id_customization'];
700        }
701
702        return $customizations;
703    }
704
705    protected function manageCustomizationImages()
706    {
707        $normal_image_sizes = ImageType::getImagesTypes($this->imageType);
708        if (empty($this->wsObject->urlSegment[2])) {
709            $results = Db::getInstance()->executeS('SELECT DISTINCT `id_cart` FROM `' . _DB_PREFIX_ . 'customization`');
710            $ids = [];
711            foreach ($results as $result) {
712                $ids[] = $result['id_cart'];
713            }
714            asort($ids);
715            $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('carts', []);
716            foreach ($ids as $id) {
717                $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('cart', [], ['id' => $id, 'xlink_resource' => $this->wsObject->wsUrl . 'images/' . $this->imageType . '/' . $id], false);
718            }
719            $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('carts', []);
720
721            return true;
722        } elseif (empty($this->wsObject->urlSegment[3])) {
723            $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('customizations', []);
724            $customizations = $this->getCustomizations();
725            foreach ($customizations as $id) {
726                $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('customization', [], ['id' => $id, 'xlink_resource' => $this->wsObject->wsUrl . 'images/' . $this->imageType . '/' . $id], false);
727            }
728            $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('customizations', []);
729
730            return true;
731        } elseif (empty($this->wsObject->urlSegment[4])) {
732            if ($this->wsObject->method == 'GET') {
733                $results = Db::getInstance()->executeS(
734                    'SELECT *
735					FROM `' . _DB_PREFIX_ . 'customized_data`
736					WHERE id_customization = ' . (int) $this->wsObject->urlSegment[3] . ' AND type = 0'
737                );
738
739                $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('images', []);
740                foreach ($results as $result) {
741                    $this->output .= $this->objOutput->getObjectRender()->renderNodeHeader('image', [], ['id' => $result['index'], 'xlink_resource' => $this->wsObject->wsUrl . 'images/' . $this->imageType . '/' . $result['index']], false);
742                }
743                $this->output .= $this->objOutput->getObjectRender()->renderNodeFooter('images', []);
744
745                return true;
746            }
747        } else {
748            if ($this->wsObject->method == 'GET') {
749                $results = Db::getInstance()->executeS(
750                    'SELECT *
751					FROM `' . _DB_PREFIX_ . 'customized_data`
752					WHERE id_customization = ' . (int) $this->wsObject->urlSegment[3] . '
753					AND `index` = ' . (int) $this->wsObject->urlSegment[4]
754                );
755                if (empty($results[0]) || empty($results[0]['value'])) {
756                    throw new WebserviceException('This image does not exist on disk', [61, 500]);
757                }
758                $this->imgToDisplay = _PS_UPLOAD_DIR_ . $results[0]['value'];
759
760                return true;
761            }
762            if ($this->wsObject->method == 'POST') {
763                $customizations = $this->getCustomizations();
764                if (!in_array((int) $this->wsObject->urlSegment[3], $customizations)) {
765                    throw new WebserviceException('Customization does not exist', [61, 500]);
766                }
767                $results = Db::getInstance()->executeS(
768                    'SELECT id_customization_field
769					FROM `' . _DB_PREFIX_ . 'customization_field`
770					WHERE id_customization_field = ' . (int) $this->wsObject->urlSegment[4] . '
771					AND type = 0'
772                );
773                if (empty($results)) {
774                    throw new WebserviceException('Customization field does not exist.', [61, 500]);
775                }
776                $results = Db::getInstance()->executeS(
777                    'SELECT *
778					FROM `' . _DB_PREFIX_ . 'customized_data`
779					WHERE id_customization = ' . (int) $this->wsObject->urlSegment[3] . '
780					AND `index` = ' . (int) $this->wsObject->urlSegment[4] . '
781					AND type = 0'
782                );
783                if (!empty($results)) { // customization field exists and has no value
784                    throw new WebserviceException('Customization field already have a value, please use PUT method.', [61, 500]);
785                }
786
787                return $this->manageDeclinatedImagesCRUD(false, '', $normal_image_sizes, _PS_UPLOAD_DIR_);
788            }
789            $results = Db::getInstance()->executeS(
790                'SELECT *
791				FROM `' . _DB_PREFIX_ . 'customized_data`
792				WHERE id_customization = ' . (int) $this->wsObject->urlSegment[3] . '
793				AND `index` = ' . (int) $this->wsObject->urlSegment[4]
794            );
795            if (empty($results[0]) || empty($results[0]['value'])) {
796                throw new WebserviceException('This image does not exist on disk', [61, 500]);
797            }
798            $this->imgToDisplay = _PS_UPLOAD_DIR_ . $results[0]['value'];
799            $filename_exists = file_exists($this->imgToDisplay);
800
801            return $this->manageDeclinatedImagesCRUD($filename_exists, $this->imgToDisplay, $normal_image_sizes, _PS_UPLOAD_DIR_);
802        }
803    }
804
805    /**
806     * Management of normal images CRUD.
807     *
808     * @param bool $filename_exists if the filename exists
809     * @param string $filename the image path
810     * @param array $image_sizes The
811     * @param string $directory
812     *
813     * @return bool
814     *
815     * @throws WebserviceException
816     */
817    protected function manageDeclinatedImagesCRUD($filename_exists, $filename, $image_sizes, $directory)
818    {
819        switch ($this->wsObject->method) {
820            // Display the image
821            case 'GET':
822            case 'HEAD':
823                if ($filename_exists) {
824                    $this->imgToDisplay = $filename;
825                } else {
826                    throw new WebserviceException('This image does not exist on disk', [61, 500]);
827                }
828
829                break;
830            // Modify the image
831            case 'PUT':
832                if ($filename_exists) {
833                    if ($this->writePostedImageOnDisk($filename, null, null, $image_sizes, $directory)) {
834                        $this->imgToDisplay = $filename;
835
836                        return true;
837                    } else {
838                        throw new WebserviceException('Unable to save this image.', [62, 500]);
839                    }
840                } else {
841                    throw new WebserviceException('This image does not exist on disk', [63, 500]);
842                }
843
844                break;
845            // Delete the image
846            case 'DELETE':
847                // Delete products image in DB
848                if ($this->imageType == 'products') {
849                    $image = new Image((int) $this->wsObject->urlSegment[3]);
850
851                    return $image->delete();
852                } elseif ($filename_exists) {
853                    if (in_array($this->imageType, ['categories', 'manufacturers', 'suppliers', 'stores'])) {
854                        /** @var ObjectModel $object */
855                        $object = new $this->wsObject->resourceList[$this->imageType]['class']((int) $this->wsObject->urlSegment[2]);
856
857                        return $object->deleteImage(true);
858                    } else {
859                        return $this->deleteImageOnDisk($filename, $image_sizes, $directory);
860                    }
861                } else {
862                    throw new WebserviceException('This image does not exist on disk', [64, 500]);
863                }
864
865                break;
866            // Add the image
867            case 'POST':
868                if ($filename_exists) {
869                    throw new WebserviceException('This image already exists. To modify it, please use the PUT method', [65, 400]);
870                } else {
871                    if ($this->writePostedImageOnDisk($filename, null, null, $image_sizes, $directory)) {
872                        return true;
873                    } else {
874                        throw new WebserviceException('Unable to save this image', [66, 500]);
875                    }
876                }
877
878                break;
879            default:
880                throw new WebserviceException('This method is not allowed', [67, 405]);
881        }
882    }
883
884    /**
885     * Delete the image on disk.
886     *
887     * @param string $file_path the image file path
888     * @param array $image_types The different sizes
889     * @param string $parent_path The parent path
890     *
891     * @return bool
892     */
893    protected function deleteImageOnDisk($file_path, $image_types = null, $parent_path = null)
894    {
895        $this->wsObject->setOutputEnabled(false);
896        if (file_exists($file_path)) {
897            // delete image on disk
898            @unlink($file_path);
899            // Delete declinated image if needed
900            if ($image_types) {
901                foreach ($image_types as $image_type) {
902                    if ($this->defaultImage) { /** @todo products images too !! */
903                        $declination_path = $parent_path . $this->wsObject->urlSegment[3] . '-default-' . $image_type['name'] . '.jpg';
904                    } else {
905                        $declination_path = $parent_path . $this->wsObject->urlSegment[2] . '-' . $image_type['name'] . '.jpg';
906                    }
907                    if (!@unlink($declination_path)) {
908                        $this->objOutput->setStatus(204);
909
910                        return false;
911                    }
912                }
913            }
914
915            return true;
916        } else {
917            $this->objOutput->setStatus(204);
918
919            return false;
920        }
921    }
922
923    /**
924     * Write the image on disk.
925     *
926     * @param string $base_path
927     * @param string $new_path
928     * @param int $dest_width
929     * @param int $dest_height
930     * @param array $image_types
931     * @param string $parent_path
932     *
933     * @return string
934     *
935     * @throws WebserviceException
936     */
937    protected function writeImageOnDisk($base_path, $new_path, $dest_width = null, $dest_height = null, $image_types = null, $parent_path = null)
938    {
939        list($source_width, $source_height, $type, $attr) = getimagesize($base_path);
940        if (!$source_width) {
941            throw new WebserviceException('Image width was null', [68, 400]);
942        }
943        if ($dest_width == null) {
944            $dest_width = $source_width;
945        }
946        if ($dest_height == null) {
947            $dest_height = $source_height;
948        }
949        switch ($type) {
950            case 1:
951                $source_image = imagecreatefromgif($base_path);
952
953                break;
954            case 3:
955                $source_image = imagecreatefrompng($base_path);
956
957                break;
958            case 2:
959            default:
960                $source_image = imagecreatefromjpeg($base_path);
961
962                break;
963        }
964
965        $width_diff = $dest_width / $source_width;
966        $height_diff = $dest_height / $source_height;
967
968        if ($width_diff > 1 && $height_diff > 1) {
969            $next_width = $source_width;
970            $next_height = $source_height;
971        } else {
972            if ((int) (Configuration::get('PS_IMAGE_GENERATION_METHOD')) == 2 || ((int) (Configuration::get('PS_IMAGE_GENERATION_METHOD')) == 0 && $width_diff > $height_diff)) {
973                $next_height = $dest_height;
974                $next_width = (int) (($source_width * $next_height) / $source_height);
975                $dest_width = ((int) (Configuration::get('PS_IMAGE_GENERATION_METHOD')) == 0 ? $dest_width : $next_width);
976            } else {
977                $next_width = $dest_width;
978                $next_height = (int) ($source_height * $dest_width / $source_width);
979                $dest_height = ((int) (Configuration::get('PS_IMAGE_GENERATION_METHOD')) == 0 ? $dest_height : $next_height);
980            }
981        }
982
983        $border_width = (int) (($dest_width - $next_width) / 2);
984        $border_height = (int) (($dest_height - $next_height) / 2);
985
986        // Build the image
987        if (
988            !($dest_image = imagecreatetruecolor($dest_width, $dest_height)) ||
989            !($white = imagecolorallocate($dest_image, 255, 255, 255)) ||
990            !imagefill($dest_image, 0, 0, $white) ||
991            !imagecopyresampled($dest_image, $source_image, $border_width, $border_height, 0, 0, $next_width, $next_height, $source_width, $source_height) ||
992            !imagecolortransparent($dest_image, $white)
993        ) {
994            throw new WebserviceException(sprintf('Unable to build the image "%s".', str_replace(_PS_ROOT_DIR_, '[SHOP_ROOT_DIR]', $new_path)), [69, 500]);
995        }
996
997        // Write it on disk
998
999        switch ($this->imgExtension) {
1000            case 'gif':
1001                $imaged = imagegif($dest_image, $new_path);
1002
1003                break;
1004            case 'png':
1005                $quality = (Configuration::get('PS_PNG_QUALITY') === false ? 7 : Configuration::get('PS_PNG_QUALITY'));
1006                $imaged = imagepng($dest_image, $new_path, (int) $quality);
1007
1008                break;
1009            case 'jpeg':
1010            default:
1011                $quality = (Configuration::get('PS_JPEG_QUALITY') === false ? 90 : Configuration::get('PS_JPEG_QUALITY'));
1012                $imaged = imagejpeg($dest_image, $new_path, (int) $quality);
1013                if ($this->wsObject->urlSegment[1] == 'customizations') {
1014                    // write smaller image in case of customization image
1015                    $product_picture_width = (int) Configuration::get('PS_PRODUCT_PICTURE_WIDTH');
1016                    $product_picture_height = (int) Configuration::get('PS_PRODUCT_PICTURE_HEIGHT');
1017                    if (!ImageManager::resize($new_path, $new_path . '_small', $product_picture_width, $product_picture_height)) {
1018                        $this->errors[] = Context::getContext()->getTranslator()->trans('An error occurred while uploading the image.', [], 'Admin.Notifications.Error');
1019                    }
1020                }
1021
1022                break;
1023        }
1024        imagedestroy($dest_image);
1025        if (!$imaged) {
1026            throw new WebserviceException(sprintf('Unable to write the image "%s".', str_replace(_PS_ROOT_DIR_, '[SHOP_ROOT_DIR]', $new_path)), [70, 500]);
1027        }
1028
1029        // Write image declinations if present
1030        if ($image_types) {
1031            foreach ($image_types as $image_type) {
1032                if ($this->defaultImage) {
1033                    $declination_path = $parent_path . $this->wsObject->urlSegment[3] . '-default-' . $image_type['name'] . '.jpg';
1034                } else {
1035                    if ($this->imageType == 'products') {
1036                        $declination_path = $parent_path . chunk_split($this->wsObject->urlSegment[3], 1, '/') . $this->wsObject->urlSegment[3] . '-' . $image_type['name'] . '.jpg';
1037                    } else {
1038                        $declination_path = $parent_path . $this->wsObject->urlSegment[2] . '-' . $image_type['name'] . '.jpg';
1039                    }
1040                }
1041                if (!$this->writeImageOnDisk($base_path, $declination_path, $image_type['width'], $image_type['height'])) {
1042                    throw new WebserviceException(sprintf('Unable to save the declination "%s" of this image.', $image_type['name']), [71, 500]);
1043                }
1044            }
1045        }
1046
1047        Hook::exec('actionWatermark', ['id_image' => $this->wsObject->urlSegment[3], 'id_product' => $this->wsObject->urlSegment[2]]);
1048
1049        return $new_path;
1050    }
1051
1052    /**
1053     * Write the posted image on disk.
1054     *
1055     * @param string $reception_path
1056     * @param int $dest_width
1057     * @param int $dest_height
1058     * @param array $image_types
1059     * @param string $parent_path
1060     *
1061     * @return bool
1062     *
1063     * @throws WebserviceException
1064     */
1065    protected function writePostedImageOnDisk($reception_path, $dest_width = null, $dest_height = null, $image_types = null, $parent_path = null)
1066    {
1067        if ($this->wsObject->method == 'PUT') {
1068            if (isset($_FILES['image']['tmp_name']) && $_FILES['image']['tmp_name']) {
1069                $file = $_FILES['image'];
1070                if ($file['size'] > $this->imgMaxUploadSize) {
1071                    throw new WebserviceException(sprintf('The image size is too large (maximum allowed is %d KB)', ($this->imgMaxUploadSize / 1000)), [72, 400]);
1072                }
1073                // Get mime content type
1074                $mime_type = false;
1075                if (Tools::isCallable('finfo_open')) {
1076                    $const = defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME;
1077                    $finfo = finfo_open($const);
1078                    $mime_type = finfo_file($finfo, $file['tmp_name']);
1079                    finfo_close($finfo);
1080                } elseif (Tools::isCallable('mime_content_type')) {
1081                    $mime_type = mime_content_type($file['tmp_name']);
1082                } elseif (Tools::isCallable('exec')) {
1083                    $mime_type = trim(exec('file -b --mime-type ' . escapeshellarg($file['tmp_name'])));
1084                }
1085                if (empty($mime_type) || $mime_type == 'regular file') {
1086                    $mime_type = $file['type'];
1087                }
1088                if (($pos = strpos($mime_type, ';')) !== false) {
1089                    $mime_type = substr($mime_type, 0, $pos);
1090                }
1091
1092                // Check mime content type
1093                if (!$mime_type || !in_array($mime_type, $this->acceptedImgMimeTypes)) {
1094                    throw new WebserviceException('This type of image format is not recognized, allowed formats are: ' . implode('", "', $this->acceptedImgMimeTypes), [73, 400]);
1095                } elseif ($file['error']) {
1096                    // Check error while uploading
1097                    throw new WebserviceException('Error while uploading image. Please change your server\'s settings', [74, 400]);
1098                }
1099
1100                // Try to copy image file to a temporary file
1101                if (!($tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($_FILES['image']['tmp_name'], $tmp_name)) {
1102                    throw new WebserviceException('Error while copying image to the temporary directory', [75, 400]);
1103                } else {
1104                    // Try to copy image file to the image directory
1105                    $result = $this->writeImageOnDisk($tmp_name, $reception_path, $dest_width, $dest_height, $image_types, $parent_path);
1106                }
1107
1108                @unlink($tmp_name);
1109
1110                return $result;
1111            } else {
1112                throw new WebserviceException('Please set an "image" parameter with image data for value', [76, 400]);
1113            }
1114        } elseif ($this->wsObject->method == 'POST') {
1115            if (isset($_FILES['image']['tmp_name']) && $_FILES['image']['tmp_name']) {
1116                $file = $_FILES['image'];
1117                if ($file['size'] > $this->imgMaxUploadSize) {
1118                    throw new WebserviceException(sprintf('The image size is too large (maximum allowed is %d KB)', ($this->imgMaxUploadSize / 1000)), [72, 400]);
1119                }
1120                if ($error = ImageManager::validateUpload($file)) {
1121                    throw new WebserviceException('Image upload error : ' . $error, [76, 400]);
1122                }
1123
1124                if (isset($file['tmp_name']) && $file['tmp_name'] != null) {
1125                    if ($this->imageType == 'products') {
1126                        $product = new Product((int) $this->wsObject->urlSegment[2]);
1127                        if (!Validate::isLoadedObject($product)) {
1128                            throw new WebserviceException('Product ' . (int) $this->wsObject->urlSegment[2] . ' does not exist', [76, 400]);
1129                        }
1130                        $image = new Image();
1131                        $image->id_product = (int) ($product->id);
1132                        $image->position = Image::getHighestPosition($product->id) + 1;
1133
1134                        if (!Image::getCover((int) $product->id)) {
1135                            $image->cover = 1;
1136                        } else {
1137                            $image->cover = 0;
1138                        }
1139
1140                        if (!$image->add()) {
1141                            throw new WebserviceException('Error while creating image', [76, 400]);
1142                        }
1143                        if (!Validate::isLoadedObject($product)) {
1144                            throw new WebserviceException('Product ' . (int) $this->wsObject->urlSegment[2] . ' does not exist', [76, 400]);
1145                        }
1146                        Hook::exec('actionProductUpdate', ['id_product' => (int) $this->wsObject->urlSegment[2]]);
1147                    }
1148
1149                    // copy image
1150                    if (!isset($file['tmp_name'])) {
1151                        return false;
1152                    }
1153                    if ($error = ImageManager::validateUpload($file, $this->imgMaxUploadSize)) {
1154                        throw new WebserviceException('Bad image : ' . $error, [76, 400]);
1155                    }
1156
1157                    if ($this->imageType == 'products') {
1158                        $image = new Image($image->id);
1159                        if (!(Configuration::get('PS_OLD_FILESYSTEM') && file_exists(_PS_PROD_IMG_DIR_ . $product->id . '-' . $image->id . '.jpg'))) {
1160                            $image->createImgFolder();
1161                        }
1162
1163                        if (!($tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($file['tmp_name'], $tmp_name)) {
1164                            throw new WebserviceException('An error occurred during the image upload', [76, 400]);
1165                        } elseif (!ImageManager::resize($tmp_name, _PS_PROD_IMG_DIR_ . $image->getExistingImgPath() . '.' . $image->image_format)) {
1166                            throw new WebserviceException('An error occurred while copying image', [76, 400]);
1167                        } else {
1168                            $images_types = ImageType::getImagesTypes('products');
1169                            foreach ($images_types as $imageType) {
1170                                if (!ImageManager::resize($tmp_name, _PS_PROD_IMG_DIR_ . $image->getExistingImgPath() . '-' . stripslashes($imageType['name']) . '.' . $image->image_format, $imageType['width'], $imageType['height'], $image->image_format)) {
1171                                    $this->_errors[] = Context::getContext()->getTranslator()->trans('An error occurred while copying this image: %s', [stripslashes($imageType['name'])], 'Admin.Notifications.Error');
1172                                }
1173                            }
1174                        }
1175                        @unlink($tmp_name);
1176
1177                        Hook::exec('actionWatermark', ['id_image' => $image->id, 'id_product' => $image->id_product]);
1178
1179                        $this->imgToDisplay = _PS_PROD_IMG_DIR_ . $image->getExistingImgPath() . '.' . $image->image_format;
1180                        $this->objOutput->setFieldsToDisplay('full');
1181                        $this->output = $this->objOutput->renderEntity($image, 1);
1182                        $image_content = ['sqlId' => 'content', 'value' => base64_encode(file_get_contents($this->imgToDisplay)), 'encode' => 'base64'];
1183                        $this->output .= $this->objOutput->objectRender->renderField($image_content);
1184                    } elseif (in_array($this->imageType, ['categories', 'manufacturers', 'suppliers', 'stores'])) {
1185                        if (!($tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($file['tmp_name'], $tmp_name)) {
1186                            throw new WebserviceException('An error occurred during the image upload', [76, 400]);
1187                        } elseif (!ImageManager::resize($tmp_name, $reception_path)) {
1188                            throw new WebserviceException('An error occurred while copying image', [76, 400]);
1189                        }
1190                        $images_types = ImageType::getImagesTypes($this->imageType);
1191                        foreach ($images_types as $imageType) {
1192                            if (!ImageManager::resize($tmp_name, $parent_path . $this->wsObject->urlSegment[2] . '-' . stripslashes($imageType['name']) . '.jpg', $imageType['width'], $imageType['height'])) {
1193                                $this->_errors[] = Context::getContext()->getTranslator()->trans('An error occurred while copying this image: %s', [stripslashes($imageType['name'])], 'Admin.Notifications.Error');
1194                            }
1195                        }
1196                        @unlink(_PS_TMP_IMG_DIR_ . $tmp_name);
1197                        $this->imgToDisplay = $reception_path;
1198                    } elseif ($this->imageType == 'customizations') {
1199                        $filename = md5(uniqid(mt_rand(0, mt_getrandmax()), true));
1200                        $this->imgToDisplay = _PS_UPLOAD_DIR_ . $filename;
1201                        if (!($tmp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS')) || !move_uploaded_file($file['tmp_name'], $tmp_name)) {
1202                            throw new WebserviceException('An error occurred during the image upload', [76, 400]);
1203                        } elseif (!ImageManager::resize($tmp_name, $this->imgToDisplay)) {
1204                            throw new WebserviceException('An error occurred while copying image', [76, 400]);
1205                        }
1206                        $product_picture_width = (int) Configuration::get('PS_PRODUCT_PICTURE_WIDTH');
1207                        $product_picture_height = (int) Configuration::get('PS_PRODUCT_PICTURE_HEIGHT');
1208                        if (!ImageManager::resize($this->imgToDisplay, $this->imgToDisplay . '_small', $product_picture_width, $product_picture_height)) {
1209                            throw new WebserviceException('An error occurred while resizing image', [76, 400]);
1210                        }
1211                        @unlink(_PS_TMP_IMG_DIR_ . $tmp_name);
1212
1213                        $query = 'INSERT INTO `' . _DB_PREFIX_ . 'customized_data` (`id_customization`, `type`, `index`, `value`)
1214							VALUES (' . (int) $this->wsObject->urlSegment[3] . ', 0, ' . (int) $this->wsObject->urlSegment[4] . ', \'' . $filename . '\')';
1215
1216                        if (!Db::getInstance()->execute($query)) {
1217                            return false;
1218                        }
1219                    }
1220
1221                    return true;
1222                }
1223            } else {
1224                throw new WebserviceException('Please set an "image" parameter with image data for value', [76, 400]);
1225            }
1226        } else {
1227            throw new WebserviceException('Method ' . $this->wsObject->method . ' is not allowed for an image resource', [77, 405]);
1228        }
1229    }
1230}
1231