dbXapp 2.0
RAD, CMS, Module und Runtime-IDE fuer dbXapp
Loading...
Searching...
No Matches
dbxUpload.class.php
Go to the documentation of this file.
1<?php
2// +------------------------------------------------------------------------+
3// | class.upload.php |
4// +------------------------------------------------------------------------+
5// | Copyright (c) Colin Verot 2003-2019. All rights reserved. |
6// | Email colin@verot.net |
7// | Web http://www.verot.net |
8// +------------------------------------------------------------------------+
9// | This program is free software; you can redistribute it and/or modify |
10// | it under the terms of the GNU General Public License version 2 as |
11// | published by the Free Software Foundation. |
12// | |
13// | This program is distributed in the hope that it will be useful, |
14// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16// | GNU General Public License for more details. |
17// | |
18// | You should have received a copy of the GNU General Public License |
19// | along with this program; if not, write to the |
20// | Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
21// | Boston, MA 02111-1307 USA |
22// | |
23// | Please give credit on sites that use class.upload and submit changes |
24// | of the script so other people can use them as well. |
25// | This script is free to use, don't abuse. |
26// +------------------------------------------------------------------------+
27
28// namespace Verot\Upload; #dbXapp use it as system class
29
30if (!defined('IMG_WEBP')) define('IMG_WEBP', 32);
31
39class dbxUpload {
40
41
48
55
62
69
76
83
90
97
104
111
118
125
132
139
147
155
163
170
177
185
193
201
208
216
225
239
248
255
261 var $log;
262
263
264 // overiddable processing variables
265
266
273
280
287
294
302
313
323
340
351
365
379
392
402
418
428
438
448
457
469
476
487
499
509
519
528
543
559
571
580
589
601
613
622
631
641
651
660
671
681
691
700
711
723
733
743
759
769
779
789
803
819
827
839
851
863
875
887
901
915
925
935
947
959
973
990
1004
1030
1044
1056
1068
1080
1092
1105
1119
1134
1155
1168
1181
1195
1209
1223
1239
1255
1268
1282
1297
1307
1319
1331
1361
1373
1387
1400
1413
1433
1446
1460
1479
1497
1520
1534
1548
1566
1579
1592
1610
1628
1635
1647
1664
1674
1683
1691 function init() {
1692
1693 // overiddable variables
1694 $this->file_new_name_body = null; // replace the name body
1695 $this->file_name_body_add = null; // append to the name body
1696 $this->file_name_body_pre = null; // prepend to the name body
1697 $this->file_new_name_ext = null; // replace the file extension
1698 $this->file_safe_name = true; // format safely the filename
1699 $this->file_force_extension = true; // forces extension if there isn't one
1700 $this->file_overwrite = false; // allows overwritting if the file already exists
1701 $this->file_auto_rename = true; // auto-rename if the file already exists
1702 $this->dir_auto_create = true; // auto-creates directory if missing
1703 $this->dir_auto_chmod = true; // auto-chmod directory if not writeable
1704 $this->dir_chmod = 0755; // default chmod to use
1705
1706 $this->no_script = true; // turns scripts into test files
1707 $this->mime_check = true; // checks the mime type against the allowed list
1708
1709 // these are the different MIME detection methods. if one of these method doesn't work on your
1710 // system, you can deactivate it here; just set it to false
1711 $this->mime_fileinfo = true; // MIME detection with Fileinfo PECL extension
1712 $this->mime_file = true; // MIME detection with UNIX file() command
1713 $this->mime_magic = true; // MIME detection with mime_magic (mime_content_type())
1714 $this->mime_getimagesize = true; // MIME detection with getimagesize()
1715
1716 // get the default max size from php.ini
1717 $this->file_max_size_raw = trim(ini_get('upload_max_filesize'));
1718 $this->file_max_size = $this->getsize($this->file_max_size_raw);
1719
1720 $this->image_resize = false; // resize the image
1721 $this->image_convert = ''; // convert. values :''; 'png'; 'jpeg'; 'gif'; 'bmp'; 'webp'
1722
1723 $this->image_x = 150;
1724 $this->image_y = 150;
1725 $this->image_ratio = false; // keeps aspect ratio within x and y dimensions
1726 $this->image_ratio_crop = false; // keeps aspect ratio within x and y dimensions, filling the space
1727 $this->image_ratio_fill = false; // keeps aspect ratio within x and y dimensions, fitting the image in the space
1728 $this->image_ratio_pixels = false; // keeps aspect ratio, calculating x and y to reach the number of pixels
1729 $this->image_ratio_x = false; // calculate the $image_x if true
1730 $this->image_ratio_y = false; // calculate the $image_y if true
1731 $this->image_ratio_no_zoom_in = false;
1732 $this->image_ratio_no_zoom_out = false;
1733 $this->image_no_enlarging = false;
1734 $this->image_no_shrinking = false;
1735
1736 $this->png_compression = null;
1737 $this->webp_quality = 85;
1738 $this->jpeg_quality = 85;
1739 $this->jpeg_size = null;
1740 $this->image_interlace = false;
1741 $this->image_is_transparent = false;
1742 $this->image_transparent_color = null;
1743 $this->image_background_color = null;
1744 $this->image_default_color = '#ffffff';
1745 $this->image_is_palette = false;
1746
1747 $this->image_max_width = null;
1748 $this->image_max_height = null;
1749 $this->image_max_pixels = null;
1750 $this->image_max_ratio = null;
1751 $this->image_min_width = null;
1752 $this->image_min_height = null;
1753 $this->image_min_pixels = null;
1754 $this->image_min_ratio = null;
1755
1756 $this->image_brightness = null;
1757 $this->image_contrast = null;
1758 $this->image_opacity = null;
1759 $this->image_threshold = null;
1760 $this->image_tint_color = null;
1761 $this->image_overlay_color = null;
1762 $this->image_overlay_opacity = null;
1763 $this->image_negative = false;
1764 $this->image_greyscale = false;
1765 $this->image_pixelate = null;
1766 $this->image_unsharp = false;
1767 $this->image_unsharp_amount = 80;
1768 $this->image_unsharp_radius = 0.5;
1769 $this->image_unsharp_threshold = 1;
1770
1771 $this->image_text = null;
1772 $this->image_text_direction = null;
1773 $this->image_text_color = '#FFFFFF';
1774 $this->image_text_opacity = 100;
1775 $this->image_text_background = null;
1776 $this->image_text_background_opacity = 100;
1777 $this->image_text_font = 5;
1778 $this->image_text_size = 16;
1779 $this->image_text_angle = null;
1780 $this->image_text_x = null;
1781 $this->image_text_y = null;
1782 $this->image_text_position = null;
1783 $this->image_text_padding = 0;
1784 $this->image_text_padding_x = null;
1785 $this->image_text_padding_y = null;
1786 $this->image_text_alignment = 'C';
1787 $this->image_text_line_spacing = 0;
1788
1789 $this->image_reflection_height = null;
1790 $this->image_reflection_space = 2;
1791 $this->image_reflection_opacity = 60;
1792
1793 $this->image_watermark = null;
1794 $this->image_watermark_x = null;
1795 $this->image_watermark_y = null;
1796 $this->image_watermark_position = null;
1797 $this->image_watermark_no_zoom_in = true;
1798 $this->image_watermark_no_zoom_out = false;
1799
1800 $this->image_flip = null;
1801 $this->image_auto_rotate = true;
1802 $this->image_rotate = null;
1803 $this->image_crop = null;
1804 $this->image_precrop = null;
1805
1806 $this->image_bevel = null;
1807 $this->image_bevel_color1 = '#FFFFFF';
1808 $this->image_bevel_color2 = '#000000';
1809 $this->image_border = null;
1810 $this->image_border_color = '#FFFFFF';
1811 $this->image_border_opacity = 100;
1812 $this->image_border_transparent = null;
1813 $this->image_frame = null;
1814 $this->image_frame_colors = '#FFFFFF #999999 #666666 #000000';
1815 $this->image_frame_opacity = 100;
1816
1817 $this->dangerous = array(
1818 'php',
1819 'php7',
1820 'php6',
1821 'php5',
1822 'php4',
1823 'php3',
1824 'phtml',
1825 'pht',
1826 'phpt',
1827 'phtm',
1828 'phps',
1829 'inc',
1830 'pl',
1831 'py',
1832 'cgi',
1833 'asp',
1834 'js',
1835 'sh',
1836 'bat',
1837 'phar',
1838 'wsdl',
1839 'html',
1840 'htm',
1841 );
1842
1843 $this->forbidden = array_merge($this->dangerous, array(
1844 'exe',
1845 'dll',
1846 ));
1847
1848 $this->allowed = array(
1849 'application/arj',
1850 'application/excel',
1851 'application/gnutar',
1852 'application/mspowerpoint',
1853 'application/msword',
1854 'application/octet-stream',
1855 'application/onenote',
1856 'application/pdf',
1857 'application/plain',
1858 'application/postscript',
1859 'application/powerpoint',
1860 'application/rar',
1861 'application/rtf',
1862 'application/vnd.ms-excel',
1863 'application/vnd.ms-excel.addin.macroEnabled.12',
1864 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
1865 'application/vnd.ms-excel.sheet.macroEnabled.12',
1866 'application/vnd.ms-excel.template.macroEnabled.12',
1867 'application/vnd.ms-office',
1868 'application/vnd.ms-officetheme',
1869 'application/vnd.ms-powerpoint',
1870 'application/vnd.ms-powerpoint.addin.macroEnabled.12',
1871 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
1872 'application/vnd.ms-powerpoint.slide.macroEnabled.12',
1873 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',
1874 'application/vnd.ms-powerpoint.template.macroEnabled.12',
1875 'application/vnd.ms-word',
1876 'application/vnd.ms-word.document.macroEnabled.12',
1877 'application/vnd.ms-word.template.macroEnabled.12',
1878 'application/vnd.oasis.opendocument.chart',
1879 'application/vnd.oasis.opendocument.database',
1880 'application/vnd.oasis.opendocument.formula',
1881 'application/vnd.oasis.opendocument.graphics',
1882 'application/vnd.oasis.opendocument.graphics-template',
1883 'application/vnd.oasis.opendocument.image',
1884 'application/vnd.oasis.opendocument.presentation',
1885 'application/vnd.oasis.opendocument.presentation-template',
1886 'application/vnd.oasis.opendocument.spreadsheet',
1887 'application/vnd.oasis.opendocument.spreadsheet-template',
1888 'application/vnd.oasis.opendocument.text',
1889 'application/vnd.oasis.opendocument.text-master',
1890 'application/vnd.oasis.opendocument.text-template',
1891 'application/vnd.oasis.opendocument.text-web',
1892 'application/vnd.openofficeorg.extension',
1893 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
1894 'application/vnd.openxmlformats-officedocument.presentationml.slide',
1895 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
1896 'application/vnd.openxmlformats-officedocument.presentationml.template',
1897 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
1898 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
1899 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
1900 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
1901 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
1902 'application/vocaltec-media-file',
1903 'application/wordperfect',
1904 'application/haansoftxlsx',
1905 'application/x-bittorrent',
1906 'application/x-bzip',
1907 'application/x-bzip2',
1908 'application/x-compressed',
1909 'application/x-excel',
1910 'application/x-gzip',
1911 'application/x-latex',
1912 'application/x-midi',
1913 'application/xml',
1914 'application/x-msexcel',
1915 'application/x-rar',
1916 'application/x-rar-compressed',
1917 'application/x-rtf',
1918 'application/x-shockwave-flash',
1919 'application/x-sit',
1920 'application/x-stuffit',
1921 'application/x-troff-msvideo',
1922 'application/x-zip',
1923 'application/x-zip-compressed',
1924 'application/zip',
1925 'audio/*',
1926 'image/*',
1927 'multipart/x-gzip',
1928 'multipart/x-zip',
1929 'text/plain',
1930 'text/rtf',
1931 'text/richtext',
1932 'text/xml',
1933 'video/*',
1934 'text/csv',
1935 'text/x-c',
1936 'text/x-csv',
1937 'text/comma-separated-values',
1938 'text/x-comma-separated-values',
1939 'application/csv',
1940 'application/x-csv',
1941 );
1942
1943 $this->mime_types = array(
1944 'jpg' => 'image/jpeg',
1945 'jpeg' => 'image/jpeg',
1946 'jpe' => 'image/jpeg',
1947 'gif' => 'image/gif',
1948 'webp' => 'image/webp',
1949 'png' => 'image/png',
1950 'bmp' => 'image/bmp',
1951 'flif' => 'image/flif',
1952 'flv' => 'video/x-flv',
1953 'js' => 'application/x-javascript',
1954 'json' => 'application/json',
1955 'tiff' => 'image/tiff',
1956 'css' => 'text/css',
1957 'xml' => 'application/xml',
1958 'doc' => 'application/msword',
1959 'xls' => 'application/vnd.ms-excel',
1960 'xlt' => 'application/vnd.ms-excel',
1961 'xlm' => 'application/vnd.ms-excel',
1962 'xld' => 'application/vnd.ms-excel',
1963 'xla' => 'application/vnd.ms-excel',
1964 'xlc' => 'application/vnd.ms-excel',
1965 'xlw' => 'application/vnd.ms-excel',
1966 'xll' => 'application/vnd.ms-excel',
1967 'ppt' => 'application/vnd.ms-powerpoint',
1968 'pps' => 'application/vnd.ms-powerpoint',
1969 'rtf' => 'application/rtf',
1970 'pdf' => 'application/pdf',
1971 'html' => 'text/html',
1972 'htm' => 'text/html',
1973 'php' => 'text/html',
1974 'txt' => 'text/plain',
1975 'mpeg' => 'video/mpeg',
1976 'mpg' => 'video/mpeg',
1977 'mpe' => 'video/mpeg',
1978 'mp3' => 'audio/mpeg3',
1979 'mp4' => 'video/mp4',
1980 'wav' => 'audio/wav',
1981 'aiff' => 'audio/aiff',
1982 'aif' => 'audio/aiff',
1983 'avi' => 'video/msvideo',
1984 'wmv' => 'video/x-ms-wmv',
1985 'mov' => 'video/quicktime',
1986 'zip' => 'application/zip',
1987 'tar' => 'application/x-tar',
1988 'swf' => 'application/x-shockwave-flash',
1989 'odt' => 'application/vnd.oasis.opendocument.text',
1990 'ott' => 'application/vnd.oasis.opendocument.text-template',
1991 'oth' => 'application/vnd.oasis.opendocument.text-web',
1992 'odm' => 'application/vnd.oasis.opendocument.text-master',
1993 'odg' => 'application/vnd.oasis.opendocument.graphics',
1994 'otg' => 'application/vnd.oasis.opendocument.graphics-template',
1995 'odp' => 'application/vnd.oasis.opendocument.presentation',
1996 'otp' => 'application/vnd.oasis.opendocument.presentation-template',
1997 'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
1998 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
1999 'odc' => 'application/vnd.oasis.opendocument.chart',
2000 'odf' => 'application/vnd.oasis.opendocument.formula',
2001 'odb' => 'application/vnd.oasis.opendocument.database',
2002 'odi' => 'application/vnd.oasis.opendocument.image',
2003 'oxt' => 'application/vnd.openofficeorg.extension',
2004 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
2005 'docm' => 'application/vnd.ms-word.document.macroEnabled.12',
2006 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
2007 'dotm' => 'application/vnd.ms-word.template.macroEnabled.12',
2008 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
2009 'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12',
2010 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
2011 'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12',
2012 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
2013 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
2014 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
2015 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
2016 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
2017 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',
2018 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
2019 'potm' => 'application/vnd.ms-powerpoint.template.macroEnabled.12',
2020 'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12',
2021 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
2022 'sldm' => 'application/vnd.ms-powerpoint.slide.macroEnabled.12',
2023 'thmx' => 'application/vnd.ms-officetheme',
2024 'onetoc' => 'application/onenote',
2025 'onetoc2' => 'application/onenote',
2026 'onetmp' => 'application/onenote',
2027 'onepkg' => 'application/onenote',
2028 'csv' => 'text/csv',
2029 );
2030
2031
2032 }
2033
2037 function __construct($file='', $lang = 'en_GB') {
2038 if ($file) $this->upload($file, $lang);
2039 }
2040
2065 function upload($file, $lang = 'en_GB') {
2066
2067 $this->version = '10/09/2024';
2068
2069 $this->file_src_name = '';
2070 $this->file_src_name_body = '';
2071 $this->file_src_name_ext = '';
2072 $this->file_src_mime = '';
2073 $this->file_src_size = '';
2074 $this->file_src_error = '';
2075 $this->file_src_pathname = '';
2076 $this->file_src_temp = '';
2077
2078 $this->file_dst_path = '';
2079 $this->file_dst_name = '';
2080 $this->file_dst_name_body = '';
2081 $this->file_dst_name_ext = '';
2082 $this->file_dst_pathname = '';
2083
2084 $this->image_src_x = null;
2085 $this->image_src_y = null;
2086 $this->image_src_bits = null;
2087 $this->image_src_type = null;
2088 $this->image_src_pixels = null;
2089 $this->image_dst_x = 0;
2090 $this->image_dst_y = 0;
2091 $this->image_dst_type = '';
2092
2093 $this->uploaded = true;
2094 $this->no_upload_check = false;
2095 $this->processed = false;
2096 $this->error = '';
2097 $this->log = '';
2098 $this->allowed = array();
2099 $this->forbidden = array();
2100 $this->file_is_image = false;
2101 $this->init();
2102 $info = null;
2103 $mime_from_browser = null;
2104
2105 // sets default language
2106 $this->translation = array();
2107 $this->translation['file_error'] = 'File error. Please try again.';
2108 $this->translation['local_file_missing'] = 'Local file doesn\'t exist.';
2109 $this->translation['local_file_not_readable'] = 'Local file is not readable.';
2110 $this->translation['uploaded_too_big_ini'] = 'File upload error (the uploaded file exceeds the upload_max_filesize directive in php.ini).';
2111 $this->translation['uploaded_too_big_html'] = 'File upload error (the uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the html form).';
2112 $this->translation['uploaded_partial'] = 'File upload error (the uploaded file was only partially uploaded).';
2113 $this->translation['uploaded_missing'] = 'File upload error (no file was uploaded).';
2114 $this->translation['uploaded_no_tmp_dir'] = 'File upload error (missing a temporary folder).';
2115 $this->translation['uploaded_cant_write'] = 'File upload error (failed to write file to disk).';
2116 $this->translation['uploaded_err_extension'] = 'File upload error (file upload stopped by extension).';
2117 $this->translation['uploaded_unknown'] = 'File upload error (unknown error code).';
2118 $this->translation['try_again'] = 'File upload error. Please try again.';
2119 $this->translation['file_too_big'] = 'File too big.';
2120 $this->translation['no_mime'] = 'MIME type can\'t be detected.';
2121 $this->translation['incorrect_file'] = 'Incorrect type of file.';
2122 $this->translation['image_too_wide'] = 'Image too wide.';
2123 $this->translation['image_too_narrow'] = 'Image too narrow.';
2124 $this->translation['image_too_high'] = 'Image too tall.';
2125 $this->translation['image_too_short'] = 'Image too short.';
2126 $this->translation['ratio_too_high'] = 'Image ratio too high (image too wide).';
2127 $this->translation['ratio_too_low'] = 'Image ratio too low (image too high).';
2128 $this->translation['too_many_pixels'] = 'Image has too many pixels.';
2129 $this->translation['not_enough_pixels'] = 'Image has not enough pixels.';
2130 $this->translation['file_not_uploaded'] = 'File not uploaded. Can\'t carry on a process.';
2131 $this->translation['already_exists'] = '%s already exists. Please change the file name.';
2132 $this->translation['temp_file_missing'] = 'No correct temp source file. Can\'t carry on a process.';
2133 $this->translation['source_missing'] = 'No correct uploaded source file. Can\'t carry on a process.';
2134 $this->translation['destination_dir'] = 'Destination directory can\'t be created. Can\'t carry on a process.';
2135 $this->translation['destination_dir_missing'] = 'Destination directory doesn\'t exist. Can\'t carry on a process.';
2136 $this->translation['destination_path_not_dir'] = 'Destination path is not a directory. Can\'t carry on a process.';
2137 $this->translation['destination_dir_write'] = 'Destination directory can\'t be made writeable. Can\'t carry on a process.';
2138 $this->translation['destination_path_write'] = 'Destination path is not a writeable. Can\'t carry on a process.';
2139 $this->translation['temp_file'] = 'Can\'t create the temporary file. Can\'t carry on a process.';
2140 $this->translation['source_not_readable'] = 'Source file is not readable. Can\'t carry on a process.';
2141 $this->translation['no_create_support'] = 'No create from %s support.';
2142 $this->translation['create_error'] = 'Error in creating %s image from source.';
2143 $this->translation['source_invalid'] = 'Can\'t read image source. Not an image?.';
2144 $this->translation['gd_missing'] = 'GD doesn\'t seem to be present.';
2145 $this->translation['watermark_no_create_support'] = 'No create from %s support, can\'t read watermark.';
2146 $this->translation['watermark_create_error'] = 'No %s read support, can\'t create watermark.';
2147 $this->translation['watermark_invalid'] = 'Unknown image format, can\'t read watermark.';
2148 $this->translation['file_create'] = 'No %s create support.';
2149 $this->translation['no_conversion_type'] = 'No conversion type defined.';
2150 $this->translation['copy_failed'] = 'Error copying file on the server. copy() failed.';
2151 $this->translation['reading_failed'] = 'Error reading the file.';
2152
2153 // determines the language
2154 $this->lang = $lang;
2155 if ($this->lang != 'en_GB' && file_exists(dirname(__FILE__).'/lang') && file_exists(dirname(__FILE__).'/lang/class.upload.' . $lang . '.php')) {
2156 $translation = null;
2157 include(dirname(__FILE__).'/lang/class.upload.' . $lang . '.php');
2158 if (is_array($translation)) {
2159 $this->translation = array_merge($this->translation, $translation);
2160 } else {
2161 $this->lang = 'en_GB';
2162 }
2163 }
2164
2165
2166 // determines the supported MIME types, and matching image format
2167 $this->image_supported = array();
2168 if ($this->gdversion()) {
2169 if (imagetypes() & IMG_GIF) {
2170 $this->image_supported['image/gif'] = 'gif';
2171 }
2172 if (imagetypes() & IMG_JPG) {
2173 $this->image_supported['image/jpg'] = 'jpg';
2174 $this->image_supported['image/jpeg'] = 'jpg';
2175 $this->image_supported['image/pjpeg'] = 'jpg';
2176 }
2177 if (imagetypes() & IMG_PNG) {
2178 $this->image_supported['image/png'] = 'png';
2179 $this->image_supported['image/x-png'] = 'png';
2180 }
2181 if (imagetypes() & IMG_WEBP) {
2182 $this->image_supported['image/webp'] = 'webp';
2183 $this->image_supported['image/x-webp'] = 'webp';
2184 }
2185 if (imagetypes() & IMG_WBMP) {
2186 $this->image_supported['image/bmp'] = 'bmp';
2187 $this->image_supported['image/x-ms-bmp'] = 'bmp';
2188 $this->image_supported['image/x-windows-bmp'] = 'bmp';
2189 }
2190 }
2191
2192 // display some system information
2193 if (empty($this->log)) {
2194 $this->log .= '<b>system information</b><br />';
2195 if ($this->function_enabled('ini_get_all')) {
2196 $inis = ini_get_all();
2197 $open_basedir = (array_key_exists('open_basedir', $inis) && array_key_exists('local_value', $inis['open_basedir']) && !empty($inis['open_basedir']['local_value'])) ? $inis['open_basedir']['local_value'] : false;
2198 } else {
2199 $open_basedir = false;
2200 }
2201 $gd = $this->gdversion() ? $this->gdversion(true) : 'GD not present';
2202 $supported = trim((in_array('png', $this->image_supported) ? 'png' : '') . ' ' .
2203 (in_array('webp', $this->image_supported) ? 'webp' : '') . ' ' .
2204 (in_array('jpg', $this->image_supported) ? 'jpg' : '') . ' ' .
2205 (in_array('gif', $this->image_supported) ? 'gif' : '') . ' ' .
2206 (in_array('bmp', $this->image_supported) ? 'bmp' : ''));
2207 $this->log .= '-&nbsp;class version : ' . $this->version . '<br />';
2208 $this->log .= '-&nbsp;operating system : ' . PHP_OS . '<br />';
2209 $this->log .= '-&nbsp;PHP version : ' . PHP_VERSION . '<br />';
2210 $this->log .= '-&nbsp;GD version : ' . $gd . '<br />';
2211 $this->log .= '-&nbsp;supported image types : ' . (!empty($supported) ? $supported : 'none') . '<br />';
2212 $this->log .= '-&nbsp;open_basedir : ' . (!empty($open_basedir) ? $open_basedir : 'no restriction') . '<br />';
2213 $this->log .= '-&nbsp;upload_max_filesize : ' . $this->file_max_size_raw . ' (' . $this->file_max_size . ' bytes)<br />';
2214 $this->log .= '-&nbsp;language : ' . $this->lang . '<br />';
2215 }
2216
2217 if (!$file) {
2218 $this->uploaded = false;
2219 $this->error = $this->translate('file_error');
2220 }
2221
2222 // check if we sent a local filename or a PHP stream rather than a $_FILE element
2223 if (!is_array($file)) {
2224 if (empty($file)) {
2225 $this->uploaded = false;
2226 $this->error = $this->translate('file_error');
2227 } else {
2228 $file = (string) $file;
2229 if (substr($file, 0, 4) == 'php:' || substr($file, 0, 5) == 'data:' || substr($file, 0, 7) == 'base64:') {
2230 $data = null;
2231
2232 // this is a PHP stream, i.e.not uploaded
2233 if (substr($file, 0, 4) == 'php:') {
2234 $file = preg_replace('/^php:(.*)/i', '$1', $file);
2235 if (!$file) $file = $_SERVER['HTTP_X_FILE_NAME'];
2236 if (!$file) $file = 'unknown';
2237 $data = file_get_contents('php://input');
2238 $this->log .= '<b>source is a PHP stream ' . $file . ' of length ' . strlen($data) . '</b><br />';
2239
2240 // this is the raw file data, base64-encoded, i.e.not uploaded
2241 } else if (substr($file, 0, 7) == 'base64:') {
2242 $data = base64_decode(preg_replace('/^base64:(.*)/i', '$1', $file));
2243 $file = 'base64';
2244 $this->log .= '<b>source is a base64 string of length ' . strlen($data) . '</b><br />';
2245
2246 // this is the raw file data, base64-encoded, i.e.not uploaded
2247 } else if (substr($file, 0, 5) == 'data:' && strpos($file, 'base64,') !== false) {
2248 $data = base64_decode(preg_replace('/^data:.*base64,(.*)/i', '$1', $file));
2249 $file = 'base64';
2250 $this->log .= '<b>source is a base64 data string of length ' . strlen($data) . '</b><br />';
2251
2252 // this is the raw file data, i.e.not uploaded
2253 } else if (substr($file, 0, 5) == 'data:') {
2254 $data = preg_replace('/^data:(.*)/i', '$1', $file);
2255 $file = 'data';
2256 $this->log .= '<b>source is a data string of length ' . strlen($data) . '</b><br />';
2257 }
2258
2259 if (!$data) {
2260 $this->log .= '- source is empty!<br />';
2261 $this->uploaded = false;
2262 $this->error = $this->translate('source_invalid');
2263 }
2264
2265 $this->no_upload_check = true;
2266
2267 if ($this->uploaded) {
2268 $this->log .= '- requires a temp file ... ';
2269 $hash = $this->temp_dir() . md5($file . rand(1, 1000));
2270 if ($data && file_put_contents($hash, $data)) {
2271 $this->file_src_pathname = $hash;
2272 $this->log .= ' file created<br />';
2273 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;temp file is: ' . $this->file_src_pathname . '<br />';
2274 } else {
2275 $this->log .= ' failed<br />';
2276 $this->uploaded = false;
2277 $this->error = $this->translate('temp_file');
2278 }
2279 }
2280
2281 if ($this->uploaded) {
2282 $this->file_src_name = $file;
2283 $this->log .= '- local file OK<br />';
2284 preg_match('/\.([^\.]*$)/', $this->file_src_name, $extension);
2285 if (is_array($extension) && sizeof($extension) > 0) {
2286 $this->file_src_name_ext = strtolower($extension[1]);
2287 $this->file_src_name_body = substr($this->file_src_name, 0, ((strlen($this->file_src_name) - strlen($this->file_src_name_ext)))-1);
2288 } else {
2289 $this->file_src_name_ext = '';
2290 $this->file_src_name_body = $this->file_src_name;
2291 }
2292 $this->file_src_size = (file_exists($this->file_src_pathname) ? filesize($this->file_src_pathname) : 0);
2293 }
2294 $this->file_src_error = 0;
2295
2296 } else {
2297 // this is a local filename, i.e.not uploaded
2298 $this->log .= '<b>source is a local file ' . $file . '</b><br />';
2299 $this->no_upload_check = true;
2300
2301 if ($this->uploaded && !file_exists($file)) {
2302 $this->uploaded = false;
2303 $this->error = $this->translate('local_file_missing');
2304 }
2305
2306 if ($this->uploaded && !is_readable($file)) {
2307 $this->uploaded = false;
2308 $this->error = $this->translate('local_file_not_readable');
2309 }
2310
2311 if ($this->uploaded) {
2312 $this->file_src_pathname = $file;
2313 $this->file_src_name = basename($file);
2314 $this->log .= '- local file OK<br />';
2315 preg_match('/\.([^\.]*$)/', $this->file_src_name, $extension);
2316 if (is_array($extension) && sizeof($extension) > 0) {
2317 $this->file_src_name_ext = strtolower($extension[1]);
2318 $this->file_src_name_body = substr($this->file_src_name, 0, ((strlen($this->file_src_name) - strlen($this->file_src_name_ext)))-1);
2319 } else {
2320 $this->file_src_name_ext = '';
2321 $this->file_src_name_body = $this->file_src_name;
2322 }
2323 $this->file_src_size = (file_exists($this->file_src_pathname) ? filesize($this->file_src_pathname) : 0);
2324 }
2325 $this->file_src_error = 0;
2326 }
2327 }
2328 } else {
2329 // this is an element from $_FILE, i.e. an uploaded file
2330 $this->log .= '<b>source is an uploaded file</b><br />';
2331 if ($this->uploaded) {
2332 $this->file_src_error = trim((int) $file['error']);
2333 switch($this->file_src_error) {
2334 case UPLOAD_ERR_OK:
2335 // all is OK
2336 $this->log .= '- upload OK<br />';
2337 break;
2338 case UPLOAD_ERR_INI_SIZE:
2339 $this->uploaded = false;
2340 $this->error = $this->translate('uploaded_too_big_ini');
2341 break;
2342 case UPLOAD_ERR_FORM_SIZE:
2343 $this->uploaded = false;
2344 $this->error = $this->translate('uploaded_too_big_html');
2345 break;
2346 case UPLOAD_ERR_PARTIAL:
2347 $this->uploaded = false;
2348 $this->error = $this->translate('uploaded_partial');
2349 break;
2350 case UPLOAD_ERR_NO_FILE:
2351 $this->uploaded = false;
2352 $this->error = $this->translate('uploaded_missing');
2353 break;
2354 case @UPLOAD_ERR_NO_TMP_DIR:
2355 $this->uploaded = false;
2356 $this->error = $this->translate('uploaded_no_tmp_dir');
2357 break;
2358 case @UPLOAD_ERR_CANT_WRITE:
2359 $this->uploaded = false;
2360 $this->error = $this->translate('uploaded_cant_write');
2361 break;
2362 case @UPLOAD_ERR_EXTENSION:
2363 $this->uploaded = false;
2364 $this->error = $this->translate('uploaded_err_extension');
2365 break;
2366 default:
2367 $this->uploaded = false;
2368 $this->error = $this->translate('uploaded_unknown') . ' ('.$this->file_src_error.')';
2369 }
2370 }
2371
2372 if ($this->uploaded) {
2373 $this->file_src_pathname = (string) $file['tmp_name'];
2374 $this->file_src_name = (string) $file['name'];
2375 if ($this->file_src_name == '') {
2376 $this->uploaded = false;
2377 $this->error = $this->translate('try_again');
2378 }
2379 }
2380
2381 if ($this->uploaded) {
2382 $this->log .= '- file name OK<br />';
2383 preg_match('/\.([^\.]*$)/', $this->file_src_name, $extension);
2384 if (is_array($extension) && sizeof($extension) > 0) {
2385 $this->file_src_name_ext = strtolower($extension[1]);
2386 $this->file_src_name_body = substr($this->file_src_name, 0, ((strlen($this->file_src_name) - strlen($this->file_src_name_ext)))-1);
2387 } else {
2388 $this->file_src_name_ext = '';
2389 $this->file_src_name_body = $this->file_src_name;
2390 }
2391 $this->file_src_size = (int) $file['size'];
2392 $mime_from_browser = (string) $file['type'];
2393 }
2394 }
2395
2396 if ($this->uploaded) {
2397 $this->log .= '<b>determining MIME type</b><br />';
2398 $this->file_src_mime = null;
2399
2400 // checks MIME type with Fileinfo PECL extension
2401 if (!$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime) || strpos($this->file_src_mime, '/') === false) {
2402 if ($this->mime_fileinfo) {
2403 $this->log .= '- checking MIME type with Fileinfo PECL extension<br />';
2404 if ($this->function_enabled('finfo_open')) {
2405 $path = null;
2406 if ($this->mime_fileinfo !== '') {
2407 if ($this->mime_fileinfo === true) {
2408 if (getenv('MAGIC') === false) {
2409 if (substr(PHP_OS, 0, 3) == 'WIN') {
2410 $path = realpath(ini_get('extension_dir') . '/../') . '/extras/magic';
2411 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MAGIC path defaults to ' . $path . '<br />';
2412 }
2413 } else {
2414 $path = getenv('MAGIC');
2415 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MAGIC path is set to ' . $path . ' from MAGIC variable<br />';
2416 }
2417 } else {
2418 $path = $this->mime_fileinfo;
2419 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MAGIC path is set to ' . $path . '<br />';
2420 }
2421 }
2422 if ($path && file_exists($path)) {
2423 $f = @finfo_open(FILEINFO_MIME, $path);
2424 } else {
2425 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MAGIC path will not be used<br />';
2426 $f = @finfo_open(FILEINFO_MIME);
2427 }
2428 if ($f) {
2429 $mime = finfo_file($f, realpath($this->file_src_pathname));
2430 finfo_close($f);
2431 $this->file_src_mime = $mime;
2432 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MIME type detected as ' . $this->file_src_mime . ' by Fileinfo PECL extension<br />';
2433 if (preg_match("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", $this->file_src_mime)) {
2434 $this->file_src_mime = preg_replace("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", '$1/$2', $this->file_src_mime);
2435 $this->log .= '-&nbsp;MIME validated as ' . $this->file_src_mime . '<br />';
2436 } else {
2437 $this->file_src_mime = null;
2438 }
2439 } else {
2440 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;Fileinfo PECL extension failed (finfo_open)<br />';
2441 }
2442 } elseif (@class_exists('finfo', false)) {
2443 $f = new finfo( FILEINFO_MIME );
2444 if ($f) {
2445 $this->file_src_mime = $f->file(realpath($this->file_src_pathname));
2446 $this->log .= '- MIME type detected as ' . $this->file_src_mime . ' by Fileinfo PECL extension<br />';
2447 if (preg_match("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", $this->file_src_mime)) {
2448 $this->file_src_mime = preg_replace("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", '$1/$2', $this->file_src_mime);
2449 $this->log .= '-&nbsp;MIME validated as ' . $this->file_src_mime . '<br />';
2450 } else {
2451 $this->file_src_mime = null;
2452 }
2453 } else {
2454 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;Fileinfo PECL extension failed (finfo)<br />';
2455 }
2456 } else {
2457 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;Fileinfo PECL extension not available<br />';
2458 }
2459 } else {
2460 $this->log .= '- Fileinfo PECL extension deactivated<br />';
2461 }
2462 }
2463
2464 // checks MIME type with shell if unix access is authorized
2465 if (!$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime) || strpos($this->file_src_mime, '/') === false) {
2466 if ($this->mime_file) {
2467 $this->log .= '- checking MIME type with UNIX file() command<br />';
2468 if (substr(PHP_OS, 0, 3) != 'WIN') {
2469 if ($this->function_enabled('exec') && $this->function_enabled('escapeshellarg')) {
2470 if (strlen($mime = @exec("file -bi ".escapeshellarg($this->file_src_pathname))) != 0) {
2471 $this->file_src_mime = trim($mime);
2472 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MIME type detected as ' . $this->file_src_mime . ' by UNIX file() command<br />';
2473 if (preg_match("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", $this->file_src_mime)) {
2474 $this->file_src_mime = preg_replace("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", '$1/$2', $this->file_src_mime);
2475 $this->log .= '-&nbsp;MIME validated as ' . $this->file_src_mime . '<br />';
2476 } else {
2477 $this->file_src_mime = null;
2478 }
2479 } else {
2480 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;UNIX file() command failed<br />';
2481 }
2482 } else {
2483 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;PHP exec() function is disabled<br />';
2484 }
2485 } else {
2486 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;UNIX file() command not availabled<br />';
2487 }
2488 } else {
2489 $this->log .= '- UNIX file() command is deactivated<br />';
2490 }
2491 }
2492
2493 // checks MIME type with mime_magic
2494 if (!$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime) || strpos($this->file_src_mime, '/') === false) {
2495 if ($this->mime_magic) {
2496 $this->log .= '- checking MIME type with mime.magic file (mime_content_type())<br />';
2497 if ($this->function_enabled('mime_content_type')) {
2498 $this->file_src_mime = mime_content_type($this->file_src_pathname);
2499 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MIME type detected as ' . $this->file_src_mime . ' by mime_content_type()<br />';
2500 if (preg_match("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", $this->file_src_mime)) {
2501 $this->file_src_mime = preg_replace("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", '$1/$2', $this->file_src_mime);
2502 $this->log .= '-&nbsp;MIME validated as ' . $this->file_src_mime . '<br />';
2503 } else {
2504 $this->file_src_mime = null;
2505 }
2506 } else {
2507 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;mime_content_type() is not available<br />';
2508 }
2509 } else {
2510 $this->log .= '- mime.magic file (mime_content_type()) is deactivated<br />';
2511 }
2512 }
2513
2514 // checks MIME type with getimagesize()
2515 if (!$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime) || strpos($this->file_src_mime, '/') === false) {
2516 if ($this->mime_getimagesize) {
2517 $this->log .= '- checking MIME type with getimagesize()<br />';
2518 $info = getimagesize($this->file_src_pathname);
2519 if (is_array($info) && array_key_exists('mime', $info)) {
2520 $this->file_src_mime = trim($info['mime']);
2521 if (empty($this->file_src_mime)) {
2522 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MIME empty, guessing from type<br />';
2523 $mime = (is_array($info) && array_key_exists(2, $info) ? $info[2] : null); // 1 = GIF, 2 = JPG, 3 = PNG
2524 $this->file_src_mime = ($mime==IMAGETYPE_GIF ? 'image/gif' :
2525 ($mime==IMAGETYPE_JPEG ? 'image/jpeg' :
2526 ($mime==IMAGETYPE_PNG ? 'image/png' :
2527 ($mime==IMAGETYPE_WEBP ? 'image/webp' :
2528 ($mime==IMAGETYPE_BMP ? 'image/bmp' : null)))));
2529 }
2530 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;MIME type detected as ' . $this->file_src_mime . ' by PHP getimagesize() function<br />';
2531 if (preg_match("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", $this->file_src_mime)) {
2532 $this->file_src_mime = preg_replace("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", '$1/$2', $this->file_src_mime);
2533 $this->log .= '-&nbsp;MIME validated as ' . $this->file_src_mime . '<br />';
2534 } else {
2535 $this->file_src_mime = null;
2536 }
2537 } else {
2538 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;getimagesize() failed<br />';
2539 }
2540 } else {
2541 $this->log .= '- getimagesize() is deactivated<br />';
2542 }
2543 }
2544
2545 // default to MIME from browser (or Flash)
2546 if (!empty($mime_from_browser) && !$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime)) {
2547 $this->file_src_mime =$mime_from_browser;
2548 $this->log .= '- MIME type detected as ' . $this->file_src_mime . ' by browser<br />';
2549 if (preg_match("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", $this->file_src_mime)) {
2550 $this->file_src_mime = preg_replace("/^([\.\w-]+)\/([\.\w-]+)(.*)$/i", '$1/$2', $this->file_src_mime);
2551 $this->log .= '-&nbsp;MIME validated as ' . $this->file_src_mime . '<br />';
2552 } else {
2553 $this->file_src_mime = null;
2554 }
2555 }
2556
2557 // we need to work some magic if we upload via Flash
2558 if ($this->file_src_mime == 'application/octet-stream' || !$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime) || strpos($this->file_src_mime, '/') === false) {
2559 if ($this->file_src_mime == 'application/octet-stream') $this->log .= '- Flash may be rewriting MIME as application/octet-stream<br />';
2560 $this->log .= '- try to guess MIME type from file extension (' . $this->file_src_name_ext . '): ';
2561 if (array_key_exists($this->file_src_name_ext, $this->mime_types)) $this->file_src_mime = $this->mime_types[$this->file_src_name_ext];
2562 if ($this->file_src_mime == 'application/octet-stream') {
2563 $this->log .= 'doesn\'t look like anything known<br />';
2564 } else {
2565 $this->log .= 'MIME type set to ' . $this->file_src_mime . '<br />';
2566 }
2567 }
2568
2569 if (!$this->file_src_mime || !is_string($this->file_src_mime) || empty($this->file_src_mime) || strpos($this->file_src_mime, '/') === false) {
2570 $this->log .= '- MIME type couldn\'t be detected! (' . (string) $this->file_src_mime . ')<br />';
2571 }
2572
2573 // determine whether the file is an image
2574 if ($this->file_src_mime && is_string($this->file_src_mime) && !empty($this->file_src_mime)) {
2575 if (array_key_exists($this->file_src_mime, $this->image_supported)) {
2576 $this->file_is_image = true;
2577 $this->image_src_type = $this->image_supported[$this->file_src_mime];
2578 $this->log .= '- file is an image, and its type is supported by GD<br />';
2579 } else if (strpos($this->file_src_mime, 'image/') !== FALSE && sizeof($this->image_supported) == 0) {
2580 $this->log .= '- file may be an image, but its type is not supported; is GD installed ?<br />';
2581 }
2582 }
2583
2584 // if the file is an image, we gather some useful data
2585 if ($this->file_is_image) {
2586 if ($h = fopen($this->file_src_pathname, 'r')) {
2587 fclose($h);
2588 $info = getimagesize($this->file_src_pathname);
2589 if (is_array($info)) {
2590 $this->image_src_x = $info[0];
2591 $this->image_src_y = $info[1];
2592 $this->image_dst_x = $this->image_src_x;
2593 $this->image_dst_y = $this->image_src_y;
2594 $this->image_src_pixels = $this->image_src_x * $this->image_src_y;
2595 $this->image_src_bits = array_key_exists('bits', $info) ? $info['bits'] : null;
2596 } else {
2597 $this->file_is_image = false;
2598 $this->uploaded = false;
2599 $this->log .= '- can\'t retrieve image information, image may have been tampered with<br />';
2600 $this->error = $this->translate('source_invalid');
2601 }
2602 } else {
2603 $this->log .= '- can\'t read source file directly. open_basedir restriction in place?<br />';
2604 }
2605 }
2606
2607 $this->log .= '<b>source variables</b><br />';
2608 $this->log .= '- you can use all these before calling process()<br />';
2609 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_src_name : ' . $this->file_src_name . '<br />';
2610 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_src_name_body : ' . $this->file_src_name_body . '<br />';
2611 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_src_name_ext : ' . $this->file_src_name_ext . '<br />';
2612 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_src_pathname : ' . $this->file_src_pathname . '<br />';
2613 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_src_mime : ' . $this->file_src_mime . '<br />';
2614 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_src_size : ' . $this->file_src_size . ' (max= ' . $this->file_max_size . ')<br />';
2615 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_src_error : ' . $this->file_src_error . '<br />';
2616
2617 if ($this->file_is_image) {
2618 $this->log .= '- source file is an image<br />';
2619 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;image_src_x : ' . $this->image_src_x . '<br />';
2620 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;image_src_y : ' . $this->image_src_y . '<br />';
2621 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;image_src_pixels : ' . $this->image_src_pixels . '<br />';
2622 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;image_src_type : ' . $this->image_src_type . '<br />';
2623 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;image_src_bits : ' . $this->image_src_bits . '<br />';
2624 }
2625 }
2626
2627 }
2628
2636 function gdversion($full = false) {
2637 static $gd_version = null;
2638 static $gd_full_version = null;
2639 if ($gd_version === null) {
2640 if ($this->function_enabled('gd_info')) {
2641 $gd = gd_info();
2642 $gd = $gd["GD Version"];
2643 $regex = "/([\d\.]+)/i";
2644 } else {
2645 ob_start();
2646 phpinfo(8);
2647 $gd = ob_get_contents();
2648 ob_end_clean();
2649 $regex = "/\bgd\s+version\b[^\d\n\r]+?([\d\.]+)/i";
2650 }
2651 if (preg_match($regex, $gd, $m)) {
2652 $gd_full_version = (string) $m[1];
2653 $gd_version = (float) $m[1];
2654 } else {
2655 $gd_full_version = 'none';
2656 $gd_version = 0;
2657 }
2658 }
2659 if ($full) {
2660 return $gd_full_version;
2661 } else {
2662 return $gd_version;
2663 }
2664 }
2665
2673 function function_enabled($func) {
2674 // cache the list of disabled functions
2675 static $disabled = null;
2676 if ($disabled === null) $disabled = array_map('trim', array_map('strtolower', explode(',', ini_get('disable_functions'))));
2677 // cache the list of functions blacklisted by suhosin
2678 static $blacklist = null;
2679 if ($blacklist === null) $blacklist = extension_loaded('suhosin') ? array_map('trim', array_map('strtolower', explode(',', ini_get(' suhosin.executor.func.blacklist')))) : array();
2680 // checks if the function is really enabled
2681 return (function_exists($func) && !in_array($func, $disabled) && !in_array($func, $blacklist));
2682 }
2683
2692 function rmkdir($path, $mode = 0755) {
2693 return is_dir($path) || ( $this->rmkdir(dirname($path), $mode) && $this->_mkdir($path, $mode) );
2694 }
2695
2704 function _mkdir($path, $mode = 0755) {
2705 $old = umask(0);
2706 $res = @mkdir($path, $mode);
2707 umask($old);
2708 return $res;
2709 }
2710
2719 function translate($str, $tokens = array()) {
2720 if (array_key_exists($str, $this->translation)) $str = $this->translation[$str];
2721 if (is_array($tokens) && sizeof($tokens) > 0) $str = vsprintf($str, $tokens);
2722 return $str;
2723 }
2724
2731 function temp_dir() {
2732 $dir = '';
2733 if ($this->function_enabled('sys_get_temp_dir')) $dir = sys_get_temp_dir();
2734 if (!$dir && $tmp=getenv('TMP')) $dir = $tmp;
2735 if (!$dir && $tmp=getenv('TEMP')) $dir = $tmp;
2736 if (!$dir && $tmp=getenv('TMPDIR')) $dir = $tmp;
2737 if (!$dir) {
2738 $tmp = tempnam(__FILE__,'');
2739 if (file_exists($tmp)) {
2740 unlink($tmp);
2741 $dir = dirname($tmp);
2742 }
2743 }
2744 if (!$dir) return '';
2745 $slash = (strtolower(substr(PHP_OS, 0, 3)) === 'win' ? '\\' : '/');
2746 if (substr($dir, -1) != $slash) $dir = $dir . $slash;
2747 return $dir;
2748 }
2749
2757 function sanitize($filename) {
2758 // remove HTML tags
2759 $filename = strip_tags($filename);
2760 // remove non-breaking spaces
2761 $filename = preg_replace("#\x{00a0}#siu", ' ', $filename);
2762 // remove illegal file system characters
2763 $filename = str_replace(array_map('chr', range(0, 31)), '', $filename);
2764 // remove dangerous characters for file names
2765 $chars = array("?", "[", "]", "/", "\\", "=", "<", ">", ":", ";", ",", "'", "\"", "&", "’", "%20",
2766 "+", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}", "%", "+", "^", chr(0));
2767 $filename = str_replace($chars, '-', $filename);
2768 // remove break/tabs/return carriage
2769 $filename = preg_replace('/[\r\n\t -]+/', '-', $filename);
2770 // convert some special letters
2771 $convert = array('Þ' => 'TH', 'þ' => 'th', 'Ð' => 'DH', 'ð' => 'dh', 'ß' => 'ss',
2772 'Œ' => 'OE', 'œ' => 'oe', 'Æ' => 'AE', 'æ' => 'ae', 'µ' => 'u');
2773 $filename = strtr($filename, $convert);
2774 // remove foreign accents by converting to HTML entities, and then remove the code
2775 $filename = html_entity_decode( $filename, ENT_QUOTES, "utf-8" );
2776 $filename = htmlentities($filename, ENT_QUOTES, "utf-8");
2777 $filename = preg_replace("/(&)([a-z])([a-z]+;)/i", '$2', $filename);
2778 // clean up, and remove repetitions
2779 $filename = preg_replace('/_+/', '_', $filename);
2780 $filename = preg_replace(array('/ +/', '/-+/'), '-', $filename);
2781 $filename = preg_replace(array('/-*\.- */', '/\.{2,}/'), '.', $filename);
2782 // cut to 255 characters
2783 $length = 255 - strlen($this->file_dst_name_ext) + 1;
2784 $filename = extension_loaded('mbstring') ? mb_strcut($filename, 0, $length, mb_detect_encoding($filename)) : substr($filename, 0, $length);
2785 // remove bad characters at start and end
2786 $filename = trim($filename, '.-_');
2787 return $filename;
2788 }
2789
2797 function getcolors($color) {
2798 $color = str_replace('#', '', $color);
2799 if (strlen($color) == 3) $color = str_repeat(substr($color, 0, 1), 2) . str_repeat(substr($color, 1, 1), 2) . str_repeat(substr($color, 2, 1), 2);
2800 $r = sscanf($color, "%2x%2x%2x");
2801 $red = (is_array($r) && array_key_exists(0, $r) && is_numeric($r[0]) ? $r[0] : 0);
2802 $green = (is_array($r) && array_key_exists(1, $r) && is_numeric($r[1]) ? $r[1] : 0);
2803 $blue = (is_array($r) && array_key_exists(2, $r) && is_numeric($r[2]) ? $r[2] : 0);
2804 return array($red, $green, $blue);
2805 }
2806
2814 function getsize($size) {
2815 if ($size === null) return null;
2816 $last = is_string($size) ? strtolower(substr($size, -1)) : null;
2817 $size = (int) $size;
2818 switch($last) {
2819 case 'g':
2820 $size *= 1024;
2821 case 'm':
2822 $size *= 1024;
2823 case 'k':
2824 $size *= 1024;
2825 }
2826 return $size;
2827 }
2828
2840 function getoffsets($offsets, $x, $y, $round = true, $negative = true) {
2841 if (!is_array($offsets)) $offsets = explode(' ', $offsets);
2842 if (sizeof($offsets) == 4) {
2843 $ct = $offsets[0]; $cr = $offsets[1]; $cb = $offsets[2]; $cl = $offsets[3];
2844 } else if (sizeof($offsets) == 2) {
2845 $ct = $offsets[0]; $cr = $offsets[1]; $cb = $offsets[0]; $cl = $offsets[1];
2846 } else {
2847 $ct = $offsets[0]; $cr = $offsets[0]; $cb = $offsets[0]; $cl = $offsets[0];
2848 }
2849 if (strpos($ct, '%')>0) $ct = $y * (str_replace('%','',$ct) / 100);
2850 if (strpos($cr, '%')>0) $cr = $x * (str_replace('%','',$cr) / 100);
2851 if (strpos($cb, '%')>0) $cb = $y * (str_replace('%','',$cb) / 100);
2852 if (strpos($cl, '%')>0) $cl = $x * (str_replace('%','',$cl) / 100);
2853 if (strpos($ct, 'px')>0) $ct = str_replace('px','',$ct);
2854 if (strpos($cr, 'px')>0) $cr = str_replace('px','',$cr);
2855 if (strpos($cb, 'px')>0) $cb = str_replace('px','',$cb);
2856 if (strpos($cl, 'px')>0) $cl = str_replace('px','',$cl);
2857 $ct = (int) $ct; $cr = (int) $cr; $cb = (int) $cb; $cl = (int) $cl;
2858 if ($round) {
2859 $ct = round($ct);
2860 $cr = round($cr);
2861 $cb = round($cb);
2862 $cl = round($cl);
2863 }
2864 if (!$negative) {
2865 if ($ct < 0) $ct = 0;
2866 if ($cr < 0) $cr = 0;
2867 if ($cb < 0) $cb = 0;
2868 if ($cl < 0) $cl = 0;
2869 }
2870 return array($ct, $cr, $cb, $cl);
2871 }
2872
2883 function imagecreatenew($x, $y, $fill = true, $trsp = false) {
2884 $x = (int) $x; $y = (int) $y;
2885 if ($x < 1) $x = 1; if ($y < 1) $y = 1;
2886 if ($this->gdversion() >= 2 && !$this->image_is_palette) {
2887 // create a true color image
2888 $dst_im = imagecreatetruecolor($x, $y);
2889 // this preserves transparency in PNG and WEBP, in true color
2890 if (empty($this->image_background_color) || $trsp) {
2891 imagealphablending($dst_im, false );
2892 imagefilledrectangle($dst_im, 0, 0, $x, $y, imagecolorallocatealpha($dst_im, 0, 0, 0, 127));
2893 }
2894 } else {
2895 // creates a palette image
2896 $dst_im = imagecreate($x, $y);
2897 // preserves transparency for palette images, if the original image has transparency
2898 if (($fill && $this->image_is_transparent && empty($this->image_background_color)) || $trsp) {
2899 imagefilledrectangle($dst_im, 0, 0, $x, $y, $this->image_transparent_color);
2900 imagecolortransparent($dst_im, $this->image_transparent_color);
2901 }
2902 }
2903 // fills with background color if any is set
2904 if ($fill && !empty($this->image_background_color) && !$trsp) {
2905 list($red, $green, $blue) = $this->getcolors($this->image_background_color);
2906 $background_color = imagecolorallocate($dst_im, $red, $green, $blue);
2907 imagefilledrectangle($dst_im, 0, 0, $x, $y, $background_color);
2908 }
2909 return $dst_im;
2910 }
2911
2912
2921 function imagetransfer($src_im, $dst_im) {
2922 $this->imageunset($dst_im);
2923 $dst_im = & $src_im;
2924 return $dst_im;
2925 }
2926
2933 function imageunset($im) {
2934 if (is_resource($im)) {
2935 imagedestroy($im);
2936 } else if (is_object($im) && $im instanceOf \GdImage) {
2937 unset($im);
2938 }
2939 }
2940
2969 function imagecopymergealpha(&$dst_im, &$src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct = 0) {
2970 $dst_x = (int) $dst_x;
2971 $dst_y = (int) $dst_y;
2972 $src_x = (int) $src_x;
2973 $src_y = (int) $src_y;
2974 $src_w = (int) $src_w;
2975 $src_h = (int) $src_h;
2976 $pct = (int) $pct;
2977 $dst_w = imagesx($dst_im);
2978 $dst_h = imagesy($dst_im);
2979
2980 for ($y = $src_y; $y < $src_h; $y++) {
2981 for ($x = $src_x; $x < $src_w; $x++) {
2982
2983 if ($x + $dst_x >= 0 && $x + $dst_x < $dst_w && $x + $src_x >= 0 && $x + $src_x < $src_w
2984 && $y + $dst_y >= 0 && $y + $dst_y < $dst_h && $y + $src_y >= 0 && $y + $src_y < $src_h) {
2985
2986 $dst_pixel = imagecolorsforindex($dst_im, imagecolorat($dst_im, $x + $dst_x, $y + $dst_y));
2987 $src_pixel = imagecolorsforindex($src_im, imagecolorat($src_im, $x + $src_x, $y + $src_y));
2988
2989 $src_alpha = 1 - ($src_pixel['alpha'] / 127);
2990 $dst_alpha = 1 - ($dst_pixel['alpha'] / 127);
2991 $opacity = $src_alpha * $pct / 100;
2992 if ($dst_alpha >= $opacity) $alpha = $dst_alpha;
2993 if ($dst_alpha < $opacity) $alpha = $opacity;
2994 if ($alpha > 1) $alpha = 1;
2995
2996 if ($opacity > 0) {
2997 $dst_red = round(( ($dst_pixel['red'] * $dst_alpha * (1 - $opacity)) ) );
2998 $dst_green = round(( ($dst_pixel['green'] * $dst_alpha * (1 - $opacity)) ) );
2999 $dst_blue = round(( ($dst_pixel['blue'] * $dst_alpha * (1 - $opacity)) ) );
3000 $src_red = round((($src_pixel['red'] * $opacity)) );
3001 $src_green = round((($src_pixel['green'] * $opacity)) );
3002 $src_blue = round((($src_pixel['blue'] * $opacity)) );
3003 $red = round(($dst_red + $src_red ) / ($dst_alpha * (1 - $opacity) + $opacity));
3004 $green = round(($dst_green + $src_green) / ($dst_alpha * (1 - $opacity) + $opacity));
3005 $blue = round(($dst_blue + $src_blue ) / ($dst_alpha * (1 - $opacity) + $opacity));
3006 if ($red > 255) $red = 255;
3007 if ($green > 255) $green = 255;
3008 if ($blue > 255) $blue = 255;
3009 $alpha = round((1 - $alpha) * 127);
3010 $color = imagecolorallocatealpha($dst_im, $red, $green, $blue, $alpha);
3011 imagesetpixel($dst_im, $x + $dst_x, $y + $dst_y, $color);
3012 }
3013 }
3014 }
3015 }
3016 return true;
3017 }
3018
3019
3020
3045 function process($server_path = null) {
3046 $this->error = '';
3047 $this->processed = true;
3048 $return_mode = false;
3049 $return_content = null;
3050
3051 // clean up dst variables
3052 $this->file_dst_path = '';
3053 $this->file_dst_pathname = '';
3054 $this->file_dst_name = '';
3055 $this->file_dst_name_body = '';
3056 $this->file_dst_name_ext = '';
3057
3058 // clean up some parameters
3059 $this->file_max_size = $this->getsize($this->file_max_size);
3060 $this->jpeg_size = $this->getsize($this->jpeg_size);
3061
3062 // copy some variables as we need to keep them clean
3066
3067 if (!$this->uploaded) {
3068 $this->error = $this->translate('file_not_uploaded');
3069 $this->processed = false;
3070 }
3071
3072 if ($this->processed) {
3073 if (empty($server_path) || is_null($server_path)) {
3074 $this->log .= '<b>process file and return the content</b><br />';
3075 $return_mode = true;
3076 } else {
3077 if(strtolower(substr(PHP_OS, 0, 3)) === 'win') {
3078 if (substr($server_path, -1, 1) != '\\') $server_path = $server_path . '\\';
3079 } else {
3080 if (substr($server_path, -1, 1) != '/') $server_path = $server_path . '/';
3081 }
3082 $this->log .= '<b>process file to ' . $server_path . '</b><br />';
3083 }
3084 }
3085
3086 if ($this->processed) {
3087 // checks file max size
3088 if ($this->file_src_size > $this->file_max_size) {
3089 $this->processed = false;
3090 $this->error = $this->translate('file_too_big') . ' : ' . $this->file_src_size . ' > ' . $this->file_max_size;
3091 } else {
3092 $this->log .= '- file size OK<br />';
3093 }
3094 }
3095
3096 if ($this->processed) {
3097 // if we have an image without extension, set it
3098 if ($this->file_force_extension && $this->file_is_image && !$this->file_src_name_ext) $file_src_name_ext = $this->image_src_type;
3099 // turn dangerous scripts into text files
3100 if ($this->no_script) {
3101 // if the file has no extension, we try to guess it from the MIME type
3102 if ($this->file_force_extension && empty($file_src_name_ext)) {
3103 if ($key = array_search($this->file_src_mime, $this->mime_types)) {
3104 $file_src_name_ext = $key;
3106 $this->log .= '- file renamed as ' . $file_src_name_body . '.' . $file_src_name_ext . '!<br />';
3107 }
3108 }
3109 // if the file is text based, or has a dangerous extension, we rename it as .txt
3110 if ((((substr($this->file_src_mime, 0, 5) == 'text/' && $this->file_src_mime != 'text/rtf') || strpos($this->file_src_mime, 'javascript') !== false) && (substr($file_src_name, -4) != '.txt'))
3111 || preg_match('/\.(' . implode('|', $this->dangerous) . ')/i', $this->file_src_name)
3112 || $this->file_force_extension && empty($file_src_name_ext)) {
3113 $this->file_src_mime = 'text/plain';
3114 if ($this->file_src_name_ext) $file_src_name_body = $file_src_name_body . '.' . $this->file_src_name_ext;
3115 $file_src_name_ext = 'txt';
3117 $this->log .= '- script renamed as ' . $file_src_name_body . '.' . $file_src_name_ext . '!<br />';
3118 }
3119 }
3120
3121 if ($this->mime_check && empty($this->file_src_mime)) {
3122 $this->processed = false;
3123 $this->error = $this->translate('no_mime');
3124 } else if ($this->mime_check && !empty($this->file_src_mime) && strpos($this->file_src_mime, '/') !== false) {
3125 list($m1, $m2) = explode('/', $this->file_src_mime);
3126 $allowed = false;
3127 // check wether the mime type or file extension is allowed
3128 if (!is_array($this->allowed)) $this->allowed = array($this->allowed);
3129 foreach($this->allowed as $k => $v) {
3130 if (strpos($v, '/') == false) {
3131 if ($v == '*' || strtolower($v) == strtolower($file_src_name_ext)) {
3132 $allowed = true;
3133 break;
3134 }
3135 } else {
3136 list($v1, $v2) = explode('/', $v);
3137 if (($v1 == '*' && $v2 == '*') || ($v1 == $m1 && ($v2 == $m2 || $v2 == '*'))) {
3138 $allowed = true;
3139 break;
3140 }
3141 }
3142 }
3143 if (!$allowed) $this->log .= '- MIME type and/or extension is not allowed !<br />';
3144 // check wether the mime type or file extension is forbidden
3145 if (!is_array($this->forbidden)) $this->forbidden = array($this->forbidden);
3146 foreach($this->forbidden as $k => $v) {
3147 if (strpos($v, '/') == false) {
3148 if ($v == '*' || strtolower($v) == strtolower($file_src_name_ext)) {
3149 $allowed = false;
3150 $this->log .= '- extension ' . $v . ' is forbidden !<br />';
3151 break;
3152 }
3153 } else {
3154 list($v1, $v2) = explode('/', $v);
3155 if (($v1 == '*' && $v2 == '*') || ($v1 == $m1 && ($v2 == $m2 || $v2 == '*'))) {
3156 $allowed = false;
3157 $this->log .= '- MIME type ' . $v . ' is forbidden !<br />';
3158 break;
3159 }
3160 }
3161 }
3162 if (!$allowed) {
3163 $this->processed = false;
3164 $this->error = $this->translate('incorrect_file');
3165 } else {
3166 $this->log .= '- file mime OK : ' . $this->file_src_mime . '<br />';
3167 $this->log .= '- file extension OK : ' . $file_src_name_ext . '<br />';
3168 }
3169 } else {
3170 $this->log .= '- file mime (not checked) : ' . $this->file_src_mime . '<br />';
3171 }
3172
3173 // if the file is an image, we can check on its dimensions
3174 // these checks are not available if open_basedir restrictions are in place
3175 if ($this->file_is_image) {
3176 if (is_numeric($this->image_src_x) && is_numeric($this->image_src_y)) {
3177 $ratio = $this->image_src_x / $this->image_src_y;
3178 if (!is_null($this->image_max_width) && $this->image_src_x > $this->image_max_width) {
3179 $this->processed = false;
3180 $this->error = $this->translate('image_too_wide');
3181 }
3182 if (!is_null($this->image_min_width) && $this->image_src_x < $this->image_min_width) {
3183 $this->processed = false;
3184 $this->error = $this->translate('image_too_narrow');
3185 }
3186 if (!is_null($this->image_max_height) && $this->image_src_y > $this->image_max_height) {
3187 $this->processed = false;
3188 $this->error = $this->translate('image_too_high');
3189 }
3190 if (!is_null($this->image_min_height) && $this->image_src_y < $this->image_min_height) {
3191 $this->processed = false;
3192 $this->error = $this->translate('image_too_short');
3193 }
3194 if (!is_null($this->image_max_ratio) && $ratio > $this->image_max_ratio) {
3195 $this->processed = false;
3196 $this->error = $this->translate('ratio_too_high');
3197 }
3198 if (!is_null($this->image_min_ratio) && $ratio < $this->image_min_ratio) {
3199 $this->processed = false;
3200 $this->error = $this->translate('ratio_too_low');
3201 }
3202 if (!is_null($this->image_max_pixels) && $this->image_src_pixels > $this->image_max_pixels) {
3203 $this->processed = false;
3204 $this->error = $this->translate('too_many_pixels');
3205 }
3206 if (!is_null($this->image_min_pixels) && $this->image_src_pixels < $this->image_min_pixels) {
3207 $this->processed = false;
3208 $this->error = $this->translate('not_enough_pixels');
3209 }
3210 } else {
3211 $this->log .= '- no image properties available, can\'t enforce dimension checks : ' . $this->file_src_mime . '<br />';
3212 }
3213 }
3214 }
3215
3216 if ($this->processed) {
3217 $this->file_dst_path = $server_path;
3218
3219 // repopulate dst variables from src
3220 $this->file_dst_name = $file_src_name;
3221 $this->file_dst_name_body = $file_src_name_body;
3222 $this->file_dst_name_ext = $file_src_name_ext;
3223 if ($this->file_overwrite) $this->file_auto_rename = false;
3224
3225 if ($this->image_convert && $this->file_is_image) { // if we convert as an image
3226 $this->file_dst_name_ext = $this->image_convert;
3227 $this->log .= '- new file name ext : ' . $this->file_dst_name_ext . '<br />';
3228 }
3229 if (!is_null($this->file_new_name_body)) { // rename file body
3230 $this->file_dst_name_body = $this->file_new_name_body;
3231 $this->log .= '- new file name body : ' . $this->file_new_name_body . '<br />';
3232 }
3233 if (!is_null($this->file_new_name_ext)) { // rename file ext
3234 $this->file_dst_name_ext = $this->file_new_name_ext;
3235 $this->log .= '- new file name ext : ' . $this->file_new_name_ext . '<br />';
3236 }
3237 if (!is_null($this->file_name_body_add)) { // append a string to the name
3238 $this->file_dst_name_body = $this->file_dst_name_body . $this->file_name_body_add;
3239 $this->log .= '- file name body append : ' . $this->file_name_body_add . '<br />';
3240 }
3241 if (!is_null($this->file_name_body_pre)) { // prepend a string to the name
3242 $this->file_dst_name_body = $this->file_name_body_pre . $this->file_dst_name_body;
3243 $this->log .= '- file name body prepend : ' . $this->file_name_body_pre . '<br />';
3244 }
3245 if ($this->file_safe_name) { // sanitize the name
3246 $this->file_dst_name_body = $this->sanitize($this->file_dst_name_body);
3247 $this->log .= '- file name safe format<br />';
3248 }
3249
3250 $this->log .= '- destination variables<br />';
3251 if (empty($this->file_dst_path) || is_null($this->file_dst_path)) {
3252 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_dst_path : n/a<br />';
3253 } else {
3254 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_dst_path : ' . $this->file_dst_path . '<br />';
3255 }
3256 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_dst_name_body : ' . $this->file_dst_name_body . '<br />';
3257 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_dst_name_ext : ' . $this->file_dst_name_ext . '<br />';
3258
3259 // set the destination file name
3260 $this->file_dst_name = $this->file_dst_name_body . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : '');
3261
3262 if (!$return_mode) {
3263 if (!$this->file_auto_rename) {
3264 $this->log .= '- no auto_rename if same filename exists<br />';
3265 $this->file_dst_pathname = $this->file_dst_path . $this->file_dst_name;
3266 } else {
3267 $this->log .= '- checking for auto_rename<br />';
3268 $this->file_dst_pathname = $this->file_dst_path . $this->file_dst_name;
3270 $ext = '';
3271 // if we have changed the extension, then we add our increment before
3272 if ($file_src_name_ext != $this->file_src_name_ext) {
3273 if (substr($this->file_dst_name_body, -1 - strlen($this->file_src_name_ext)) == '.' . $this->file_src_name_ext) {
3274 $body = substr($this->file_dst_name_body, 0, strlen($this->file_dst_name_body) - 1 - strlen($this->file_src_name_ext));
3275 $ext = '.' . $this->file_src_name_ext;
3276 }
3277 }
3278 $cpt = 1;
3279 while (@file_exists($this->file_dst_pathname)) {
3280 $this->file_dst_name_body = $body . '_' . $cpt . $ext;
3281 $this->file_dst_name = $this->file_dst_name_body . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : '');
3282 $cpt++;
3283 $this->file_dst_pathname = $this->file_dst_path . $this->file_dst_name;
3284 }
3285 if ($cpt>1) $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;auto_rename to ' . $this->file_dst_name . '<br />';
3286 }
3287
3288 $this->log .= '- destination file details<br />';
3289 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_dst_name : ' . $this->file_dst_name . '<br />';
3290 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;file_dst_pathname : ' . $this->file_dst_pathname . '<br />';
3291
3292 if ($this->file_overwrite) {
3293 $this->log .= '- no overwrite checking<br />';
3294 } else {
3295 if (@file_exists($this->file_dst_pathname)) {
3296 $this->processed = false;
3297 $this->error = $this->translate('already_exists', array($this->file_dst_name));
3298 } else {
3299 $this->log .= '- ' . $this->file_dst_name . ' doesn\'t exist already<br />';
3300 }
3301 }
3302 }
3303 }
3304
3305 if ($this->processed) {
3306 // if we have already moved the uploaded file, we use the temporary copy as source file, and check if it exists
3307 if (!empty($this->file_src_temp)) {
3308 $this->log .= '- use the temp file instead of the original file since it is a second process<br />';
3309 $this->file_src_pathname = $this->file_src_temp;
3310 if (!file_exists($this->file_src_pathname)) {
3311 $this->processed = false;
3312 $this->error = $this->translate('temp_file_missing');
3313 }
3314 // if we haven't a temp file, and that we do check on uploads, we use is_uploaded_file()
3315 } else if (!$this->no_upload_check) {
3316 if (!is_uploaded_file($this->file_src_pathname)) {
3317 $this->processed = false;
3318 $this->error = $this->translate('source_missing');
3319 }
3320 // otherwise, if we don't check on uploaded files (local file for instance), we use file_exists()
3321 } else {
3322 if (!file_exists($this->file_src_pathname)) {
3323 $this->processed = false;
3324 $this->error = $this->translate('source_missing');
3325 }
3326 }
3327
3328 // checks if the destination directory exists, and attempt to create it
3329 if (!$return_mode) {
3330 if ($this->processed && !file_exists($this->file_dst_path)) {
3331 if ($this->dir_auto_create) {
3332 $this->log .= '- ' . $this->file_dst_path . ' doesn\'t exist. Attempting creation:';
3333 if (!$this->rmkdir($this->file_dst_path, $this->dir_chmod)) {
3334 $this->log .= ' failed<br />';
3335 $this->processed = false;
3336 $this->error = $this->translate('destination_dir');
3337 } else {
3338 $this->log .= ' success<br />';
3339 }
3340 } else {
3341 $this->error = $this->translate('destination_dir_missing');
3342 }
3343 }
3344
3345 if ($this->processed && !is_dir($this->file_dst_path)) {
3346 $this->processed = false;
3347 $this->error = $this->translate('destination_path_not_dir');
3348 }
3349
3350 // checks if the destination directory is writeable, and attempt to make it writeable
3351 $hash = md5($this->file_dst_name_body . rand(1, 1000));
3352 if ($this->processed && !($f = @fopen($this->file_dst_path . $hash . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : ''), 'a+'))) {
3353 if ($this->dir_auto_chmod) {
3354 $this->log .= '- ' . $this->file_dst_path . ' is not writeable. Attempting chmod:';
3355 if (!@chmod($this->file_dst_path, $this->dir_chmod)) {
3356 $this->log .= ' failed<br />';
3357 $this->processed = false;
3358 $this->error = $this->translate('destination_dir_write');
3359 } else {
3360 $this->log .= ' success<br />';
3361 if (!($f = @fopen($this->file_dst_path . $hash . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : ''), 'a+'))) { // we re-check
3362 $this->processed = false;
3363 $this->error = $this->translate('destination_dir_write');
3364 } else {
3365 @fclose($f);
3366 }
3367 }
3368 } else {
3369 $this->processed = false;
3370 $this->error = $this->translate('destination_path_write');
3371 }
3372 } else {
3373 if ($this->processed) @fclose($f);
3374 @unlink($this->file_dst_path . $hash . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : ''));
3375 }
3376
3377
3378 // if we have an uploaded file, and if it is the first process, and if we can't access the file directly (open_basedir restriction)
3379 // then we create a temp file that will be used as the source file in subsequent processes
3380 // the third condition is there to check if the file is not accessible *directly* (it already has positively gone through is_uploaded_file(), so it exists)
3381 if (!$this->no_upload_check && empty($this->file_src_temp) && !@file_exists($this->file_src_pathname)) {
3382 $this->log .= '- attempting to use a temp file:';
3383 $hash = md5($this->file_dst_name_body . rand(1, 1000));
3384 if (move_uploaded_file($this->file_src_pathname, $this->file_dst_path . $hash . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : ''))) {
3385 $this->file_src_pathname = $this->file_dst_path . $hash . (!empty($this->file_dst_name_ext) ? '.' . $this->file_dst_name_ext : '');
3386 $this->file_src_temp = $this->file_src_pathname;
3387 $this->log .= ' file created<br />';
3388 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;temp file is: ' . $this->file_src_temp . '<br />';
3389 } else {
3390 $this->log .= ' failed<br />';
3391 $this->processed = false;
3392 $this->error = $this->translate('temp_file');
3393 }
3394 }
3395 }
3396 }
3397
3398 if ($this->processed) {
3399
3400 // check if we need to autorotate, to automatically pre-rotates the image according to EXIF data (JPEG only)
3401 $auto_flip = false;
3402 $auto_rotate = 0;
3403 if ($this->file_is_image && $this->image_auto_rotate && $this->image_src_type == 'jpg' && $this->function_enabled('exif_read_data')) {
3404 $exif = @exif_read_data($this->file_src_pathname);
3405 if (is_array($exif) && isset($exif['Orientation'])) {
3406 $orientation = $exif['Orientation'];
3407 switch($orientation) {
3408 case 1:
3409 $this->log .= '- EXIF orientation = 1 : default<br />';
3410 break;
3411 case 2:
3412 $auto_flip = 'v';
3413 $this->log .= '- EXIF orientation = 2 : vertical flip<br />';
3414 break;
3415 case 3:
3416 $auto_rotate = 180;
3417 $this->log .= '- EXIF orientation = 3 : 180 rotate left<br />';
3418 break;
3419 case 4:
3420 $auto_flip = 'h';
3421 $this->log .= '- EXIF orientation = 4 : horizontal flip<br />';
3422 break;
3423 case 5:
3424 $auto_flip = 'h';
3425 $auto_rotate = 90;
3426 $this->log .= '- EXIF orientation = 5 : horizontal flip + 90 rotate right<br />';
3427 break;
3428 case 6:
3429 $auto_rotate = 90;
3430 $this->log .= '- EXIF orientation = 6 : 90 rotate right<br />';
3431 break;
3432 case 7:
3433 $auto_flip = 'v';
3434 $auto_rotate = 90;
3435 $this->log .= '- EXIF orientation = 7 : vertical flip + 90 rotate right<br />';
3436 break;
3437 case 8:
3438 $auto_rotate = 270;
3439 $this->log .= '- EXIF orientation = 8 : 90 rotate left<br />';
3440 break;
3441 default:
3442 $this->log .= '- EXIF orientation = '.$orientation.' : unknown<br />';
3443 break;
3444 }
3445 } else {
3446 $this->log .= '- EXIF data is invalid or missing<br />';
3447 }
3448 } else {
3449 if (!$this->image_auto_rotate) {
3450 $this->log .= '- auto-rotate deactivated<br />';
3451 } else if (!$this->image_src_type == 'jpg') {
3452 $this->log .= '- auto-rotate applies only to JPEG images<br />';
3453 } else if (!$this->function_enabled('exif_read_data')) {
3454 $this->log .= '- auto-rotate requires function exif_read_data to be enabled<br />';
3455 }
3456 }
3457
3458 // do we do some image manipulation?
3459 $image_manipulation = ($this->file_is_image && (
3460 $this->image_resize
3461 || $this->image_convert != ''
3462 || is_numeric($this->image_brightness)
3463 || is_numeric($this->image_contrast)
3464 || is_numeric($this->image_opacity)
3465 || is_numeric($this->image_threshold)
3466 || !empty($this->image_tint_color)
3467 || !empty($this->image_overlay_color)
3468 || $this->image_pixelate
3469 || $this->image_unsharp
3470 || !empty($this->image_text)
3471 || $this->image_greyscale
3472 || $this->image_negative
3473 || !empty($this->image_watermark)
3474 || $auto_rotate || $auto_flip
3475 || is_numeric($this->image_rotate)
3476 || is_numeric($this->jpeg_size)
3477 || !empty($this->image_flip)
3478 || !empty($this->image_crop)
3479 || !empty($this->image_precrop)
3480 || !empty($this->image_border)
3481 || !empty($this->image_border_transparent)
3482 || $this->image_frame > 0
3483 || $this->image_bevel > 0
3485
3486 // we do a quick check to ensure the file is really an image
3487 // we can do this only now, as it would have failed before in case of open_basedir
3488 if ($image_manipulation && !@getimagesize($this->file_src_pathname)) {
3489 $this->log .= '- the file is not an image!<br />';
3490 $image_manipulation = false;
3491 }
3492
3493 if ($image_manipulation) {
3494
3495 // make sure GD doesn't complain too much
3496 @ini_set("gd.jpeg_ignore_warning", 1);
3497
3498 // checks if the source file is readable
3499 if ($this->processed && !($f = @fopen($this->file_src_pathname, 'r'))) {
3500 $this->processed = false;
3501 $this->error = $this->translate('source_not_readable');
3502 } else {
3503 @fclose($f);
3504 }
3505
3506 // we now do all the image manipulations
3507 $this->log .= '- image resizing or conversion wanted<br />';
3508 if ($this->gdversion()) {
3509 switch($this->image_src_type) {
3510 case 'jpg':
3511 if (!$this->function_enabled('imagecreatefromjpeg')) {
3512 $this->processed = false;
3513 $this->error = $this->translate('no_create_support', array('JPEG'));
3514 } else {
3515 $image_src = @imagecreatefromjpeg($this->file_src_pathname);
3516 if (!$image_src) {
3517 $this->processed = false;
3518 $this->error = $this->translate('create_error', array('JPEG'));
3519 } else {
3520 $this->log .= '- source image is JPEG<br />';
3521 }
3522 }
3523 break;
3524 case 'png':
3525 if (!$this->function_enabled('imagecreatefrompng')) {
3526 $this->processed = false;
3527 $this->error = $this->translate('no_create_support', array('PNG'));
3528 } else {
3529 $image_src = @imagecreatefrompng($this->file_src_pathname);
3530 if (!$image_src) {
3531 $this->processed = false;
3532 $this->error = $this->translate('create_error', array('PNG'));
3533 } else {
3534 $this->log .= '- source image is PNG<br />';
3535 }
3536 }
3537 break;
3538 case 'webp':
3539 if (!$this->function_enabled('imagecreatefromwebp')) {
3540 $this->processed = false;
3541 $this->error = $this->translate('no_create_support', array('WEBP'));
3542 } else {
3543 $image_src = @imagecreatefromwebp($this->file_src_pathname);
3544 if (!$image_src) {
3545 $this->processed = false;
3546 $this->error = $this->translate('create_error', array('WEBP'));
3547 } else {
3548 $this->log .= '- source image is WEBP<br />';
3549 }
3550 }
3551 break;
3552 case 'gif':
3553 if (!$this->function_enabled('imagecreatefromgif')) {
3554 $this->processed = false;
3555 $this->error = $this->translate('no_create_support', array('GIF'));
3556 } else {
3557 $image_src = @imagecreatefromgif($this->file_src_pathname);
3558 if (!$image_src) {
3559 $this->processed = false;
3560 $this->error = $this->translate('create_error', array('GIF'));
3561 } else {
3562 $this->log .= '- source image is GIF<br />';
3563 }
3564 }
3565 break;
3566 case 'bmp':
3567 if (!method_exists($this, 'imagecreatefrombmp')) {
3568 $this->processed = false;
3569 $this->error = $this->translate('no_create_support', array('BMP'));
3570 } else {
3571 $image_src = @$this->imagecreatefrombmp($this->file_src_pathname);
3572 if (!$image_src) {
3573 $this->processed = false;
3574 $this->error = $this->translate('create_error', array('BMP'));
3575 } else {
3576 $this->log .= '- source image is BMP<br />';
3577 }
3578 }
3579 break;
3580 default:
3581 $this->processed = false;
3582 $this->error = $this->translate('source_invalid');
3583 }
3584 } else {
3585 $this->processed = false;
3586 $this->error = $this->translate('gd_missing');
3587 }
3588
3589 if ($this->processed && $image_src) {
3590
3591 // we have to set image_convert if it is not already
3592 if (empty($this->image_convert)) {
3593 $this->log .= '- setting destination file type to ' . $this->image_src_type . '<br />';
3594 $this->image_convert = $this->image_src_type;
3595 } else {
3596 $this->log .= '- requested destination file type is ' . $this->image_convert . '<br />';
3597 }
3598
3599 if (!in_array($this->image_convert, $this->image_supported)) {
3600 $this->log .= '- destination file type ' . $this->image_convert . ' is not supported; switching to jpg<br />';
3601 $this->image_convert = 'jpg';
3602 }
3603
3604 // we set the default color to be the background color if we don't output in a transparent format
3605 if ($this->image_convert != 'png' && $this->image_convert != 'webp' && $this->image_convert != 'gif' && !empty($this->image_default_color) && empty($this->image_background_color)) $this->image_background_color = $this->image_default_color;
3606 if (!empty($this->image_background_color)) $this->image_default_color = $this->image_background_color;
3607 if (empty($this->image_default_color)) $this->image_default_color = '#FFFFFF';
3608
3609 $this->image_src_x = imagesx($image_src);
3610 $this->image_src_y = imagesy($image_src);
3611 $gd_version = $this->gdversion();
3612 $ratio_crop = null;
3613
3614 if (!imageistruecolor($image_src)) { // $this->image_src_type == 'gif'
3615 $this->log .= '- image is detected as having a palette<br />';
3616 $this->image_is_palette = true;
3617 $this->image_transparent_color = imagecolortransparent($image_src);
3618 if ($this->image_transparent_color >= 0 && imagecolorstotal($image_src) > $this->image_transparent_color) {
3619 $this->image_is_transparent = true;
3620 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;palette image is detected as transparent<br />';
3621 }
3622 // if the image has a palette (GIF), we convert it to true color, preserving transparency
3623 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;convert palette image to true color<br />';
3624 $true_color = imagecreatetruecolor($this->image_src_x, $this->image_src_y);
3625 imagealphablending($true_color, false);
3626 imagesavealpha($true_color, true);
3627 for ($x = 0; $x < $this->image_src_x; $x++) {
3628 for ($y = 0; $y < $this->image_src_y; $y++) {
3629 if ($this->image_transparent_color >= 0 && imagecolorat($image_src, $x, $y) == $this->image_transparent_color) {
3630 imagesetpixel($true_color, $x, $y, 127 << 24);
3631 } else {
3632 $rgb = imagecolorsforindex($image_src, imagecolorat($image_src, $x, $y));
3633 imagesetpixel($true_color, $x, $y, ($rgb['alpha'] << 24) | ($rgb['red'] << 16) | ($rgb['green'] << 8) | $rgb['blue']);
3634 }
3635 }
3636 }
3637 $image_src = $this->imagetransfer($true_color, $image_src);
3638 imagealphablending($image_src, false);
3639 imagesavealpha($image_src, true);
3640 $this->image_is_palette = false;
3641 }
3642
3643 $image_dst = & $image_src;
3644
3645 // auto-flip image, according to EXIF data (JPEG only)
3646 if ($gd_version >= 2 && !empty($auto_flip)) {
3647 $this->log .= '- auto-flip image : ' . ($auto_flip == 'v' ? 'vertical' : 'horizontal') . '<br />';
3648 $tmp = $this->imagecreatenew($this->image_src_x, $this->image_src_y);
3649 for ($x = 0; $x < $this->image_src_x; $x++) {
3650 for ($y = 0; $y < $this->image_src_y; $y++){
3651 if (strpos($auto_flip, 'v') !== false) {
3652 imagecopy($tmp, $image_dst, $this->image_src_x - $x - 1, $y, $x, $y, 1, 1);
3653 } else {
3654 imagecopy($tmp, $image_dst, $x, $this->image_src_y - $y - 1, $x, $y, 1, 1);
3655 }
3656 }
3657 }
3658 // we transfert tmp into image_dst
3659 $image_dst = $this->imagetransfer($tmp, $image_dst);
3660 }
3661
3662 // auto-rotate image, according to EXIF data (JPEG only)
3663 if ($gd_version >= 2 && is_numeric($auto_rotate)) {
3664 if (!in_array($auto_rotate, array(0, 90, 180, 270))) $auto_rotate = 0;
3665 if ($auto_rotate != 0) {
3666 if ($auto_rotate == 90 || $auto_rotate == 270) {
3667 $tmp = $this->imagecreatenew($this->image_src_y, $this->image_src_x);
3668 } else {
3669 $tmp = $this->imagecreatenew($this->image_src_x, $this->image_src_y);
3670 }
3671 $this->log .= '- auto-rotate image : ' . $auto_rotate . '<br />';
3672 for ($x = 0; $x < $this->image_src_x; $x++) {
3673 for ($y = 0; $y < $this->image_src_y; $y++){
3674 if ($auto_rotate == 90) {
3675 imagecopy($tmp, $image_dst, $y, $x, $x, $this->image_src_y - $y - 1, 1, 1);
3676 } else if ($auto_rotate == 180) {
3677 imagecopy($tmp, $image_dst, $x, $y, $this->image_src_x - $x - 1, $this->image_src_y - $y - 1, 1, 1);
3678 } else if ($auto_rotate == 270) {
3679 imagecopy($tmp, $image_dst, $y, $x, $this->image_src_x - $x - 1, $y, 1, 1);
3680 } else {
3681 imagecopy($tmp, $image_dst, $x, $y, $x, $y, 1, 1);
3682 }
3683 }
3684 }
3685 if ($auto_rotate == 90 || $auto_rotate == 270) {
3686 $t = $this->image_src_y;
3687 $this->image_src_y = $this->image_src_x;
3688 $this->image_src_x = $t;
3689 }
3690 // we transfert tmp into image_dst
3691 $image_dst = $this->imagetransfer($tmp, $image_dst);
3692 }
3693 }
3694
3695 // pre-crop image, before resizing
3696 if ((!empty($this->image_precrop))) {
3697 list($ct, $cr, $cb, $cl) = $this->getoffsets($this->image_precrop, $this->image_src_x, $this->image_src_y, true, true);
3698 $this->log .= '- pre-crop image : ' . $ct . ' ' . $cr . ' ' . $cb . ' ' . $cl . ' <br />';
3699 $this->image_src_x = $this->image_src_x - $cl - $cr;
3700 $this->image_src_y = $this->image_src_y - $ct - $cb;
3701 if ($this->image_src_x < 1) $this->image_src_x = 1;
3702 if ($this->image_src_y < 1) $this->image_src_y = 1;
3703 $tmp = $this->imagecreatenew($this->image_src_x, $this->image_src_y);
3704
3705 // we copy the image into the recieving image
3706 imagecopy($tmp, $image_dst, 0, 0, $cl, $ct, $this->image_src_x, $this->image_src_y);
3707
3708 // if we crop with negative margins, we have to make sure the extra bits are the right color, or transparent
3709 if ($ct < 0 || $cr < 0 || $cb < 0 || $cl < 0 ) {
3710 // use the background color if present
3711 if (!empty($this->image_background_color)) {
3712 list($red, $green, $blue) = $this->getcolors($this->image_background_color);
3713 $fill = imagecolorallocate($tmp, $red, $green, $blue);
3714 } else {
3715 $fill = imagecolorallocatealpha($tmp, 0, 0, 0, 127);
3716 }
3717 // fills eventual negative margins
3718 if ($ct < 0) imagefilledrectangle($tmp, 0, 0, $this->image_src_x, -$ct, $fill);
3719 if ($cr < 0) imagefilledrectangle($tmp, $this->image_src_x + $cr, 0, $this->image_src_x, $this->image_src_y, $fill);
3720 if ($cb < 0) imagefilledrectangle($tmp, 0, $this->image_src_y + $cb, $this->image_src_x, $this->image_src_y, $fill);
3721 if ($cl < 0) imagefilledrectangle($tmp, 0, 0, -$cl, $this->image_src_y, $fill);
3722 }
3723
3724 // we transfert tmp into image_dst
3725 $image_dst = $this->imagetransfer($tmp, $image_dst);
3726 }
3727
3728 // resize image (and move image_src_x, image_src_y dimensions into image_dst_x, image_dst_y)
3729 if ($this->image_resize) {
3730 $this->log .= '- resizing...<br />';
3731 $this->image_dst_x = $this->image_x;
3732 $this->image_dst_y = $this->image_y;
3733
3734 // backward compatibility for soon to be deprecated settings
3735 if ($this->image_ratio_no_zoom_in) {
3736 $this->image_ratio = true;
3737 $this->image_no_enlarging = true;
3738 } else if ($this->image_ratio_no_zoom_out) {
3739 $this->image_ratio = true;
3740 $this->image_no_shrinking = true;
3741 }
3742
3743 // keeps aspect ratio with x calculated from y
3744 if ($this->image_ratio_x) {
3745 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;calculate x size<br />';
3746 $this->image_dst_x = round(($this->image_src_x * $this->image_y) / $this->image_src_y);
3747 $this->image_dst_y = $this->image_y;
3748
3749 // keeps aspect ratio with y calculated from x
3750 } else if ($this->image_ratio_y) {
3751 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;calculate y size<br />';
3752 $this->image_dst_x = $this->image_x;
3753 $this->image_dst_y = round(($this->image_src_y * $this->image_x) / $this->image_src_x);
3754
3755 // keeps aspect ratio, calculating x and y so that the image is approx the set number of pixels
3756 } else if (is_numeric($this->image_ratio_pixels)) {
3757 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;calculate x/y size to match a number of pixels<br />';
3758 $pixels = $this->image_src_y * $this->image_src_x;
3759 $diff = sqrt($this->image_ratio_pixels / $pixels);
3760 $this->image_dst_x = round($this->image_src_x * $diff);
3761 $this->image_dst_y = round($this->image_src_y * $diff);
3762
3763 // keeps aspect ratio with x and y dimensions, filling the space
3764 } else if ($this->image_ratio_crop) {
3765 if (!is_string($this->image_ratio_crop)) $this->image_ratio_crop = '';
3766 $this->image_ratio_crop = strtolower($this->image_ratio_crop);
3767 if (($this->image_src_x/$this->image_x) > ($this->image_src_y/$this->image_y)) {
3768 $this->image_dst_y = $this->image_y;
3769 $this->image_dst_x = intval($this->image_src_x*($this->image_y / $this->image_src_y));
3770 $ratio_crop = array();
3771 $ratio_crop['x'] = $this->image_dst_x - $this->image_x;
3772 if (strpos($this->image_ratio_crop, 'l') !== false) {
3773 $ratio_crop['l'] = 0;
3774 $ratio_crop['r'] = $ratio_crop['x'];
3775 } else if (strpos($this->image_ratio_crop, 'r') !== false) {
3776 $ratio_crop['l'] = $ratio_crop['x'];
3777 $ratio_crop['r'] = 0;
3778 } else {
3779 $ratio_crop['l'] = round($ratio_crop['x']/2);
3780 $ratio_crop['r'] = $ratio_crop['x'] - $ratio_crop['l'];
3781 }
3782 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;ratio_crop_x : ' . $ratio_crop['x'] . ' (' . $ratio_crop['l'] . ';' . $ratio_crop['r'] . ')<br />';
3783 if (is_null($this->image_crop)) $this->image_crop = array(0, 0, 0, 0);
3784 } else {
3785 $this->image_dst_x = $this->image_x;
3786 $this->image_dst_y = intval($this->image_src_y*($this->image_x / $this->image_src_x));
3787 $ratio_crop = array();
3788 $ratio_crop['y'] = $this->image_dst_y - $this->image_y;
3789 if (strpos($this->image_ratio_crop, 't') !== false) {
3790 $ratio_crop['t'] = 0;
3791 $ratio_crop['b'] = $ratio_crop['y'];
3792 } else if (strpos($this->image_ratio_crop, 'b') !== false) {
3793 $ratio_crop['t'] = $ratio_crop['y'];
3794 $ratio_crop['b'] = 0;
3795 } else {
3796 $ratio_crop['t'] = round($ratio_crop['y']/2);
3797 $ratio_crop['b'] = $ratio_crop['y'] - $ratio_crop['t'];
3798 }
3799 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;ratio_crop_y : ' . $ratio_crop['y'] . ' (' . $ratio_crop['t'] . ';' . $ratio_crop['b'] . ')<br />';
3800 if (is_null($this->image_crop)) $this->image_crop = array(0, 0, 0, 0);
3801 }
3802
3803 // keeps aspect ratio with x and y dimensions, fitting the image in the space, and coloring the rest
3804 } else if ($this->image_ratio_fill) {
3805 if (!is_string($this->image_ratio_fill)) $this->image_ratio_fill = '';
3806 $this->image_ratio_fill = strtolower($this->image_ratio_fill);
3807 if (($this->image_src_x/$this->image_x) < ($this->image_src_y/$this->image_y)) {
3808 $this->image_dst_y = $this->image_y;
3809 $this->image_dst_x = intval($this->image_src_x*($this->image_y / $this->image_src_y));
3810 $ratio_crop = array();
3811 $ratio_crop['x'] = $this->image_dst_x - $this->image_x;
3812 if (strpos($this->image_ratio_fill, 'l') !== false) {
3813 $ratio_crop['l'] = 0;
3814 $ratio_crop['r'] = $ratio_crop['x'];
3815 } else if (strpos($this->image_ratio_fill, 'r') !== false) {
3816 $ratio_crop['l'] = $ratio_crop['x'];
3817 $ratio_crop['r'] = 0;
3818 } else {
3819 $ratio_crop['l'] = round($ratio_crop['x']/2);
3820 $ratio_crop['r'] = $ratio_crop['x'] - $ratio_crop['l'];
3821 }
3822 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;ratio_fill_x : ' . $ratio_crop['x'] . ' (' . $ratio_crop['l'] . ';' . $ratio_crop['r'] . ')<br />';
3823 if (is_null($this->image_crop)) $this->image_crop = array(0, 0, 0, 0);
3824 } else {
3825 $this->image_dst_x = $this->image_x;
3826 $this->image_dst_y = intval($this->image_src_y*($this->image_x / $this->image_src_x));
3827 $ratio_crop = array();
3828 $ratio_crop['y'] = $this->image_dst_y - $this->image_y;
3829 if (strpos($this->image_ratio_fill, 't') !== false) {
3830 $ratio_crop['t'] = 0;
3831 $ratio_crop['b'] = $ratio_crop['y'];
3832 } else if (strpos($this->image_ratio_fill, 'b') !== false) {
3833 $ratio_crop['t'] = $ratio_crop['y'];
3834 $ratio_crop['b'] = 0;
3835 } else {
3836 $ratio_crop['t'] = round($ratio_crop['y']/2);
3837 $ratio_crop['b'] = $ratio_crop['y'] - $ratio_crop['t'];
3838 }
3839 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;ratio_fill_y : ' . $ratio_crop['y'] . ' (' . $ratio_crop['t'] . ';' . $ratio_crop['b'] . ')<br />';
3840 if (is_null($this->image_crop)) $this->image_crop = array(0, 0, 0, 0);
3841 }
3842
3843 // keeps aspect ratio with x and y dimensions
3844 } else if ($this->image_ratio) {
3845 if (($this->image_src_x/$this->image_x) > ($this->image_src_y/$this->image_y)) {
3846 $this->image_dst_x = $this->image_x;
3847 $this->image_dst_y = intval($this->image_src_y*($this->image_x / $this->image_src_x));
3848 } else {
3849 $this->image_dst_y = $this->image_y;
3850 $this->image_dst_x = intval($this->image_src_x*($this->image_y / $this->image_src_y));
3851 }
3852
3853 // resize to provided exact dimensions
3854 } else {
3855 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;use plain sizes<br />';
3856 $this->image_dst_x = $this->image_x;
3857 $this->image_dst_y = $this->image_y;
3858 }
3859
3860 if ($this->image_dst_x < 1) $this->image_dst_x = 1;
3861 if ($this->image_dst_y < 1) $this->image_dst_y = 1;
3862 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;image_src_x y : ' . $this->image_src_x . ' x ' . $this->image_src_y . '<br />';
3863 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;image_dst_x y : ' . $this->image_dst_x . ' x ' . $this->image_dst_y . '<br />';
3864
3865 // make sure we don't enlarge the image if we don't want to
3866 if ($this->image_no_enlarging && ($this->image_src_x < $this->image_dst_x || $this->image_src_y < $this->image_dst_y)) {
3867 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;cancel resizing, as it would enlarge the image!<br />';
3868 $this->image_dst_x = $this->image_src_x;
3869 $this->image_dst_y = $this->image_src_y;
3870 $ratio_crop = null;
3871 }
3872
3873 // make sure we don't shrink the image if we don't want to
3874 if ($this->image_no_shrinking && ($this->image_src_x > $this->image_dst_x || $this->image_src_y > $this->image_dst_y)) {
3875 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;cancel resizing, as it would shrink the image!<br />';
3876 $this->image_dst_x = $this->image_src_x;
3877 $this->image_dst_y = $this->image_src_y;
3878 $ratio_crop = null;
3879 }
3880
3881 // resize the image
3882 if ($this->image_dst_x != $this->image_src_x || $this->image_dst_y != $this->image_src_y) {
3883 $this->image_dst_x = (int) $this->image_dst_x;
3884 $this->image_dst_y = (int) $this->image_dst_y;
3885 $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
3886
3887 if ($gd_version >= 2) {
3888 $res = imagecopyresampled($tmp, $image_src, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, $this->image_src_x, $this->image_src_y);
3889 } else {
3890 $res = imagecopyresized($tmp, $image_src, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, $this->image_src_x, $this->image_src_y);
3891 }
3892
3893 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;resized image object created<br />';
3894 // we transfert tmp into image_dst
3895 $image_dst = $this->imagetransfer($tmp, $image_dst);
3896 }
3897
3898 } else {
3899 $this->image_dst_x = $this->image_src_x;
3900 $this->image_dst_y = $this->image_src_y;
3901 }
3902
3903 // crop image (and also crops if image_ratio_crop is used)
3904 if ((!empty($this->image_crop) || !is_null($ratio_crop))) {
3905 list($ct, $cr, $cb, $cl) = $this->getoffsets($this->image_crop, $this->image_dst_x, $this->image_dst_y, true, true);
3906 // we adjust the cropping if we use image_ratio_crop
3907 if (!is_null($ratio_crop)) {
3908 if (array_key_exists('t', $ratio_crop)) $ct += $ratio_crop['t'];
3909 if (array_key_exists('r', $ratio_crop)) $cr += $ratio_crop['r'];
3910 if (array_key_exists('b', $ratio_crop)) $cb += $ratio_crop['b'];
3911 if (array_key_exists('l', $ratio_crop)) $cl += $ratio_crop['l'];
3912 }
3913 if ($ct != 0 || $cr != 0 || $cb != 0 || $cl != 0) {
3914 $this->log .= '- crop image : ' . $ct . ' ' . $cr . ' ' . $cb . ' ' . $cl . ' <br />';
3915 $this->image_dst_x = $this->image_dst_x - $cl - $cr;
3916 $this->image_dst_y = $this->image_dst_y - $ct - $cb;
3917 if ($this->image_dst_x < 1) $this->image_dst_x = 1;
3918 if ($this->image_dst_y < 1) $this->image_dst_y = 1;
3919 $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
3920
3921 // we copy the image into the recieving image
3922 imagecopy($tmp, $image_dst, 0, 0, $cl, $ct, $this->image_dst_x, $this->image_dst_y);
3923
3924 // if we crop with negative margins, we have to make sure the extra bits are the right color, or transparent
3925 if ($ct < 0 || $cr < 0 || $cb < 0 || $cl < 0 ) {
3926 // use the background color if present
3927 if (!empty($this->image_background_color)) {
3928 list($red, $green, $blue) = $this->getcolors($this->image_background_color);
3929 $fill = imagecolorallocate($tmp, $red, $green, $blue);
3930 } else {
3931 $fill = imagecolorallocatealpha($tmp, 0, 0, 0, 127);
3932 }
3933 // fills eventual negative margins
3934 if ($ct < 0) imagefilledrectangle($tmp, 0, 0, $this->image_dst_x, -$ct-1, $fill);
3935 if ($cr < 0) imagefilledrectangle($tmp, $this->image_dst_x + $cr, 0, $this->image_dst_x, $this->image_dst_y, $fill);
3936 if ($cb < 0) imagefilledrectangle($tmp, 0, $this->image_dst_y + $cb, $this->image_dst_x, $this->image_dst_y, $fill);
3937 if ($cl < 0) imagefilledrectangle($tmp, 0, 0, -$cl-1, $this->image_dst_y, $fill);
3938 }
3939
3940 // we transfert tmp into image_dst
3941 $image_dst = $this->imagetransfer($tmp, $image_dst);
3942 }
3943 }
3944
3945 // flip image
3946 if ($gd_version >= 2 && !empty($this->image_flip)) {
3947 $this->image_flip = strtolower($this->image_flip);
3948 $this->log .= '- flip image : ' . $this->image_flip . '<br />';
3949 $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
3950 for ($x = 0; $x < $this->image_dst_x; $x++) {
3951 for ($y = 0; $y < $this->image_dst_y; $y++){
3952 if (strpos($this->image_flip, 'v') !== false) {
3953 imagecopy($tmp, $image_dst, $this->image_dst_x - $x - 1, $y, $x, $y, 1, 1);
3954 } else {
3955 imagecopy($tmp, $image_dst, $x, $this->image_dst_y - $y - 1, $x, $y, 1, 1);
3956 }
3957 }
3958 }
3959 // we transfert tmp into image_dst
3960 $image_dst = $this->imagetransfer($tmp, $image_dst);
3961 }
3962
3963 // rotate image
3964 if ($gd_version >= 2 && is_numeric($this->image_rotate)) {
3965 if (!in_array($this->image_rotate, array(0, 90, 180, 270))) $this->image_rotate = 0;
3966 if ($this->image_rotate != 0) {
3967 if ($this->image_rotate == 90 || $this->image_rotate == 270) {
3968 $tmp = $this->imagecreatenew($this->image_dst_y, $this->image_dst_x);
3969 } else {
3970 $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
3971 }
3972 $this->log .= '- rotate image : ' . $this->image_rotate . '<br />';
3973 for ($x = 0; $x < $this->image_dst_x; $x++) {
3974 for ($y = 0; $y < $this->image_dst_y; $y++){
3975 if ($this->image_rotate == 90) {
3976 imagecopy($tmp, $image_dst, $y, $x, $x, $this->image_dst_y - $y - 1, 1, 1);
3977 } else if ($this->image_rotate == 180) {
3978 imagecopy($tmp, $image_dst, $x, $y, $this->image_dst_x - $x - 1, $this->image_dst_y - $y - 1, 1, 1);
3979 } else if ($this->image_rotate == 270) {
3980 imagecopy($tmp, $image_dst, $y, $x, $this->image_dst_x - $x - 1, $y, 1, 1);
3981 } else {
3982 imagecopy($tmp, $image_dst, $x, $y, $x, $y, 1, 1);
3983 }
3984 }
3985 }
3986 if ($this->image_rotate == 90 || $this->image_rotate == 270) {
3987 $t = $this->image_dst_y;
3988 $this->image_dst_y = $this->image_dst_x;
3989 $this->image_dst_x = $t;
3990 }
3991 // we transfert tmp into image_dst
3992 $image_dst = $this->imagetransfer($tmp, $image_dst);
3993 }
3994 }
3995
3996 // pixelate image
3997 if ((is_numeric($this->image_pixelate) && $this->image_pixelate > 0)) {
3998 $this->log .= '- pixelate image (' . $this->image_pixelate . 'px)<br />';
3999 $filter = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
4000 if ($gd_version >= 2) {
4001 imagecopyresampled($filter, $image_dst, 0, 0, 0, 0, round($this->image_dst_x / $this->image_pixelate), round($this->image_dst_y / $this->image_pixelate), $this->image_dst_x, $this->image_dst_y);
4002 imagecopyresampled($image_dst, $filter, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, round($this->image_dst_x / $this->image_pixelate), round($this->image_dst_y / $this->image_pixelate));
4003 } else {
4004 imagecopyresized($filter, $image_dst, 0, 0, 0, 0, round($this->image_dst_x / $this->image_pixelate), round($this->image_dst_y / $this->image_pixelate), $this->image_dst_x, $this->image_dst_y);
4005 imagecopyresized($image_dst, $filter, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, round($this->image_dst_x / $this->image_pixelate), round($this->image_dst_y / $this->image_pixelate));
4006 }
4007 $this->imageunset($filter);
4008 }
4009
4010 // unsharp mask
4011 if ($gd_version >= 2 && $this->image_unsharp && is_numeric($this->image_unsharp_amount) && is_numeric($this->image_unsharp_radius) && is_numeric($this->image_unsharp_threshold)) {
4012 // Unsharp Mask for PHP - version 2.1.1
4013 // Unsharp mask algorithm by Torstein Hønsi 2003-07.
4014 // Used with permission
4015 // Modified to support alpha transparency
4016 if ($this->image_unsharp_amount > 500) $this->image_unsharp_amount = 500;
4017 $this->image_unsharp_amount = $this->image_unsharp_amount * 0.016;
4018 if ($this->image_unsharp_radius > 50) $this->image_unsharp_radius = 50;
4019 $this->image_unsharp_radius = $this->image_unsharp_radius * 2;
4020 if ($this->image_unsharp_threshold > 255) $this->image_unsharp_threshold = 255;
4021 $this->image_unsharp_radius = abs(round($this->image_unsharp_radius));
4022 if ($this->image_unsharp_radius != 0) {
4023 $this->image_dst_x = imagesx($image_dst); $this->image_dst_y = imagesy($image_dst);
4024 $canvas = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y, false, true);
4025 $blur = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y, false, true);
4026 if ($this->function_enabled('imageconvolution')) { // PHP >= 5.1
4027 $matrix = array(array( 1, 2, 1 ), array( 2, 4, 2 ), array( 1, 2, 1 ));
4028 imagecopy($blur, $image_dst, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y);
4029 imageconvolution($blur, $matrix, 16, 0);
4030 } else {
4031 for ($i = 0; $i < $this->image_unsharp_radius; $i++) {
4032 imagecopy($blur, $image_dst, 0, 0, 1, 0, $this->image_dst_x - 1, $this->image_dst_y); // left
4033 $this->imagecopymergealpha($blur, $image_dst, 1, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, 50); // right
4034 $this->imagecopymergealpha($blur, $image_dst, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, 50); // center
4035 imagecopy($canvas, $blur, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y);
4036 $this->imagecopymergealpha($blur, $canvas, 0, 0, 0, 1, $this->image_dst_x, $this->image_dst_y - 1, 33.33333 ); // up
4037 $this->imagecopymergealpha($blur, $canvas, 0, 1, 0, 0, $this->image_dst_x, $this->image_dst_y, 25); // down
4038 }
4039 }
4040 $p_new = array();
4041 if($this->image_unsharp_threshold>0) {
4042 for ($x = 0; $x < $this->image_dst_x-1; $x++) {
4043 for ($y = 0; $y < $this->image_dst_y; $y++) {
4044 $p_orig = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4045 $p_blur = imagecolorsforindex($blur, imagecolorat($blur, $x, $y));
4046 $p_new['red'] = (abs($p_orig['red'] - $p_blur['red']) >= $this->image_unsharp_threshold) ? max(0, min(255, ($this->image_unsharp_amount * ($p_orig['red'] - $p_blur['red'])) + $p_orig['red'])) : $p_orig['red'];
4047 $p_new['green'] = (abs($p_orig['green'] - $p_blur['green']) >= $this->image_unsharp_threshold) ? max(0, min(255, ($this->image_unsharp_amount * ($p_orig['green'] - $p_blur['green'])) + $p_orig['green'])) : $p_orig['green'];
4048 $p_new['blue'] = (abs($p_orig['blue'] - $p_blur['blue']) >= $this->image_unsharp_threshold) ? max(0, min(255, ($this->image_unsharp_amount * ($p_orig['blue'] - $p_blur['blue'])) + $p_orig['blue'])) : $p_orig['blue'];
4049 $p_new['alpha'] = max(-127, min(127, $p_orig['alpha']));
4050 if (($p_orig['red'] != $p_new['red']) || ($p_orig['green'] != $p_new['green']) || ($p_orig['blue'] != $p_new['blue'])) {
4051 $color = imagecolorallocatealpha($image_dst, (int) $p_new['red'], (int) $p_new['green'], (int) $p_new['blue'], (int) $p_new['alpha']);
4052 imagesetpixel($image_dst, $x, $y, $color);
4053 }
4054 }
4055 }
4056 } else {
4057 for ($x = 0; $x < $this->image_dst_x; $x++) {
4058 for ($y = 0; $y < $this->image_dst_y; $y++) {
4059 $p_orig = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4060 $p_blur = imagecolorsforindex($blur, imagecolorat($blur, $x, $y));
4061 $p_new['red'] = ($this->image_unsharp_amount * ($p_orig['red'] - $p_blur['red'])) + $p_orig['red'];
4062 if ($p_new['red']>255) { $p_new['red']=255; } elseif ($p_new['red']<0) { $p_new['red']=0; }
4063 $p_new['green'] = ($this->image_unsharp_amount * ($p_orig['green'] - $p_blur['green'])) + $p_orig['green'];
4064 if ($p_new['green']>255) { $p_new['green']=255; } elseif ($p_new['green']<0) { $p_new['green']=0; }
4065 $p_new['blue'] = ($this->image_unsharp_amount * ($p_orig['blue'] - $p_blur['blue'])) + $p_orig['blue'];
4066 if ($p_new['blue']>255) { $p_new['blue']=255; } elseif ($p_new['blue']<0) { $p_new['blue']=0; }
4067 $p_new['alpha'] = round(max(-127, min(127, $p_orig['alpha'])));
4068 $color = imagecolorallocatealpha($image_dst, (int) $p_new['red'], (int) $p_new['green'], (int) $p_new['blue'], (int) $p_new['alpha']);
4069 imagesetpixel($image_dst, $x, $y, $color);
4070 }
4071 }
4072 }
4073 $this->imageunset($canvas);
4074 $this->imageunset($blur);
4075 }
4076 }
4077
4078 // add color overlay
4079 if ($gd_version >= 2 && (is_numeric($this->image_overlay_opacity) && $this->image_overlay_opacity > 0 && !empty($this->image_overlay_color))) {
4080 $this->log .= '- apply color overlay<br />';
4081 list($red, $green, $blue) = $this->getcolors($this->image_overlay_color);
4082 $filter = imagecreatetruecolor($this->image_dst_x, $this->image_dst_y);
4083 $color = imagecolorallocate($filter, $red, $green, $blue);
4084 imagefilledrectangle($filter, 0, 0, $this->image_dst_x, $this->image_dst_y, $color);
4085 $this->imagecopymergealpha($image_dst, $filter, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y, $this->image_overlay_opacity);
4086 $this->imageunset($filter);
4087 }
4088
4089 // add brightness, contrast and tint, turns to greyscale and inverts colors
4090 if ($gd_version >= 2 && ($this->image_negative || $this->image_greyscale || is_numeric($this->image_threshold)|| is_numeric($this->image_brightness) || is_numeric($this->image_contrast) || !empty($this->image_tint_color))) {
4091 $this->log .= '- apply tint, light, contrast correction, negative, greyscale and threshold<br />';
4092 if (!empty($this->image_tint_color)) list($tint_red, $tint_green, $tint_blue) = $this->getcolors($this->image_tint_color);
4093 //imagealphablending($image_dst, true);
4094 for($y=0; $y < $this->image_dst_y; $y++) {
4095 for($x=0; $x < $this->image_dst_x; $x++) {
4096 if ($this->image_greyscale) {
4097 $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4098 $r = $g = $b = round((0.2125 * $pixel['red']) + (0.7154 * $pixel['green']) + (0.0721 * $pixel['blue']));
4099 $alpha = round(max(-127, min(127, $pixel['alpha'])));
4100 $color = imagecolorallocatealpha($image_dst, (int) $r, (int) $g, (int) $b, (int) $alpha);
4101 imagesetpixel($image_dst, $x, $y, $color);
4102 unset($color); unset($pixel);
4103 }
4104 if (is_numeric($this->image_threshold)) {
4105 $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4106 $c = (round($pixel['red'] + $pixel['green'] + $pixel['blue']) / 3) - 127;
4107 $r = $g = $b = ($c > $this->image_threshold ? 255 : 0);
4108 $alpha = round(max(-127, min(127, $pixel['alpha'])));
4109 $color = imagecolorallocatealpha($image_dst, (int) $r, (int) $g, (int) $b, (int) $alpha);
4110 imagesetpixel($image_dst, $x, $y, $color);
4111 unset($color); unset($pixel);
4112 }
4113 if (is_numeric($this->image_brightness)) {
4114 $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4115 $r = max(min(round($pixel['red'] + (($this->image_brightness * 2))), 255), 0);
4116 $g = max(min(round($pixel['green'] + (($this->image_brightness * 2))), 255), 0);
4117 $b = max(min(round($pixel['blue'] + (($this->image_brightness * 2))), 255), 0);
4118 $alpha = round(max(-127, min(127, $pixel['alpha'])));
4119 $color = imagecolorallocatealpha($image_dst, (int) $r, (int) $g, (int) $b, (int) $alpha);
4120 imagesetpixel($image_dst, $x, $y, $color);
4121 unset($color); unset($pixel);
4122 }
4123 if (is_numeric($this->image_contrast)) {
4124 $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4125 $r = max(min(round(($this->image_contrast + 128) * $pixel['red'] / 128), 255), 0);
4126 $g = max(min(round(($this->image_contrast + 128) * $pixel['green'] / 128), 255), 0);
4127 $b = max(min(round(($this->image_contrast + 128) * $pixel['blue'] / 128), 255), 0);
4128 $alpha = round(max(-127, min(127, $pixel['alpha'])));
4129 $color = imagecolorallocatealpha($image_dst, (int) $r, (int) $g, (int) $b, (int) $alpha);
4130 imagesetpixel($image_dst, $x, $y, $color);
4131 unset($color); unset($pixel);
4132 }
4133 if (!empty($this->image_tint_color)) {
4134 $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4135 $r = min(round($tint_red * $pixel['red'] / 169), 255);
4136 $g = min(round($tint_green * $pixel['green'] / 169), 255);
4137 $b = min(round($tint_blue * $pixel['blue'] / 169), 255);
4138 $alpha = round(max(-127, min(127, $pixel['alpha'])));
4139 $color = imagecolorallocatealpha($image_dst, (int) $r, (int) $g, (int) $b, (int) $alpha);
4140 imagesetpixel($image_dst, $x, $y, $color);
4141 unset($color); unset($pixel);
4142 }
4143 if (!empty($this->image_negative)) {
4144 $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4145 $r = round(255 - $pixel['red']);
4146 $g = round(255 - $pixel['green']);
4147 $b = round(255 - $pixel['blue']);
4148 $alpha = round(max(-127, min(127, $pixel['alpha'])));
4149 $color = imagecolorallocatealpha($image_dst, (int) $r, (int) $g, (int) $b, (int) $alpha);
4150 imagesetpixel($image_dst, $x, $y, $color);
4151 unset($color); unset($pixel);
4152 }
4153 }
4154 }
4155 }
4156
4157 // adds a border
4158 if ($gd_version >= 2 && !empty($this->image_border)) {
4159 list($ct, $cr, $cb, $cl) = $this->getoffsets($this->image_border, $this->image_dst_x, $this->image_dst_y, true, false);
4160 $this->log .= '- add border : ' . $ct . ' ' . $cr . ' ' . $cb . ' ' . $cl . '<br />';
4161 $this->image_dst_x = $this->image_dst_x + $cl + $cr;
4162 $this->image_dst_y = $this->image_dst_y + $ct + $cb;
4163 if (!empty($this->image_border_color)) list($red, $green, $blue) = $this->getcolors($this->image_border_color);
4164 $opacity = (is_numeric($this->image_border_opacity) ? (int) (127 - $this->image_border_opacity / 100 * 127): 0);
4165 // we now create an image, that we fill with the border color
4166 $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
4167 $background = imagecolorallocatealpha($tmp, $red, $green, $blue, $opacity);
4168 imagefilledrectangle($tmp, 0, 0, $this->image_dst_x, $this->image_dst_y, $background);
4169 // we then copy the source image into the new image, without merging so that only the border is actually kept
4170 imagecopy($tmp, $image_dst, $cl, $ct, 0, 0, $this->image_dst_x - $cr - $cl, $this->image_dst_y - $cb - $ct);
4171 // we transfert tmp into image_dst
4172 $image_dst = $this->imagetransfer($tmp, $image_dst);
4173 }
4174
4175 // adds a fading-to-transparent border
4176 if ($gd_version >= 2 && !empty($this->image_border_transparent)) {
4177 list($ct, $cr, $cb, $cl) = $this->getoffsets($this->image_border_transparent, $this->image_dst_x, $this->image_dst_y, true, false);
4178 $this->log .= '- add transparent border : ' . $ct . ' ' . $cr . ' ' . $cb . ' ' . $cl . '<br />';
4179 // we now create an image, that we fill with the border color
4180 $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
4181 // we then copy the source image into the new image, without the borders
4182 imagecopy($tmp, $image_dst, $cl, $ct, $cl, $ct, $this->image_dst_x - $cr - $cl, $this->image_dst_y - $cb - $ct);
4183 // we now add the top border
4184 $opacity = 100;
4185 for ($y = $ct - 1; $y >= 0; $y--) {
4186 $il = (int) ($ct > 0 ? ($cl * ($y / $ct)) : 0);
4187 $ir = (int) ($ct > 0 ? ($cr * ($y / $ct)) : 0);
4188 for ($x = $il; $x < $this->image_dst_x - $ir; $x++) {
4189 $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4190 $alpha = (1 - ($pixel['alpha'] / 127)) * $opacity / 100;
4191 if ($alpha > 0) {
4192 if ($alpha > 1) $alpha = 1;
4193 $color = imagecolorallocatealpha($tmp, $pixel['red'] , $pixel['green'], $pixel['blue'], round((1 - $alpha) * 127));
4194 imagesetpixel($tmp, $x, $y, $color);
4195 }
4196 }
4197 if ($opacity > 0) $opacity = $opacity - (100 / $ct);
4198 }
4199 // we now add the right border
4200 $opacity = 100;
4201 for ($x = $this->image_dst_x - $cr; $x < $this->image_dst_x; $x++) {
4202 $it = (int) ($cr > 0 ? ($ct * (($this->image_dst_x - $x - 1) / $cr)) : 0);
4203 $ib = (int) ($cr > 0 ? ($cb * (($this->image_dst_x - $x - 1) / $cr)) : 0);
4204 for ($y = $it; $y < $this->image_dst_y - $ib; $y++) {
4205 $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4206 $alpha = (1 - ($pixel['alpha'] / 127)) * $opacity / 100;
4207 if ($alpha > 0) {
4208 if ($alpha > 1) $alpha = 1;
4209 $color = imagecolorallocatealpha($tmp, $pixel['red'] , $pixel['green'], $pixel['blue'], round((1 - $alpha) * 127));
4210 imagesetpixel($tmp, $x, $y, $color);
4211 }
4212 }
4213 if ($opacity > 0) $opacity = $opacity - (100 / $cr);
4214 }
4215 // we now add the bottom border
4216 $opacity = 100;
4217 for ($y = $this->image_dst_y - $cb; $y < $this->image_dst_y; $y++) {
4218 $il = (int) ($cb > 0 ? ($cl * (($this->image_dst_y - $y - 1) / $cb)) : 0);
4219 $ir = (int) ($cb > 0 ? ($cr * (($this->image_dst_y - $y - 1) / $cb)) : 0);
4220 for ($x = $il; $x < $this->image_dst_x - $ir; $x++) {
4221 $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4222 $alpha = (1 - ($pixel['alpha'] / 127)) * $opacity / 100;
4223 if ($alpha > 0) {
4224 if ($alpha > 1) $alpha = 1;
4225 $color = imagecolorallocatealpha($tmp, $pixel['red'] , $pixel['green'], $pixel['blue'], round((1 - $alpha) * 127));
4226 imagesetpixel($tmp, $x, $y, $color);
4227 }
4228 }
4229 if ($opacity > 0) $opacity = $opacity - (100 / $cb);
4230 }
4231 // we now add the left border
4232 $opacity = 100;
4233 for ($x = $cl - 1; $x >= 0; $x--) {
4234 $it = (int) ($cl > 0 ? ($ct * ($x / $cl)) : 0);
4235 $ib = (int) ($cl > 0 ? ($cb * ($x / $cl)) : 0);
4236 for ($y = $it; $y < $this->image_dst_y - $ib; $y++) {
4237 $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4238 $alpha = (1 - ($pixel['alpha'] / 127)) * $opacity / 100;
4239 if ($alpha > 0) {
4240 if ($alpha > 1) $alpha = 1;
4241 $color = imagecolorallocatealpha($tmp, $pixel['red'] , $pixel['green'], $pixel['blue'], round((1 - $alpha) * 127));
4242 imagesetpixel($tmp, $x, $y, $color);
4243 }
4244 }
4245 if ($opacity > 0) $opacity = $opacity - (100 / $cl);
4246 }
4247 // we transfert tmp into image_dst
4248 $image_dst = $this->imagetransfer($tmp, $image_dst);
4249 }
4250
4251 // add frame border
4252 if ($gd_version >= 2 && is_numeric($this->image_frame)) {
4253 if (is_array($this->image_frame_colors)) {
4255 $this->log .= '- add frame : ' . implode(' ', $this->image_frame_colors) . '<br />';
4256 } else {
4257 $this->log .= '- add frame : ' . $this->image_frame_colors . '<br />';
4258 $vars = explode(' ', $this->image_frame_colors);
4259 }
4260 $nb = sizeof($vars);
4261 $this->image_dst_x = $this->image_dst_x + ($nb * 2);
4262 $this->image_dst_y = $this->image_dst_y + ($nb * 2);
4263 $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
4264 imagecopy($tmp, $image_dst, $nb, $nb, 0, 0, $this->image_dst_x - ($nb * 2), $this->image_dst_y - ($nb * 2));
4265 $opacity = (is_numeric($this->image_frame_opacity) ? (int) (127 - $this->image_frame_opacity / 100 * 127): 0);
4266 for ($i=0; $i<$nb; $i++) {
4267 list($red, $green, $blue) = $this->getcolors($vars[$i]);
4268 $c = imagecolorallocatealpha($tmp, $red, $green, $blue, $opacity);
4269 if ($this->image_frame == 1) {
4270 imageline($tmp, $i, $i, $this->image_dst_x - $i -1, $i, $c);
4271 imageline($tmp, $this->image_dst_x - $i -1, $this->image_dst_y - $i -1, $this->image_dst_x - $i -1, $i, $c);
4272 imageline($tmp, $this->image_dst_x - $i -1, $this->image_dst_y - $i -1, $i, $this->image_dst_y - $i -1, $c);
4273 imageline($tmp, $i, $i, $i, $this->image_dst_y - $i -1, $c);
4274 } else {
4275 imageline($tmp, $i, $i, $this->image_dst_x - $i -1, $i, $c);
4276 imageline($tmp, $this->image_dst_x - $nb + $i, $this->image_dst_y - $nb + $i, $this->image_dst_x - $nb + $i, $nb - $i, $c);
4277 imageline($tmp, $this->image_dst_x - $nb + $i, $this->image_dst_y - $nb + $i, $nb - $i, $this->image_dst_y - $nb + $i, $c);
4278 imageline($tmp, $i, $i, $i, $this->image_dst_y - $i -1, $c);
4279 }
4280 }
4281 // we transfert tmp into image_dst
4282 $image_dst = $this->imagetransfer($tmp, $image_dst);
4283 }
4284
4285 // add bevel border
4286 if ($gd_version >= 2 && $this->image_bevel > 0) {
4287 if (empty($this->image_bevel_color1)) $this->image_bevel_color1 = '#FFFFFF';
4288 if (empty($this->image_bevel_color2)) $this->image_bevel_color2 = '#000000';
4289 list($red1, $green1, $blue1) = $this->getcolors($this->image_bevel_color1);
4290 list($red2, $green2, $blue2) = $this->getcolors($this->image_bevel_color2);
4291 $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y);
4292 imagecopy($tmp, $image_dst, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y);
4293 imagealphablending($tmp, true);
4294 for ($i=0; $i<$this->image_bevel; $i++) {
4295 $alpha = round(($i / $this->image_bevel) * 127);
4296 $c1 = imagecolorallocatealpha($tmp, $red1, $green1, $blue1, $alpha);
4297 $c2 = imagecolorallocatealpha($tmp, $red2, $green2, $blue2, $alpha);
4298 imageline($tmp, $i, $i, $this->image_dst_x - $i -1, $i, $c1);
4299 imageline($tmp, $this->image_dst_x - $i -1, $this->image_dst_y - $i, $this->image_dst_x - $i -1, $i, $c2);
4300 imageline($tmp, $this->image_dst_x - $i -1, $this->image_dst_y - $i -1, $i, $this->image_dst_y - $i -1, $c2);
4301 imageline($tmp, $i, $i, $i, $this->image_dst_y - $i -1, $c1);
4302 }
4303 // we transfert tmp into image_dst
4304 $image_dst = $this->imagetransfer($tmp, $image_dst);
4305 }
4306
4307 // add watermark image
4308 if ($this->image_watermark!='' && file_exists($this->image_watermark)) {
4309 $this->log .= '- add watermark<br />';
4310 $this->image_watermark_position = strtolower((string) $this->image_watermark_position);
4311 $watermark_info = getimagesize($this->image_watermark);
4312 $watermark_type = (array_key_exists(2, $watermark_info) ? $watermark_info[2] : null); // 1 = GIF, 2 = JPG, 3 = PNG
4313 $watermark_checked = false;
4314 if ($watermark_type == IMAGETYPE_GIF) {
4315 if (!$this->function_enabled('imagecreatefromgif')) {
4316 $this->error = $this->translate('watermark_no_create_support', array('GIF'));
4317 } else {
4318 $filter = @imagecreatefromgif($this->image_watermark);
4319 if (!$filter) {
4320 $this->error = $this->translate('watermark_create_error', array('GIF'));
4321 } else {
4322 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;watermark source image is GIF<br />';
4323 $watermark_checked = true;
4324 }
4325 }
4326 } else if ($watermark_type == IMAGETYPE_JPEG) {
4327 if (!$this->function_enabled('imagecreatefromjpeg')) {
4328 $this->error = $this->translate('watermark_no_create_support', array('JPEG'));
4329 } else {
4330 $filter = @imagecreatefromjpeg($this->image_watermark);
4331 if (!$filter) {
4332 $this->error = $this->translate('watermark_create_error', array('JPEG'));
4333 } else {
4334 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;watermark source image is JPEG<br />';
4335 $watermark_checked = true;
4336 }
4337 }
4338 } else if ($watermark_type == IMAGETYPE_PNG) {
4339 if (!$this->function_enabled('imagecreatefrompng')) {
4340 $this->error = $this->translate('watermark_no_create_support', array('PNG'));
4341 } else {
4342 $filter = @imagecreatefrompng($this->image_watermark);
4343 if (!$filter) {
4344 $this->error = $this->translate('watermark_create_error', array('PNG'));
4345 } else {
4346 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;watermark source image is PNG<br />';
4347 $watermark_checked = true;
4348 }
4349 }
4350 } else if ($watermark_type == IMAGETYPE_WEBP) {
4351 if (!$this->function_enabled('imagecreatefromwebp')) {
4352 $this->error = $this->translate('watermark_no_create_support', array('WEBP'));
4353 } else {
4354 $filter = @imagecreatefromwebp($this->image_watermark);
4355 if (!$filter) {
4356 $this->error = $this->translate('watermark_create_error', array('WEBP'));
4357 } else {
4358 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;watermark source image is WEBP<br />';
4359 $watermark_checked = true;
4360 }
4361 }
4362 } else if ($watermark_type == IMAGETYPE_BMP) {
4363 if (!method_exists($this, 'imagecreatefrombmp')) {
4364 $this->error = $this->translate('watermark_no_create_support', array('BMP'));
4365 } else {
4366 $filter = @$this->imagecreatefrombmp($this->image_watermark);
4367 if (!$filter) {
4368 $this->error = $this->translate('watermark_create_error', array('BMP'));
4369 } else {
4370 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;watermark source image is BMP<br />';
4371 $watermark_checked = true;
4372 }
4373 }
4374 } else {
4375 $this->error = $this->translate('watermark_invalid');
4376 }
4377 if ($watermark_checked) {
4378 $watermark_dst_width = $watermark_src_width = imagesx($filter);
4379 $watermark_dst_height = $watermark_src_height = imagesy($filter);
4380
4381 // if watermark is too large/tall, resize it first
4382 if ((!$this->image_watermark_no_zoom_out && ($watermark_dst_width > $this->image_dst_x || $watermark_dst_height > $this->image_dst_y))
4383 || (!$this->image_watermark_no_zoom_in && $watermark_dst_width < $this->image_dst_x && $watermark_dst_height < $this->image_dst_y)) {
4384 $canvas_width = $this->image_dst_x - abs((int) $this->image_watermark_x);
4385 $canvas_height = $this->image_dst_y - abs((int) $this->image_watermark_y);
4386 if (($watermark_src_width/$canvas_width) > ($watermark_src_height/$canvas_height)) {
4387 $watermark_dst_width = $canvas_width;
4388 $watermark_dst_height = intval($watermark_src_height*($canvas_width / $watermark_src_width));
4389 } else {
4390 $watermark_dst_height = $canvas_height;
4391 $watermark_dst_width = intval($watermark_src_width*($canvas_height / $watermark_src_height));
4392 }
4393 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;watermark resized from '.$watermark_src_width.'x'.$watermark_src_height.' to '.$watermark_dst_width.'x'.$watermark_dst_height.'<br />';
4394
4395 }
4396 // determine watermark position
4397 $watermark_x = 0;
4398 $watermark_y = 0;
4399 if (is_numeric($this->image_watermark_x)) {
4400 if ($this->image_watermark_x < 0) {
4401 $watermark_x = $this->image_dst_x - $watermark_dst_width + $this->image_watermark_x;
4402 } else {
4403 $watermark_x = $this->image_watermark_x;
4404 }
4405 } else {
4406 if (strpos($this->image_watermark_position, 'r') !== false) {
4407 $watermark_x = $this->image_dst_x - $watermark_dst_width;
4408 } else if (strpos($this->image_watermark_position, 'l') !== false) {
4409 $watermark_x = 0;
4410 } else {
4411 $watermark_x = ($this->image_dst_x - $watermark_dst_width) / 2;
4412 }
4413 }
4414 if (is_numeric($this->image_watermark_y)) {
4415 if ($this->image_watermark_y < 0) {
4416 $watermark_y = $this->image_dst_y - $watermark_dst_height + $this->image_watermark_y;
4417 } else {
4418 $watermark_y = $this->image_watermark_y;
4419 }
4420 } else {
4421 if (strpos($this->image_watermark_position, 'b') !== false) {
4422 $watermark_y = $this->image_dst_y - $watermark_dst_height;
4423 } else if (strpos($this->image_watermark_position, 't') !== false) {
4424 $watermark_y = 0;
4425 } else {
4426 $watermark_y = ($this->image_dst_y - $watermark_dst_height) / 2;
4427 }
4428 }
4429 imagealphablending($image_dst, true);
4430 imagecopyresampled($image_dst, $filter, $watermark_x, $watermark_y, 0, 0, $watermark_dst_width, $watermark_dst_height, $watermark_src_width, $watermark_src_height);
4431 } else {
4432 $this->error = $this->translate('watermark_invalid');
4433 }
4434 }
4435
4436 // add text
4437 if (!empty($this->image_text)) {
4438 $this->log .= '- add text<br />';
4439
4440 // calculate sizes in human readable format
4441 $src_size = $this->file_src_size / 1024;
4442 $src_size_mb = number_format($src_size / 1024, 1, ".", " ");
4443 $src_size_kb = number_format($src_size, 1, ".", " ");
4444 $src_size_human = ($src_size > 1024 ? $src_size_mb . " MB" : $src_size_kb . " kb");
4445
4446 $this->image_text = str_replace(
4447 array('[src_name]',
4448 '[src_name_body]',
4449 '[src_name_ext]',
4450 '[src_pathname]',
4451 '[src_mime]',
4452 '[src_size]',
4453 '[src_size_kb]',
4454 '[src_size_mb]',
4455 '[src_size_human]',
4456 '[src_x]',
4457 '[src_y]',
4458 '[src_pixels]',
4459 '[src_type]',
4460 '[src_bits]',
4461 '[dst_path]',
4462 '[dst_name_body]',
4463 '[dst_name_ext]',
4464 '[dst_name]',
4465 '[dst_pathname]',
4466 '[dst_x]',
4467 '[dst_y]',
4468 '[date]',
4469 '[time]',
4470 '[host]',
4471 '[server]',
4472 '[ip]',
4473 '[gd_version]'),
4474 array($this->file_src_name,
4475 $this->file_src_name_body,
4476 $this->file_src_name_ext,
4477 $this->file_src_pathname,
4478 $this->file_src_mime,
4479 $this->file_src_size,
4480 $src_size_kb,
4481 $src_size_mb,
4482 $src_size_human,
4483 $this->image_src_x,
4484 $this->image_src_y,
4485 $this->image_src_pixels,
4486 $this->image_src_type,
4487 $this->image_src_bits,
4488 $this->file_dst_path,
4489 $this->file_dst_name_body,
4490 $this->file_dst_name_ext,
4491 $this->file_dst_name,
4492 $this->file_dst_pathname,
4493 $this->image_dst_x,
4494 $this->image_dst_y,
4495 date('Y-m-d'),
4496 date('H:i:s'),
4497 (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'n/a'),
4498 (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'n/a'),
4499 (isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : 'n/a'),
4500 $this->gdversion(true)),
4501 $this->image_text);
4502
4503 if (!is_numeric($this->image_text_padding)) $this->image_text_padding = 0;
4504 if (!is_numeric($this->image_text_line_spacing)) $this->image_text_line_spacing = 0;
4505 if (!is_numeric($this->image_text_padding_x)) $this->image_text_padding_x = $this->image_text_padding;
4506 if (!is_numeric($this->image_text_padding_y)) $this->image_text_padding_y = $this->image_text_padding;
4507 $this->image_text_position = strtolower((string) $this->image_text_position);
4508 $this->image_text_direction = strtolower((string) $this->image_text_direction);
4509 $this->image_text_alignment = strtolower((string) $this->image_text_alignment);
4510
4511 $font_type = 'gd';
4512
4513 // if the font is a string with a GDF font path, we assume that we might want to load a font
4514 if (!is_numeric($this->image_text_font) && strlen($this->image_text_font) > 4 && substr(strtolower($this->image_text_font), -4) == '.gdf') {
4515 if (strpos($this->image_text_font, '/') === false) $this->image_text_font = "./" . $this->image_text_font;
4516 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;try to load font ' . $this->image_text_font . '... ';
4517 if ($this->image_text_font = @imageloadfont($this->image_text_font)) {
4518 $this->log .= 'success<br />';
4519 } else {
4520 $this->log .= 'error<br />';
4521 $this->image_text_font = 5;
4522 }
4523
4524 // if the font is a string with a TTF font path, we check if we can access the font file
4525 } else if (!is_numeric($this->image_text_font) && strlen($this->image_text_font) > 4 && substr(strtolower($this->image_text_font), -4) == '.ttf') {
4526 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;try to load font ' . $this->image_text_font . '... ';
4527 if (strpos($this->image_text_font, '/') === false) $this->image_text_font = "./" . $this->image_text_font;
4528 if (file_exists($this->image_text_font) && is_readable($this->image_text_font)) {
4529 $this->log .= 'success<br />';
4530 $font_type = 'tt';
4531 } else {
4532 $this->log .= 'error<br />';
4533 $this->image_text_font = 5;
4534 }
4535 }
4536
4537 // get the text bounding box (GD fonts)
4538 if ($font_type == 'gd') {
4539 $text = explode("\n", $this->image_text);
4540 $char_width = imagefontwidth($this->image_text_font);
4541 $char_height = imagefontheight($this->image_text_font);
4542 $text_height = 0;
4543 $text_width = 0;
4544 $line_height = 0;
4545 $line_width = 0;
4546 foreach ($text as $k => $v) {
4547 if ($this->image_text_direction == 'v') {
4548 $h = ($char_width * strlen($v));
4549 if ($h > $text_height) $text_height = $h;
4550 $line_width = $char_height;
4551 $text_width += $line_width + ($k < (sizeof($text)-1) ? $this->image_text_line_spacing : 0);
4552 } else {
4553 $w = ($char_width * strlen($v));
4554 if ($w > $text_width) $text_width = $w;
4555 $line_height = $char_height;
4556 $text_height += $line_height + ($k < (sizeof($text)-1) ? $this->image_text_line_spacing : 0);
4557 }
4558 }
4559 $text_width += (2 * $this->image_text_padding_x);
4560 $text_height += (2 * $this->image_text_padding_y);
4561
4562 // get the text bounding box (TrueType fonts)
4563 } else if ($font_type == 'tt') {
4564 $text = $this->image_text;
4565 if (!$this->image_text_angle) $this->image_text_angle = $this->image_text_direction == 'v' ? 90 : 0;
4566 $text_height = 0;
4567 $text_width = 0;
4568 $text_offset_x = 0;
4569 $text_offset_y = 0;
4570 $rect = imagettfbbox($this->image_text_size, $this->image_text_angle, $this->image_text_font, $text );
4571 if ($rect) {
4572 $minX = min(array($rect[0],$rect[2],$rect[4],$rect[6]));
4573 $maxX = max(array($rect[0],$rect[2],$rect[4],$rect[6]));
4574 $minY = min(array($rect[1],$rect[3],$rect[5],$rect[7]));
4575 $maxY = max(array($rect[1],$rect[3],$rect[5],$rect[7]));
4576 $text_offset_x = abs($minX);
4577 $text_offset_y = abs($minY);
4578 $text_width = $maxX - $minX + (2 * $this->image_text_padding_x);
4579 $text_height = $maxY - $minY + (2 * $this->image_text_padding_y);
4580 }
4581 }
4582
4583 // position the text block
4584 $text_x = 0;
4585 $text_y = 0;
4586 if (is_numeric($this->image_text_x)) {
4587 if ($this->image_text_x < 0) {
4588 $text_x = $this->image_dst_x - $text_width + $this->image_text_x;
4589 } else {
4590 $text_x = $this->image_text_x;
4591 }
4592 } else {
4593 if (strpos($this->image_text_position, 'r') !== false) {
4594 $text_x = $this->image_dst_x - $text_width;
4595 } else if (strpos($this->image_text_position, 'l') !== false) {
4596 $text_x = 0;
4597 } else {
4598 $text_x = ($this->image_dst_x - $text_width) / 2;
4599 }
4600 }
4601 if (is_numeric($this->image_text_y)) {
4602 if ($this->image_text_y < 0) {
4603 $text_y = $this->image_dst_y - $text_height + $this->image_text_y;
4604 } else {
4605 $text_y = $this->image_text_y;
4606 }
4607 } else {
4608 if (strpos($this->image_text_position, 'b') !== false) {
4609 $text_y = $this->image_dst_y - $text_height;
4610 } else if (strpos($this->image_text_position, 't') !== false) {
4611 $text_y = 0;
4612 } else {
4613 $text_y = ($this->image_dst_y - $text_height) / 2;
4614 }
4615 }
4616
4617 // add a background, maybe transparent
4618 if (!empty($this->image_text_background)) {
4619 list($red, $green, $blue) = $this->getcolors($this->image_text_background);
4620 if ($gd_version >= 2 && (is_numeric($this->image_text_background_opacity)) && $this->image_text_background_opacity >= 0 && $this->image_text_background_opacity <= 100) {
4621 $filter = imagecreatetruecolor($text_width, $text_height);
4622 $background_color = imagecolorallocate($filter, $red, $green, $blue);
4623 imagefilledrectangle($filter, 0, 0, $text_width, $text_height, $background_color);
4624 $this->imagecopymergealpha($image_dst, $filter, $text_x, $text_y, 0, 0, $text_width, $text_height, $this->image_text_background_opacity);
4625 $this->imageunset($filter);
4626 } else {
4627 $background_color = imagecolorallocate($image_dst ,$red, $green, $blue);
4628 imagefilledrectangle($image_dst, $text_x, $text_y, $text_x + $text_width, $text_y + $text_height, $background_color);
4629 }
4630 }
4631
4632 $text_x += $this->image_text_padding_x;
4633 $text_y += $this->image_text_padding_y;
4634 $t_width = $text_width - (2 * $this->image_text_padding_x);
4635 $t_height = $text_height - (2 * $this->image_text_padding_y);
4636 list($red, $green, $blue) = $this->getcolors($this->image_text_color);
4637
4638 // add the text, maybe transparent
4639 if ($gd_version >= 2 && (is_numeric($this->image_text_opacity)) && $this->image_text_opacity >= 0 && $this->image_text_opacity <= 100) {
4640 if ($t_width < 0) $t_width = 0;
4641 if ($t_height < 0) $t_height = 0;
4642 $filter = $this->imagecreatenew($t_width, $t_height, false, true);
4643 $text_color = imagecolorallocate($filter ,$red, $green, $blue);
4644
4645 if ($font_type == 'gd') {
4646 foreach ($text as $k => $v) {
4647 if ($this->image_text_direction == 'v') {
4648 imagestringup($filter,
4649 $this->image_text_font,
4650 (int) ($k * ($line_width + ($k > 0 && $k < (sizeof($text)) ? $this->image_text_line_spacing : 0))),
4651 (int) ($text_height - (2 * $this->image_text_padding_y) - ($this->image_text_alignment == 'l' ? 0 : (($t_height - strlen($v) * $char_width) / ($this->image_text_alignment == 'r' ? 1 : 2)))),
4652 $v,
4653 $text_color);
4654 } else {
4655 imagestring($filter,
4656 $this->image_text_font,
4657 (int) ($this->image_text_alignment == 'l' ? 0 : (($t_width - strlen($v) * $char_width) / ($this->image_text_alignment == 'r' ? 1 : 2))),
4658 (int) ($k * ($line_height + ($k > 0 && $k < (sizeof($text)) ? $this->image_text_line_spacing : 0))),
4659 $v,
4660 $text_color);
4661 }
4662 }
4663 } else if ($font_type == 'tt') {
4664 imagettftext($filter,
4665 $this->image_text_size,
4666 $this->image_text_angle,
4667 $text_offset_x,
4668 $text_offset_y,
4669 $text_color,
4670 $this->image_text_font,
4671 $text);
4672 }
4673 $this->imagecopymergealpha($image_dst, $filter, $text_x, $text_y, 0, 0, $t_width, $t_height, $this->image_text_opacity);
4674 $this->imageunset($filter);
4675
4676 } else {
4677 $text_color = imagecolorallocate($image_dst ,$red, $green, $blue);
4678 if ($font_type == 'gd') {
4679 foreach ($text as $k => $v) {
4680 if ($this->image_text_direction == 'v') {
4681 imagestringup($image_dst,
4682 $this->image_text_font,
4683 $text_x + $k * ($line_width + ($k > 0 && $k < (sizeof($text)) ? $this->image_text_line_spacing : 0)),
4684 $text_y + $text_height - (2 * $this->image_text_padding_y) - ($this->image_text_alignment == 'l' ? 0 : (($t_height - strlen($v) * $char_width) / ($this->image_text_alignment == 'r' ? 1 : 2))),
4685 $v,
4686 $text_color);
4687 } else {
4688 imagestring($image_dst,
4689 $this->image_text_font,
4690 $text_x + ($this->image_text_alignment == 'l' ? 0 : (($t_width - strlen($v) * $char_width) / ($this->image_text_alignment == 'r' ? 1 : 2))),
4691 $text_y + $k * ($line_height + ($k > 0 && $k < (sizeof($text)) ? $this->image_text_line_spacing : 0)),
4692 $v,
4693 $text_color);
4694 }
4695 }
4696 } else if ($font_type == 'tt') {
4697 imagettftext($image_dst,
4698 $this->image_text_size,
4699 $this->image_text_angle,
4700 $text_offset_x + ($this->image_dst_x / 2) - ($text_width / 2) + $this->image_text_padding_x,
4701 $text_offset_y + ($this->image_dst_y / 2) - ($text_height / 2) + $this->image_text_padding_y,
4702 $text_color,
4703 $this->image_text_font,
4704 $text);
4705 }
4706 }
4707 }
4708
4709 // add a reflection
4710 if ($this->image_reflection_height) {
4711 $this->log .= '- add reflection : ' . $this->image_reflection_height . '<br />';
4712 // we decode image_reflection_height, which can be a integer, a string in pixels or percentage
4714 if (strpos($image_reflection_height, '%')>0) $image_reflection_height = $this->image_dst_y * ((int) str_replace('%','',$image_reflection_height) / 100);
4715 if (strpos($image_reflection_height, 'px')>0) $image_reflection_height = (int) str_replace('px','',$image_reflection_height);
4718 if (empty($this->image_reflection_opacity)) $this->image_reflection_opacity = 60;
4719 // create the new destination image
4720 $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y + $image_reflection_height + $this->image_reflection_space, true);
4721 $transparency = $this->image_reflection_opacity;
4722
4723 // copy the original image
4724 imagecopy($tmp, $image_dst, 0, 0, 0, 0, $this->image_dst_x, $this->image_dst_y + ($this->image_reflection_space < 0 ? $this->image_reflection_space : 0));
4725
4726 // we have to make sure the extra bit is the right color, or transparent
4727 if ($image_reflection_height + $this->image_reflection_space > 0) {
4728 // use the background color if present
4729 if (!empty($this->image_background_color)) {
4730 list($red, $green, $blue) = $this->getcolors($this->image_background_color);
4731 $fill = imagecolorallocate($tmp, $red, $green, $blue);
4732 } else {
4733 $fill = imagecolorallocatealpha($tmp, 0, 0, 0, 127);
4734 }
4735 // fill in from the edge of the extra bit
4736 imagefill($tmp, round($this->image_dst_x / 2), $this->image_dst_y + $image_reflection_height + $this->image_reflection_space - 1, $fill);
4737 }
4738
4739 // copy the reflection
4740 for ($y = 0; $y < $image_reflection_height; $y++) {
4741 for ($x = 0; $x < $this->image_dst_x; $x++) {
4742 $pixel_b = imagecolorsforindex($tmp, imagecolorat($tmp, $x, $y + $this->image_dst_y + $this->image_reflection_space));
4743 $pixel_o = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $this->image_dst_y - $y - 1 + ($this->image_reflection_space < 0 ? $this->image_reflection_space : 0)));
4744 $alpha_o = 1 - ($pixel_o['alpha'] / 127);
4745 $alpha_b = 1 - ($pixel_b['alpha'] / 127);
4746 $opacity = $alpha_o * $transparency / 100;
4747 if ($opacity > 0) {
4748 $red = round((($pixel_o['red'] * $opacity) + ($pixel_b['red'] ) * $alpha_b) / ($alpha_b + $opacity));
4749 $green = round((($pixel_o['green'] * $opacity) + ($pixel_b['green']) * $alpha_b) / ($alpha_b + $opacity));
4750 $blue = round((($pixel_o['blue'] * $opacity) + ($pixel_b['blue'] ) * $alpha_b) / ($alpha_b + $opacity));
4751 $alpha = ($opacity + $alpha_b);
4752 if ($alpha > 1) $alpha = 1;
4753 $alpha = round((1 - $alpha) * 127);
4754 $color = imagecolorallocatealpha($tmp, $red, $green, $blue, $alpha);
4755 imagesetpixel($tmp, $x, $y + $this->image_dst_y + $this->image_reflection_space, $color);
4756 }
4757 }
4758 if ($transparency > 0) $transparency = $transparency - ($this->image_reflection_opacity / $image_reflection_height);
4759 }
4760
4761 // copy the resulting image into the destination image
4762 $this->image_dst_y = $this->image_dst_y + $image_reflection_height + $this->image_reflection_space;
4763 $image_dst = $this->imagetransfer($tmp, $image_dst);
4764 }
4765
4766 // change opacity
4767 if ($gd_version >= 2 && is_numeric($this->image_opacity) && $this->image_opacity < 100) {
4768 $this->log .= '- change opacity<br />';
4769 // create the new destination image
4770 $tmp = $this->imagecreatenew($this->image_dst_x, $this->image_dst_y, true);
4771 for($y=0; $y < $this->image_dst_y; $y++) {
4772 for($x=0; $x < $this->image_dst_x; $x++) {
4773 $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4774 $alpha = $pixel['alpha'] + round((127 - $pixel['alpha']) * (100 - $this->image_opacity) / 100);
4775 if ($alpha > 127) $alpha = 127;
4776 if ($alpha > 0) {
4777 $color = imagecolorallocatealpha($tmp, $pixel['red'] , $pixel['green'], $pixel['blue'], $alpha);
4778 imagesetpixel($tmp, $x, $y, $color);
4779 }
4780 }
4781 }
4782 // copy the resulting image into the destination image
4783 $image_dst = $this->imagetransfer($tmp, $image_dst);
4784 }
4785
4786 // reduce the JPEG image to a set desired size
4787 if (is_numeric($this->jpeg_size) && $this->jpeg_size > 0 && ($this->image_convert == 'jpeg' || $this->image_convert == 'jpg')) {
4788 // inspired by: JPEGReducer class version 1, 25 November 2004, Author: Huda M ElMatsani, justhuda at netscape dot net
4789 $this->log .= '- JPEG desired file size : ' . $this->jpeg_size . '<br />';
4790 // calculate size of each image. 75%, 50%, and 25% quality
4791 ob_start(); imagejpeg($image_dst,null,75); $buffer = ob_get_contents(); ob_end_clean();
4792 $size75 = strlen($buffer);
4793 ob_start(); imagejpeg($image_dst,null,50); $buffer = ob_get_contents(); ob_end_clean();
4794 $size50 = strlen($buffer);
4795 ob_start(); imagejpeg($image_dst,null,25); $buffer = ob_get_contents(); ob_end_clean();
4796 $size25 = strlen($buffer);
4797
4798 // make sure we won't divide by 0
4799 if ($size50 == $size25) $size50++;
4800 if ($size75 == $size50 || $size75 == $size25) $size75++;
4801
4802 // calculate gradient of size reduction by quality
4803 $mgrad1 = 25 / ($size50-$size25);
4804 $mgrad2 = 25 / ($size75-$size50);
4805 $mgrad3 = 50 / ($size75-$size25);
4806 $mgrad = ($mgrad1 + $mgrad2 + $mgrad3) / 3;
4807 // result of approx. quality factor for expected size
4808 $q_factor = round($mgrad * ($this->jpeg_size - $size50) + 50);
4809
4810 if ($q_factor<1) {
4811 $this->jpeg_quality=1;
4812 } elseif ($q_factor>100) {
4813 $this->jpeg_quality=100;
4814 } else {
4815 $this->jpeg_quality=$q_factor;
4816 }
4817 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;JPEG quality factor set to ' . $this->jpeg_quality . '<br />';
4818 }
4819
4820 // converts image from true color, and fix transparency if needed
4821 $this->log .= '- converting...<br />';
4822 $this->image_dst_type = $this->image_convert;
4823 switch($this->image_convert) {
4824 case 'gif':
4825 // if the image is true color, we convert it to a palette
4826 if (imageistruecolor($image_dst)) {
4827 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;true color to palette<br />';
4828 // creates a black and white mask
4829 $mask = array(array());
4830 for ($x = 0; $x < $this->image_dst_x; $x++) {
4831 for ($y = 0; $y < $this->image_dst_y; $y++) {
4832 $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4833 $mask[$x][$y] = $pixel['alpha'];
4834 }
4835 }
4836 list($red, $green, $blue) = $this->getcolors($this->image_default_color);
4837 // first, we merge the image with the background color, so we know which colors we will have
4838 for ($x = 0; $x < $this->image_dst_x; $x++) {
4839 for ($y = 0; $y < $this->image_dst_y; $y++) {
4840 if ($mask[$x][$y] > 0){
4841 // we have some transparency. we combine the color with the default color
4842 $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4843 $alpha = ($mask[$x][$y] / 127);
4844 $pixel['red'] = round(($pixel['red'] * (1 -$alpha) + $red * ($alpha)));
4845 $pixel['green'] = round(($pixel['green'] * (1 -$alpha) + $green * ($alpha)));
4846 $pixel['blue'] = round(($pixel['blue'] * (1 -$alpha) + $blue * ($alpha)));
4847 $color = imagecolorallocate($image_dst, $pixel['red'], $pixel['green'], $pixel['blue']);
4848 imagesetpixel($image_dst, $x, $y, $color);
4849 }
4850 }
4851 }
4852 // transforms the true color image into palette, with its merged default color
4853 if (empty($this->image_background_color)) {
4854 imagetruecolortopalette($image_dst, true, 255);
4855 $transparency = imagecolorallocate($image_dst, 254, 1, 253);
4856 imagecolortransparent($image_dst, $transparency);
4857 // make the transparent areas transparent
4858 for ($x = 0; $x < $this->image_dst_x; $x++) {
4859 for ($y = 0; $y < $this->image_dst_y; $y++) {
4860 // we test wether we have enough opacity to justify keeping the color
4861 if ($mask[$x][$y] > 120) imagesetpixel($image_dst, $x, $y, $transparency);
4862 }
4863 }
4864 }
4865 unset($mask);
4866 }
4867 break;
4868 case 'jpg':
4869 case 'bmp':
4870 // if the image doesn't support any transparency, then we merge it with the default color
4871 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;fills in transparency with default color<br />';
4872 list($red, $green, $blue) = $this->getcolors($this->image_default_color);
4873 $transparency = imagecolorallocate($image_dst, $red, $green, $blue);
4874 // make the transaparent areas transparent
4875 for ($x = 0; $x < $this->image_dst_x; $x++) {
4876 for ($y = 0; $y < $this->image_dst_y; $y++) {
4877 // we test wether we have some transparency, in which case we will merge the colors
4878 if (imageistruecolor($image_dst)) {
4879 $rgba = imagecolorat($image_dst, $x, $y);
4880 $pixel = array('red' => ($rgba >> 16) & 0xFF,
4881 'green' => ($rgba >> 8) & 0xFF,
4882 'blue' => $rgba & 0xFF,
4883 'alpha' => ($rgba & 0x7F000000) >> 24);
4884 } else {
4885 $pixel = imagecolorsforindex($image_dst, imagecolorat($image_dst, $x, $y));
4886 }
4887 if ($pixel['alpha'] == 127) {
4888 // we have full transparency. we make the pixel transparent
4889 imagesetpixel($image_dst, $x, $y, $transparency);
4890 } else if ($pixel['alpha'] > 0) {
4891 // we have some transparency. we combine the color with the default color
4892 $alpha = ($pixel['alpha'] / 127);
4893 $pixel['red'] = round(($pixel['red'] * (1 -$alpha) + $red * ($alpha)));
4894 $pixel['green'] = round(($pixel['green'] * (1 -$alpha) + $green * ($alpha)));
4895 $pixel['blue'] = round(($pixel['blue'] * (1 -$alpha) + $blue * ($alpha)));
4896 $color = imagecolorclosest($image_dst, $pixel['red'], $pixel['green'], $pixel['blue']);
4897 imagesetpixel($image_dst, $x, $y, $color);
4898 }
4899 }
4900 }
4901
4902 break;
4903 default:
4904 break;
4905 }
4906
4907 // interlace options
4908 if($this->image_interlace) imageinterlace($image_dst, true);
4909
4910 // outputs image
4911 $this->log .= '- saving image...<br />';
4912 switch($this->image_convert) {
4913 case 'jpeg':
4914 case 'jpg':
4915 if (!$return_mode) {
4916 $result = @imagejpeg($image_dst, $this->file_dst_pathname, $this->jpeg_quality);
4917 } else {
4918 ob_start();
4919 $result = @imagejpeg($image_dst, null, $this->jpeg_quality);
4920 $return_content = ob_get_contents();
4921 ob_end_clean();
4922 }
4923 if (!$result) {
4924 $this->processed = false;
4925 $this->error = $this->translate('file_create', array('JPEG'));
4926 } else {
4927 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;JPEG image created<br />';
4928 }
4929 break;
4930 case 'png':
4931 imagealphablending( $image_dst, false );
4932 imagesavealpha( $image_dst, true );
4933 if (!$return_mode) {
4934 if (is_numeric($this->png_compression) && version_compare(PHP_VERSION, '5.1.2') >= 0) {
4935 $result = @imagepng($image_dst, $this->file_dst_pathname, $this->png_compression);
4936 } else {
4937 $result = @imagepng($image_dst, $this->file_dst_pathname);
4938 }
4939 } else {
4940 ob_start();
4941 if (is_numeric($this->png_compression) && version_compare(PHP_VERSION, '5.1.2') >= 0) {
4942 $result = @imagepng($image_dst, null, $this->png_compression);
4943 } else {
4944 $result = @imagepng($image_dst);
4945 }
4946 $return_content = ob_get_contents();
4947 ob_end_clean();
4948 }
4949 if (!$result) {
4950 $this->processed = false;
4951 $this->error = $this->translate('file_create', array('PNG'));
4952 } else {
4953 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;PNG image created<br />';
4954 }
4955 break;
4956 case 'webp':
4957 imagealphablending( $image_dst, false );
4958 imagesavealpha( $image_dst, true );
4959 if (!$return_mode) {
4960 $result = @imagewebp($image_dst, $this->file_dst_pathname, $this->webp_quality);
4961 } else {
4962 ob_start();
4963 $result = @imagewebp($image_dst, null, $this->webp_quality);
4964 $return_content = ob_get_contents();
4965 ob_end_clean();
4966 }
4967 if (!$result) {
4968 $this->processed = false;
4969 $this->error = $this->translate('file_create', array('WEBP'));
4970 } else {
4971 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;WEBP image created<br />';
4972 }
4973 break;
4974 case 'gif':
4975 if (!$return_mode) {
4976 $result = @imagegif($image_dst, $this->file_dst_pathname);
4977 } else {
4978 ob_start();
4979 $result = @imagegif($image_dst);
4980 $return_content = ob_get_contents();
4981 ob_end_clean();
4982 }
4983 if (!$result) {
4984 $this->processed = false;
4985 $this->error = $this->translate('file_create', array('GIF'));
4986 } else {
4987 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;GIF image created<br />';
4988 }
4989 break;
4990 case 'bmp':
4991 if (!$return_mode) {
4992 $result = $this->imagebmp($image_dst, $this->file_dst_pathname);
4993 } else {
4994 ob_start();
4995 $result = $this->imagebmp($image_dst);
4996 $return_content = ob_get_contents();
4997 ob_end_clean();
4998 }
4999 if (!$result) {
5000 $this->processed = false;
5001 $this->error = $this->translate('file_create', array('BMP'));
5002 } else {
5003 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;BMP image created<br />';
5004 }
5005 break;
5006
5007 default:
5008 $this->processed = false;
5009 $this->error = $this->translate('no_conversion_type');
5010 }
5011 if ($this->processed) {
5012 $this->imageunset($image_src);
5013 $this->imageunset($image_dst);
5014 $this->log .= '&nbsp;&nbsp;&nbsp;&nbsp;image objects destroyed<br />';
5015 }
5016 }
5017
5018 } else {
5019 $this->log .= '- no image processing wanted<br />';
5020
5021 if (!$return_mode) {
5022 // copy the file to its final destination. we don't use move_uploaded_file here
5023 // if we happen to have open_basedir restrictions, it is a temp file that we copy, not the original uploaded file
5024 if (!copy($this->file_src_pathname, $this->file_dst_pathname)) {
5025 $this->processed = false;
5026 $this->error = $this->translate('copy_failed');
5027 }
5028 } else {
5029 // returns the file, so that its content can be received by the caller
5030 $return_content = @file_get_contents($this->file_src_pathname);
5031 if ($return_content === false) {
5032 $this->processed = false;
5033 $this->error = $this->translate('reading_failed');
5034 }
5035 }
5036 }
5037 }
5038
5039 if ($this->processed) {
5040 $this->log .= '- <b>process OK</b><br />';
5041 } else {
5042 $this->log .= '- <b>error</b>: ' . $this->error . '<br />';
5043 }
5044
5045 // we reinit all the vars
5046 $this->init();
5047
5048 // we may return the image content
5049 if ($return_mode) return $return_content;
5050
5051 }
5052
5065 function clean() {
5066 $this->log .= '<b>cleanup</b><br />';
5067 $this->log .= '- delete temp file ' . $this->file_src_pathname . '<br />';
5068 @unlink($this->file_src_pathname);
5069 }
5070
5071
5079 function imagecreatefrombmp($filename) {
5080 if (! $f1 = fopen($filename,"rb")) return false;
5081
5082 $file = unpack("vfile_type/Vfile_size/Vreserved/Vbitmap_offset", fread($f1,14));
5083 if ($file['file_type'] != 19778) return false;
5084
5085 $bmp = unpack('Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel'.
5086 '/Vcompression/Vsize_bitmap/Vhoriz_resolution'.
5087 '/Vvert_resolution/Vcolors_used/Vcolors_important', fread($f1,40));
5088 $bmp['colors'] = pow(2,$bmp['bits_per_pixel']);
5089 if ($bmp['size_bitmap'] == 0) $bmp['size_bitmap'] = $file['file_size'] - $file['bitmap_offset'];
5090 $bmp['bytes_per_pixel'] = $bmp['bits_per_pixel']/8;
5091 $bmp['bytes_per_pixel2'] = ceil($bmp['bytes_per_pixel']);
5092 $bmp['decal'] = ($bmp['width']*$bmp['bytes_per_pixel']/4);
5093 $bmp['decal'] -= floor($bmp['width']*$bmp['bytes_per_pixel']/4);
5094 $bmp['decal'] = 4-(4*$bmp['decal']);
5095 if ($bmp['decal'] == 4) $bmp['decal'] = 0;
5096
5097 $palette = array();
5098 if ($bmp['colors'] < 16777216) {
5099 $palette = unpack('V'.$bmp['colors'], fread($f1,$bmp['colors']*4));
5100 }
5101
5102 $im = fread($f1,$bmp['size_bitmap']);
5103 $vide = chr(0);
5104
5105 $res = imagecreatetruecolor($bmp['width'],$bmp['height']);
5106 $P = 0;
5107 $Y = $bmp['height']-1;
5108 while ($Y >= 0) {
5109 $X=0;
5110 while ($X < $bmp['width']) {
5111 if ($bmp['bits_per_pixel'] == 24)
5112 $color = unpack("V",substr($im,$P,3).$vide);
5113 elseif ($bmp['bits_per_pixel'] == 16) {
5114 $color = unpack("n",substr($im,$P,2));
5115 $color[1] = $palette[$color[1]+1];
5116 } elseif ($bmp['bits_per_pixel'] == 8) {
5117 $color = unpack("n",$vide.substr($im,$P,1));
5118 $color[1] = $palette[$color[1]+1];
5119 } elseif ($bmp['bits_per_pixel'] == 4) {
5120 $color = unpack("n",$vide.substr($im,floor($P),1));
5121 if (($P*2)%2 == 0) $color[1] = ($color[1] >> 4) ; else $color[1] = ($color[1] & 0x0F);
5122 $color[1] = $palette[$color[1]+1];
5123 } elseif ($bmp['bits_per_pixel'] == 1) {
5124 $color = unpack("n",$vide.substr($im,floor($P),1));
5125 if (($P*8)%8 == 0) $color[1] = $color[1] >>7;
5126 elseif (($P*8)%8 == 1) $color[1] = ($color[1] & 0x40)>>6;
5127 elseif (($P*8)%8 == 2) $color[1] = ($color[1] & 0x20)>>5;
5128 elseif (($P*8)%8 == 3) $color[1] = ($color[1] & 0x10)>>4;
5129 elseif (($P*8)%8 == 4) $color[1] = ($color[1] & 0x8)>>3;
5130 elseif (($P*8)%8 == 5) $color[1] = ($color[1] & 0x4)>>2;
5131 elseif (($P*8)%8 == 6) $color[1] = ($color[1] & 0x2)>>1;
5132 elseif (($P*8)%8 == 7) $color[1] = ($color[1] & 0x1);
5133 $color[1] = $palette[$color[1]+1];
5134 } else
5135 return false;
5136 imagesetpixel($res,$X,$Y,$color[1]);
5137 $X++;
5138 $P += $bmp['bytes_per_pixel'];
5139 }
5140 $Y--;
5141 $P+=$bmp['decal'];
5142 }
5143 fclose($f1);
5144 return $res;
5145 }
5146
5154 function imagebmp(&$im, $filename = "") {
5155
5156 if (!$im) return false;
5157 $w = imagesx($im);
5158 $h = imagesy($im);
5159 $result = '';
5160
5161 // if the image is not true color, we convert it first
5162 if (!imageistruecolor($im)) {
5163 $tmp = imagecreatetruecolor($w, $h);
5164 imagecopy($tmp, $im, 0, 0, 0, 0, $w, $h);
5165 $this->imageunset($im);
5166 $im = & $tmp;
5167 }
5168
5169 $biBPLine = $w * 3;
5170 $biStride = ($biBPLine + 3) & ~3;
5171 $biSizeImage = $biStride * $h;
5172 $bfOffBits = 54;
5173 $bfSize = $bfOffBits + $biSizeImage;
5174
5175 $result .= substr('BM', 0, 2);
5176 $result .= pack ('VvvV', $bfSize, 0, 0, $bfOffBits);
5177 $result .= pack ('VVVvvVVVVVV', 40, $w, $h, 1, 24, 0, $biSizeImage, 0, 0, 0, 0);
5178
5179 $numpad = $biStride - $biBPLine;
5180 for ($y = $h - 1; $y >= 0; --$y) {
5181 for ($x = 0; $x < $w; ++$x) {
5182 $col = imagecolorat ($im, $x, $y);
5183 $result .= substr(pack ('V', $col), 0, 3);
5184 }
5185 for ($i = 0; $i < $numpad; ++$i)
5186 $result .= pack ('C', 0);
5187 }
5188
5189 if($filename==""){
5190 echo $result;
5191 } else {
5192 $file = fopen($filename, "wb");
5193 fwrite($file, $result);
5194 fclose($file);
5195 }
5196 return true;
5197 }
5198}
Class upload.
$image_y
Set this variable to the wanted (or maximum/minimum) height for the processed image,...
$image_text_direction
Sets the text direction for the text label.
$mime_getimagesize
Set this variable to false in the init() function if you don't want to check the MIME with getimagesi...
function_enabled($func)
Checks if a function is available.
$image_x
Set this variable to the wanted (or maximum/minimum) width for the processed image,...
$image_max_ratio
Set this variable to set a maximum image aspect ratio, above which the upload will be invalid.
getcolors($color)
Decodes colors.
$image_tint_color
Applies a tint on the image.
$image_text_background_opacity
Sets the text background opacity in the text label.
$mime_check
Set this variable to false if you don't want to check the MIME against the allowed list.
$image_convert
Set this variable to convert the file if it is an image.
$file_dst_name
Destination file name.
$image_border_color
Border color.
$processed
Flag set after calling a process.
imagecreatefrombmp($filename)
Opens a BMP image.
$image_text_padding
Sets the text label padding.
$image_reflection_height
Sets the height of the reflection.
$file_is_image
Flag to determine if the source file is an image.
$image_dst_type
Destination image type (png, gif, jpg, webp or bmp).
$image_ratio
Set this variable to keep the original size ratio to fit within image_x x image_y.
$image_max_height
Set this variable to set a maximum image height, above which the upload will be invalid.
$mime_magic
Set this variable to false in the init() function if you don't want to check the MIME with the magic....
$file_src_pathname
Uloaded file name, including server path.
$image_transparent_color
Transparent color in a palette.
$file_overwrite
Set this variable tu true to allow overwriting of an existing file.
$image_supported
Supported image formats.
$image_border_transparent
Adds a fading-to-transparent border on the image.
$png_compression
Compression level for PNG images.
$image_frame_colors
Sets the colors used to draw a frame.
clean()
Deletes the uploaded file from its temporary location.
$file_new_name_body
Set this variable to replace the name body (i.e.
imagecreatenew($x, $y, $fill=true, $trsp=false)
Creates a container image.
$image_src_y
Source image height.
$image_bevel_color1
Top and left bevel color.
$allowed
Allowed MIME types or file extensions.
gdversion($full=false)
Returns the version of GD.
$image_opacity
Changes the image opacity.
$webp_quality
Quality of WebP created/converted destination image.
$file_force_extension
Forces an extension if the source file doesn't have one.
$image_auto_rotate
Automatically rotates the image according to EXIF data (JPEG only).
translate($str, $tokens=array())
Translate error messages.
$image_ratio_pixels
Set this variable to a number of pixels so that image_x and image_y are the best match possible.
$image_min_height
Set this variable to set a minimum image height, below which the upload will be invalid.
$jpeg_quality
Quality of JPEG created/converted destination image.
$image_min_pixels
Set this variable to set a minimum number of pixels for an image, below which the upload will be inva...
imageunset($im)
Destroy GD ressource.
$image_frame
Adds a multi-color frame on the outer of the image.
$image_ratio_x
Set this variable to calculate image_x automatically , using image_y and conserving ratio.
$file_src_name_ext
Uploaded file name extension.
$image_watermark_x
Sets the watermark absolute X position within the image.
$image_text_y
Sets the text label absolute Y position within the image.
sanitize($filename)
Sanitize a file name.
$mime_types
List of MIME types per extension.
$image_greyscale
Turns the image into greyscale.
$dir_chmod
Set this variable to the default chmod you want the class to use when creating directories,...
$image_contrast
Corrects the image contrast.
$image_dst_x
Destination image width.
imagetransfer($src_im, $dst_im)
Transfers an image from the container to the destination image.
$image_unsharp
Applies an unsharp mask, with alpha transparency support.
$image_src_pixels
Number of pixels.
$image_reflection_space
Sets the space between the source image and its relection.
$image_overlay_opacity
Sets the opacity for the colored overlay.
$file_max_size
Set this variable to change the maximum size in bytes for an uploaded file.
$lang
Language selected for the translations.
$image_flip
Flips the image vertically or horizontally.
$file_dst_name_body
Destination file name body (i.e.
_mkdir($path, $mode=0755)
Creates directory.
$image_text
Adds a text label on the image.
$file_auto_rename
Set this variable to true to allow automatic renaming of the file if the file already exists.
$image_text_color
Sets the text color for the text label.
process($server_path=null)
Actually uploads the file, and act on it according to the set processing class variables.
$image_min_ratio
Set this variable to set a minimum image aspect ratio, below which the upload will be invalid.
getsize($size)
Decodes sizes.
$image_ratio_no_zoom_in
(deprecated) Set this variable to keep the original size ratio to fit within image_x x image_y,...
$file_dst_pathname
Destination file name, including path.
$image_no_shrinking
Cancel resizing if the resized image is smaller than the original image, to prevent shrinking.
$image_pixelate
Pixelate an image.
$image_threshold
Applies threshold filter.
$image_border
Adds a single-color border on the outer of the image.
$image_text_line_spacing
Sets the text line spacing.
$image_negative
Inverts the color of an image.
__construct($file='', $lang='en_GB')
Constructor, for PHP5+.
$image_rotate
Rotates the image by increments of 45 degrees.
imagebmp(&$im, $filename="")
Saves a BMP image.
$image_min_width
Set this variable to set a minimum image width, below which the upload will be invalid.
$file_dst_name_ext
Destination file extension.
$image_max_width
Set this variable to set a maximum image width, above which the upload will be invalid.
$image_text_alignment
Sets the text alignment.
$image_bevel_color2
Right and bottom bevel color.
$jpeg_size
Determines the quality of the JPG image to fit a desired file size.
$image_ratio_y
Set this variable to calculate image_y automatically , using image_x and conserving ratio.
$image_src_x
Source image width.
$error
Holds eventual error message in plain english.
$file_dst_path
Destination file name.
$uploaded
Flag set after instanciating the class.
$file_src_mime
Uploaded file MIME type.
$translation
Array of translated error messages.
$file_src_name_body
Uploaded file name body (i.e.
$image_text_font
Sets the text font in the text label.
$image_overlay_color
Applies a colored overlay on the image.
$image_unsharp_radius
Sets the unsharp mask radius.
$image_watermark_position
Sets the watermarkposition within the image.
$image_watermark_y
Sets the twatermark absolute Y position within the image.
$image_max_pixels
Set this variable to set a maximum number of pixels for an image, above which the upload will be inva...
$mime_fileinfo
Set this variable to false in the init() function if you don't want to check the MIME with Fileinfo P...
$image_text_padding_x
Sets the text label horizontal padding.
$image_is_transparent
Flag set to true when the image is transparent.
$image_unsharp_amount
Sets the unsharp mask amount.
$file_max_size_raw
Max file size, from php.ini.
temp_dir()
Returns the temp directory.
$image_text_size
Sets the text font size for TrueType fonts.
$file_name_body_pre
Set this variable to prepend a string to the file name body.
$image_border_opacity
Sets the opacity for the borders.
$image_no_enlarging
Cancel resizing if the resized image is bigger than the original image, to prevent enlarging.
$image_text_padding_y
Sets the text label vertical padding.
$image_brightness
Corrects the image brightness.
$mime_file
Set this variable to false in the init() function if you don't want to check the MIME with UNIX file(...
$image_frame_opacity
Sets the opacity for the frame.
getoffsets($offsets, $x, $y, $round=true, $negative=true)
Decodes offsets.
$image_background_color
Background color, used to paint transparent areas with.
$image_watermark
Adds a watermark on the image.
$no_upload_check
Flag stopping PHP upload checks.
$file_src_size
Uploaded file size, in bytes.
$image_is_palette
Flag set to true when the image is not true color.
$image_text_position
Sets the text label position within the image.
$image_ratio_crop
Set this variable to keep the original size ratio to fit within image_x x image_y.
$no_script
Set this variable to false if you don't want to turn dangerous scripts into simple text files The lis...
$image_bevel
Adds a bevel border on the image.
$image_text_x
Sets the text label absolute X position within the image.
rmkdir($path, $mode=0755)
Creates directories recursively.
$dangerous
Dangerous file extensions.
$image_text_angle
Sets the text angle for TrueType fonts.
init()
Init or re-init all the processing variables to their default values.
$image_src_bits
Source image color depth.
$file_src_error
Holds eventual PHP error code from $_FILES.
$file_safe_name
Set this variable to format the filename (spaces changed to _).
$dir_auto_create
Set this variable to true to allow automatic creation of the destination directory if it is missing (...
upload($file, $lang='en_GB')
Constructor, for PHP4.
$image_ratio_no_zoom_out
(deprecated) Set this variable to keep the original size ratio to fit within image_x x image_y,...
$image_ratio_fill
Set this variable to keep the original size ratio to fit within image_x x image_y.
$dir_auto_chmod
Set this variable to true to allow automatic chmod of the destination directory if it is not writeabl...
$image_default_color
Default color for non alpha-transparent images.
imagecopymergealpha(&$dst_im, &$src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct=0)
Merges two GD images while preserving alpha information.
$file_new_name_ext
Set this variable to change the file extension.
$image_text_opacity
Sets the text opacity in the text label.
$image_interlace
Turns the interlace bit on.
$image_text_background
Sets the text background color for the text label.
$forbidden
Forbidden MIME types or file extensions.
$image_crop
Crops an image.
$file_src_name
Uploaded file name.
$file_name_body_add
Set this variable to append a string to the file name body.
$image_unsharp_threshold
Sets the unsharp mask threshold.
$image_watermark_no_zoom_out
Prevents the watermark to be resized down if it is bigger than the image.
$image_precrop
Crops an image, before an eventual resizing.
$image_watermark_no_zoom_in
Prevents the watermark to be resized up if it is smaller than the image.
$image_src_type
Type of image (png, gif, jpg, webp or bmp).
$image_resize
Set this variable to true to resize the file if it is an image.
$image_reflection_opacity
Sets the initial opacity of the reflection.
$image_dst_y
Destination image height.
$log
Holds an HTML formatted log.
$file_src_temp
Uloaded file name temporary copy.
$version
Class version.
if(! $db->connect_db_server($server)) $result
$_SERVER['REQUEST_URI']