319 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			319 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * @package    JEM
 | |
|  * @copyright  (C) 2013-2024 joomlaeventmanager.net
 | |
|  * @copyright  (C) 2005-2009 Christoph Lukes
 | |
|  * @license    https://www.gnu.org/licenses/gpl-3.0 GNU/GPL
 | |
|  */
 | |
| 
 | |
| defined('_JEXEC') or die;
 | |
| 
 | |
| use Joomla\CMS\Factory;
 | |
| use Joomla\CMS\Filesystem\File;
 | |
| use Joomla\CMS\Language\Text;
 | |
| 
 | |
| require_once(JPATH_SITE.'/components/com_jem/classes/Zebra_Image.php');
 | |
| 
 | |
| /**
 | |
|  * Holds the logic for image manipulation
 | |
|  *
 | |
|  * @package JEM
 | |
|  */
 | |
| class JemImage
 | |
| {
 | |
| 	static public function thumb($name,$filename,$new_w,$new_h)
 | |
| 	{
 | |
| 		// load the image manipulation class
 | |
| 		//require 'path/to/Zebra_Image.php';
 | |
| 
 | |
| 		// create a new instance of the class
 | |
| 		$image = new Zebra_Image();
 | |
| 
 | |
| 		// indicate a source image (a GIF, PNG or JPEG file)
 | |
| 		$image->source_path = $name;
 | |
| 
 | |
| 		// indicate a target image
 | |
| 		// note that there's no extra property to set in order to specify the target
 | |
| 		// image's type -simply by writing '.jpg' as extension will instruct the script
 | |
| 		// to create a 'jpg' file
 | |
| 		$image->target_path = $filename;
 | |
| 
 | |
| 		// since in this example we're going to have a jpeg file, let's set the output
 | |
| 		// image's quality (95% has no visible effect but saves some bytes)
 | |
| 		$image->jpeg_quality = 95;
 | |
| 
 | |
| 		// some additional properties that can be set
 | |
| 		// read about them in the documentation
 | |
| 		$image->preserve_aspect_ratio = true;
 | |
| 		$image->enlarge_smaller_images = false;
 | |
| 		$image->preserve_time = true;
 | |
| 		$image->auto_handle_exif_orientation = true;
 | |
| 
 | |
| 		// resize the image to at best 100x100 pixels by using the "not boxed" method
 | |
| 		// (read more in the overview section or in the documentation)
 | |
| 		// and if there is an error, check what the error is about
 | |
| 		if (!$image->resize($new_w, $new_h, ZEBRA_IMAGE_NOT_BOXED, -1)) {
 | |
| 
 | |
| 			//only admins will see these errors
 | |
| 			if (Factory::getApplication()->getIdentity()->authorise('core.manage')) {
 | |
| 
 | |
| 				// if there was an error, let's see what the error is about
 | |
| 				switch ($image->error) {
 | |
| 				case 1:
 | |
| 					Factory::getApplication()->enqueueMessage("Source file $name could not be found!", 'warning');
 | |
| 					break;
 | |
| 				case 2:
 | |
| 					Factory::getApplication()->enqueueMessage("Source file $name is not readable!", 'warning');
 | |
| 					break;
 | |
| 				case 3:
 | |
| 					Factory::getApplication()->enqueueMessage("Could not write target file $filename !", 'warning');
 | |
| 					break;
 | |
| 				case 4:
 | |
| 					Factory::getApplication()->enqueueMessage('Unsupported source file format!', 'warning');
 | |
| 					break;
 | |
| 				case 5:
 | |
| 					Factory::getApplication()->enqueueMessage('Unsupported target file format!', 'warning');
 | |
| 					break;
 | |
| 				case 6:
 | |
| 					Factory::getApplication()->enqueueMessage('GD library version does not support target file format!', 'warning');
 | |
| 					break;
 | |
| 				case 7:
 | |
| 					Factory::getApplication()->enqueueMessage('GD library is not installed!', 'warning');
 | |
| 					break;
 | |
| 				case 8:
 | |
| 					Factory::getApplication()->enqueueMessage('"chmod" command is disabled via configuration', 'warning');
 | |
| 					break;
 | |
| 				case 9:
 | |
| 					Factory::getApplication()->enqueueMessage('"exif_read_data" function is not available', 'warning');
 | |
| 					break;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Determine the GD version
 | |
| 	 * Code from php.net
 | |
| 	 *
 | |
| 	 * @param  int
 | |
| 	 *
 | |
| 	 * @return int
 | |
| 	 */
 | |
| 	static public function gdVersion($user_ver = 0)
 | |
| 	{
 | |
| 		if (! extension_loaded('gd')) {
 | |
| 			return;
 | |
| 		}
 | |
| 		static $gd_ver = 0;
 | |
| 
 | |
| 		// Just accept the specified setting if it's 1.
 | |
| 		if ($user_ver == 1) {
 | |
| 			$gd_ver = 1;
 | |
| 			return 1;
 | |
| 		}
 | |
| 		// Use the static variable if function was called previously.
 | |
| 		if ($user_ver != 2 && $gd_ver > 0) {
 | |
| 			return $gd_ver;
 | |
| 		}
 | |
| 		// Use the gd_info() function if possible.
 | |
| 		if (function_exists('gd_info')) {
 | |
| 			$ver_info = gd_info();
 | |
| 			preg_match('/\d/', $ver_info['GD Version'], $match);
 | |
| 			$gd_ver = $match[0];
 | |
| 			return $match[0];
 | |
| 		}
 | |
| 		// If phpinfo() is disabled use a specified / fail-safe choice...
 | |
| 		if (preg_match('/phpinfo/', ini_get('disable_functions'))) {
 | |
| 			if ($user_ver == 2) {
 | |
| 				$gd_ver = 2;
 | |
| 				return 2;
 | |
| 			} else {
 | |
| 				$gd_ver = 1;
 | |
| 				return 1;
 | |
| 			}
 | |
| 		}
 | |
| 		// ...otherwise use phpinfo().
 | |
| 		ob_start();
 | |
| 		phpinfo(8);
 | |
| 		$info = ob_get_contents();
 | |
| 		ob_end_clean();
 | |
| 		$info = stristr($info, 'gd version');
 | |
| 		preg_match('/\d/', $info, $match);
 | |
| 		$gd_ver = $match[0];
 | |
| 
 | |
| 		return $match[0];
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Creates image information of an image
 | |
| 	 *
 | |
| 	 * @param  string $image The image name
 | |
| 	 * @param  array $settings
 | |
| 	 * @param  string $type event or venue
 | |
| 	 *
 | |
| 	 * @return imagedata if available
 | |
| 	 */
 | |
| 	static public function flyercreator($image, $type)
 | |
| 	{
 | |
| 		$settings = JemHelper::config();
 | |
| 
 | |
| 		if (($settings->imagewidth < 1) || ($settings->imagehight < 1)) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		//define the environment based on the type
 | |
| 		if ($type == 'event') {
 | |
| 			$folder = 'events';
 | |
| 		} else if ($type == 'category') {
 | |
| 			$folder = 'categories';
 | |
| 		} else if ($type == 'venue') {
 | |
| 			$folder = 'venues';
 | |
| 		} else {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		if ($image) {
 | |
| 			$img_orig  = 'images/jem/'.$folder.'/'.$image;
 | |
| 			$img_thumb = 'images/jem/'.$folder.'/small/'.$image;
 | |
| 
 | |
| 			$filepath  = JPATH_SITE.'/'.$img_orig;
 | |
| 			$save      = JPATH_SITE.'/'.$img_thumb;
 | |
| 
 | |
| 			// At least original image must exist
 | |
| 			if (!file_exists($filepath)) {
 | |
| 				return false;
 | |
| 			}
 | |
| 
 | |
| 			//Create thumbnail if enabled and it does not exist already
 | |
| 			if ($settings->gddisabled == 1 && !file_exists($save)) {
 | |
| 				JemImage::thumb($filepath, $save, $settings->imagewidth, $settings->imagehight);
 | |
| 			}
 | |
| 
 | |
| 			//set paths
 | |
| 			$dimage['original'] = $img_orig;
 | |
| 			$dimage['thumb']    = $img_thumb;
 | |
| 
 | |
| 			//get imagesize of the original
 | |
| 			$iminfo = @getimagesize($img_orig);
 | |
| 
 | |
| 			// and it should be an image
 | |
| 			if (!is_array($iminfo) || count($iminfo) < 2) {
 | |
| 				return false;
 | |
| 			}
 | |
| 
 | |
| 			//if the width or height is too large this formula will resize them accordingly
 | |
| 			if (($iminfo[0] > $settings->imagewidth) || ($iminfo[1] > $settings->imagehight)) {
 | |
| 				$iRatioW = $settings->imagewidth / $iminfo[0];
 | |
| 				$iRatioH = $settings->imagehight / $iminfo[1];
 | |
| 
 | |
| 				if ($iRatioW < $iRatioH) {
 | |
| 					$dimage['width']  = round($iminfo[0] * $iRatioW);
 | |
| 					$dimage['height'] = round($iminfo[1] * $iRatioW);
 | |
| 				} else {
 | |
| 					$dimage['width']  = round($iminfo[0] * $iRatioH);
 | |
| 					$dimage['height'] = round($iminfo[1] * $iRatioH);
 | |
| 				}
 | |
| 			} else {
 | |
| 				$dimage['width']  = $iminfo[0];
 | |
| 				$dimage['height'] = $iminfo[1];
 | |
| 			}
 | |
| 
 | |
| 			if (File::exists(JPATH_SITE.'/'.$img_thumb)) {
 | |
| 				//get imagesize of the thumbnail
 | |
| 				$thumbiminfo = @getimagesize($img_thumb);
 | |
| 				$dimage['thumbwidth']  = $thumbiminfo[0];
 | |
| 				$dimage['thumbheight'] = $thumbiminfo[1];
 | |
| 			}
 | |
| 
 | |
| 			return $dimage;
 | |
| 		}
 | |
| 
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	static public function check($file, $jemsettings)
 | |
| 	{
 | |
| 		$sizelimit = $jemsettings->sizelimit*1024; //size limit in kb
 | |
| 		$imagesize = $file['size'];
 | |
| 		$filetypes = $jemsettings->image_filetypes ?: 'jpg,gif,png,webp';
 | |
| 
 | |
| 		//check if the upload is an image...getimagesize will return false if not
 | |
| 		if (!getimagesize($file['tmp_name'])) {
 | |
| 			Factory::getApplication()->enqueueMessage(Text::_('COM_JEM_UPLOAD_FAILED_NOT_AN_IMAGE').': '.htmlspecialchars($file['name'], ENT_COMPAT, 'UTF-8'), 'warning');
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		//check if the imagefiletype is valid
 | |
| 		$fileext = strtolower(File::getExt($file['name']));
 | |
| 
 | |
| 		$allowable = explode(',', strtolower($filetypes));
 | |
| 		array_walk($allowable, function(&$v){$v = trim($v);});
 | |
| 		if (!in_array($fileext, $allowable)) {
 | |
| 			Factory::getApplication()->enqueueMessage(Text::_('COM_JEM_WRONG_IMAGE_FILE_TYPE').': '.htmlspecialchars($file['name'], ENT_COMPAT, 'UTF-8'), 'warning');
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		//Check filesize
 | |
| 		if ($imagesize > $sizelimit) {
 | |
| 			Factory::getApplication()->enqueueMessage(Text::_('COM_JEM_IMAGE_FILE_SIZE').': '.htmlspecialchars($file['name'], ENT_COMPAT, 'UTF-8'), 'warning');
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		//XSS check
 | |
| 		//$xss_check = File::read($file['tmp_name'], false, 256);
 | |
| 		$xss_check = file_get_contents($file['tmp_name'], false, NULL, 0, 256);
 | |
| 		$html_tags = array('abbr','acronym','address','applet','area','audioscope','base','basefont','bdo','bgsound','big','blackface','blink','blockquote','body','bq','br','button','caption','center','cite','code','col','colgroup','comment','custom','dd','del','dfn','dir','div','dl','dt','em','embed','fieldset','fn','font','form','frame','frameset','h1','h2','h3','h4','h5','h6','head','hr','html','iframe','ilayer','img','input','ins','isindex','keygen','kbd','label','layer','legend','li','limittext','link','listing','map','marquee','menu','meta','multicol','nobr','noembed','noframes','noscript','nosmartquotes','object','ol','optgroup','option','param','plaintext','pre','rt','ruby','s','samp','script','select','server','shadow','sidebar','small','spacer','span','strike','strong','style','sub','sup','table','tbody','td','textarea','tfoot','th','thead','title','tr','tt','ul','var','wbr','xml','xmp','!DOCTYPE', '!--');
 | |
| 		foreach ($html_tags as $tag) {
 | |
| 			// A tag is '<tagname ', so we need to add < and a space or '<tagname>'
 | |
| 			if (stristr($xss_check, '<'.$tag.' ') || stristr($xss_check, '<'.$tag.'>')) {
 | |
| 				Factory::getApplication()->enqueueMessage(Text::_('COM_JEM_WARN_IE_XSS'), 'warning');
 | |
| 				return false;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return true;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Sanitize the image file name and return an unique string
 | |
| 	 *
 | |
| 	 *
 | |
| 	 * @param  string $base_Dir the target directory
 | |
| 	 * @param  string $filename the unsanitized imagefile name
 | |
| 	 *
 | |
| 	 * @return string $filename the sanitized and unique image file name
 | |
| 	 */
 | |
| 	static public function sanitize($base_Dir, $filename)
 | |
| 	{
 | |
| 		//check for any leading/trailing dots and remove them (trailing shouldn't be possible cause of the getEXT check)
 | |
| 		$filename = preg_replace("/^[.]*/", '', $filename);
 | |
| 		$filename = preg_replace("/[.]*$/", '', $filename); //shouldn't be necessary, see above
 | |
| 
 | |
| 		//we need to save the last dot position cause preg_replace will also replace dots
 | |
| 		$lastdotpos = strrpos($filename, '.');
 | |
| 
 | |
| 		//replace invalid characters
 | |
| 		$filename = strtolower(preg_replace("/[^0-9a-zA-Z_-]/", '_', $filename));
 | |
| 
 | |
| 		//get the parts before and after the dot (assuming we have an extension...check was done before)
 | |
| 		$beforedot	= substr($filename, 0, $lastdotpos);
 | |
| 		$afterdot 	= substr($filename, $lastdotpos + 1);
 | |
| 
 | |
| 		//make a unique filename for the image and check it is not already taken
 | |
| 		//if it is already taken keep trying till success
 | |
| 		//$now = time();
 | |
| 
 | |
| 		$now = rand();
 | |
| 
 | |
| 		while (File::exists($base_Dir . $beforedot . '_' . $now . '.' . $afterdot)) {
 | |
| 			$now++;
 | |
| 		}
 | |
| 
 | |
| 		//create out of the seperated parts the new filename
 | |
| 		$filename = $beforedot . '_' . $now . '.' . $afterdot;
 | |
| 
 | |
| 		return $filename;
 | |
| 	}
 | |
| }
 | |
| ?>
 |