Index: branches/5.0.x/core/units/helpers/image_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/image_helper.php	(revision 12323)
+++ branches/5.0.x/core/units/helpers/image_helper.php	(revision 12324)
@@ -1,607 +1,653 @@
 <?php
 /**
 * @version	$Id$
 * @package	In-Portal
 * @copyright	Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
 * @license      GNU/GPL
 * In-Portal is Open Source software.
 * This means that this software may have been modified pursuant
 * the GNU General Public License, and as distributed it includes
 * or is derivative of works licensed under the GNU General Public License
 * or other free or open source software licenses.
 * See http://www.in-portal.net/license/ for copyright notices and details.
 */
 
 	defined('FULL_PATH') or die('restricted access!');
 
 	class ImageHelper extends kHelper {
 
 		/**
 		 * Parses format string into array
 		 *
 		 * @param string $format sample format: "resize:300x500;wm:inc/wm.png|c|-20"
 		 * @return Array sample result: Array('max_width' => 300, 'max_height' => 500, 'wm_filename' => 'inc/wm.png', 'h_margin' => 'c', 'v_margin' => -20)
 		 */
 		function parseFormat($format)
 		{
 			$res = Array ();
 
 			$format_parts = explode(';', $format);
 			foreach ($format_parts as $format_part) {
 				if (preg_match('/resize:(\d*)x(\d*)/', $format_part, $regs)) {
 					$res['max_width'] = $regs[1];
 					$res['max_height'] = $regs[2];
 				}
 				elseif (preg_match('/wm:([^\|]*)\|([^\|]*)\|([^\|]*)/', $format_part, $regs)) {
 					$res['wm_filename'] = FULL_PATH.THEMES_PATH.'/'.$regs[1];
 					$res['h_margin'] = strtolower($regs[2]);
 					$res['v_margin'] = strtolower($regs[3]);
 				}
 				elseif (preg_match('/crop:([^\|]*)\|([^\|]*)/', $format_part, $regs)) {
 					$res['crop_x'] = strtolower($regs[1]);
 					$res['crop_y'] = strtolower($regs[2]);
 				}
 				elseif ($format_part == 'img_size' || $format_part == 'img_sizes') {
 					$res['image_size'] = true;
 				}
 				elseif (preg_match('/fill:(.*)/', $format_part, $regs)) {
 					$res['fill'] = $regs[1];
 				}
 			}
 
 			return $res;
 		}
 
 		/**
 		 * Resized given image to required dimensions & saves resized image to "resized" subfolder in source image folder
 		 *
 		 * @param string $src_image full path to image (on server)
 		 * @param mixed $max_width maximal allowed resized image width or false if no limit
 		 * @param mixed $max_height maximal allowed resized image height or false if no limit
 		 * @return string direct url to resized image
 		 */
 		function ResizeImage($src_image, $max_width, $max_height = null)
 		{
 			$image_size = false;
 
 			if(isset($max_height)) {
 				$params['max_height'] = $max_height;
 				$params['max_width'] = $max_width;
 			}
 			else {
 				$params = $this->parseFormat($max_width);
 
 				if (array_key_exists('image_size', $params)) {
 					// image_size param shouldn't affect resized file name (crc part)
 					$image_size = $params['image_size'];
 					unset($params['image_size']);
 				}
 			}
 
 			if ($params['max_width'] > 0 || $params['max_height'] > 0) {
 				list ($params['target_width'], $params['target_height'], $needs_resize) = $this->GetImageDimensions($src_image, $params['max_width'], $params['max_height'], $params);
 
 				if (!is_numeric($params['max_width'])) {
 					$params['max_width'] = $params['target_width'];
 				}
 
 				if (!is_numeric($params['max_height'])) {
 					$params['max_height'] = $params['target_height'];
 				}
 
 				$src_path = dirname($src_image);
 
 				if ($needs_resize || array_key_exists('wm_filename', $params) && $params['wm_filename']) {
 					// resize required OR watermarking required -> change resulting image name !
 					$dst_image = preg_replace('/^'.preg_quote($src_path, '/').'(.*)\.(.*)$/', $src_path . DIRECTORY_SEPARATOR . 'resized\\1_' . crc32(serialize($params)) . '.\\2', $src_image);
 					if (!file_exists($dst_image) || filemtime($src_image) > filemtime($dst_image)) {
 						// resized image not available OR should be recreated due source image change
 						$params['dst_image'] = $dst_image;
 						$image_resized = $this->ScaleImage($src_image, $params);
 						if (!$image_resized) {
 							// resize failed, because of server error
 							$dst_image = $src_image;
 						}
 					}
 
 					// resize/watermarking ok
 					$src_image = $dst_image;
 				}
 			}
 
 			if ($image_size) {
 				// return only image size (resized or not)
 				$image_info = $this->getImageInfo($src_image);
 				return $image_info ? $image_info[3] : '';
 			}
 
 			$base_url = rtrim($this->Application->BaseURL(), '/');
 			return str_replace(DIRECTORY_SEPARATOR, '/', preg_replace('/^'.preg_quote(FULL_PATH, '/').'(.*)/', $base_url.'\\1', $src_image));
 		}
 
 		/**
 		 * Proportionally resizes given image to destination dimensions
 		 *
 		 * @param string $src_image full path to source image (already existing)
 		 * @param string $dst_image full path to destination image (will be created)
 		 * @param int $dst_width destination image width (in pixels)
 		 * @param int $dst_height destination image height (in pixels)
 		 */
 		function ScaleImage($src_image, $params)
 		{
 			$image_info = $this->getImageInfo($src_image);
 			if (!$image_info) {
 				return false;
 			}
 
 			/*list ($params['max_width'], $params['max_height'], $resized) = $this->GetImageDimensions($src_image, $params['max_width'], $params['max_height'], $params);
 			if (!$resized) {
 				// image dimensions are smaller or equals to required dimensions
 				return false;
 			}*/
 
 			if (!$this->Application->ConfigValue('ForceImageMagickResize') && function_exists('imagecreatefromjpeg')) {
 				// try to resize using GD
 				$resize_map = Array (
 					'image/jpeg' => 'imagecreatefromjpeg:imagejpeg:jpg',
 					'image/gif' => 'imagecreatefromgif:imagegif:gif',
 					'image/png' => 'imagecreatefrompng:imagepng:png',
 					'image/bmp' => 'imagecreatefrombmp:imagejpeg:bmp',
 				);
 
 				$mime_type = $image_info['mime'];
 				if (!isset($resize_map[$mime_type])) {
 					return false;
 				}
 
 				list ($read_function, $write_function, $file_extension) = explode(':', $resize_map[$mime_type]);
 
 				$src_image_rs = @$read_function($src_image);
 				if ($src_image_rs) {
 					// when source image has large dimensions (over 1MB filesize), then 16M is not enough
 					set_time_limit(0);
 					ini_set('memory_limit', -1);
 
 					$dst_image_rs = imagecreatetruecolor($params['target_width'], $params['target_height']); // resize target size
 
-					if ($file_extension == 'png') {
-						// preserve transparency of PNG images
-						$transparent_color = imagecolorallocate($dst_image_rs, 0, 0, 0);
-						imagecolortransparent($dst_image_rs, $transparent_color);
+					if (($file_extension == 'gif') || ($file_extension == 'png')) {
+						// preserve transparency of PNG and GIF images
+						$dst_image_rs = $this->_preserveTransparency($src_image_rs, $dst_image_rs, $image_info[2]);
 					}
 
 					// 1. resize
 					imagecopyresampled($dst_image_rs, $src_image_rs, 0, 0, 0, 0, $params['target_width'], $params['target_height'], $image_info[0], $image_info[1]);
 
 					$watermark_size = 'target';
 
 					if (array_key_exists('crop_x', $params) || array_key_exists('crop_y', $params)) {
 						// 2.1. crop image to given size
 						$dst_image_rs =& $this->_cropImage($dst_image_rs, $params);
 						$watermark_size = 'max';
 					} elseif (array_key_exists('fill', $params)) {
 						// 2.2. fill image margins from resize with given color
 						$dst_image_rs =& $this->_applyFill($dst_image_rs, $params);
 						$watermark_size = 'max';
 					}
 
 					// 3. apply watermark
 					$dst_image_rs =& $this->_applyWatermark($dst_image_rs, $params[$watermark_size . '_width'], $params[$watermark_size . '_height'], $params);
 
 					return @$write_function($dst_image_rs, $params['dst_image'], 100);
 				}
 			}
 			else {
 				// try to resize using ImageMagick
 				// TODO: implement crop and watermarking using imagemagick
 				exec('/usr/bin/convert '.$src_image.' -resize '.$params['target_width'].'x'.$params['target_height'].' '.$params['dst_image'], $shell_output, $exec_status);
 				return $exec_status == 0;
 			}
 
 			return false;
 		}
 
 		/**
+		 * Preserve transparency for GIF and PNG images
+		 *
+		 * @param resource $src_image_rs
+		 * @param resource $dst_image_rs
+		 * @param int $image_type
+		 * @return resource
+		 */
+		function _preserveTransparency($src_image_rs, $dst_image_rs, $image_type)
+		{
+			$transparent_index = imagecolortransparent($src_image_rs);
+
+			// if we have a specific transparent color
+			if ($transparent_index >= 0) {
+				// get the original image's transparent color's RGB values
+				$transparent_color = imagecolorsforindex($src_image_rs, $transparent_index);
+
+				// allocate the same color in the new image resource
+				$transparent_index = imagecolorallocate($dst_image_rs, $transparent_color['red'], $transparent_color['green'], $transparent_color['blue']);
+
+				// completely fill the background of the new image with allocated color
+				imagefill($dst_image_rs, 0, 0, $transparent_index);
+
+				// set the background color for new image to transparent
+				imagecolortransparent($dst_image_rs, $transparent_index);
+
+				return $dst_image_rs;
+			}
+
+			// always make a transparent background color for PNGs that don't have one allocated already
+			if ($image_type == IMAGETYPE_PNG) {
+				// turn off transparency blending (temporarily)
+				imagealphablending($dst_image_rs, false);
+
+				// create a new transparent color for image
+				$transparent_color = imagecolorallocatealpha($dst_image_rs, 0, 0, 0, 127);
+
+				// completely fill the background of the new image with allocated color
+				imagefill($dst_image_rs, 0, 0, $transparent_color);
+
+				// restore transparency blending
+				imagesavealpha($dst_image_rs, true);
+			}
+
+			return $dst_image_rs;
+		}
+
+		/**
 		 * Fills margins (if any) of resized are with given color
 		 *
 		 * @param resource $src_image_rs resized image resource
 		 * @param Array $params crop parameters
 		 * @return resource
 		 */
 		function &_applyFill(&$src_image_rs, $params)
 		{
 			$x_position = round(($params['max_width'] - $params['target_width']) / 2); // center
 			$y_position = round(($params['max_height'] - $params['target_height']) / 2); // center
 
 			// crop resized image
 			$fill_image_rs = imagecreatetruecolor($params['max_width'], $params['max_height']);
 
 			$fill = $params['fill'];
 
 			if (substr($fill, 0, 1) == '#') {
 				// hexdecimal color
 				$color = imagecolorallocate($fill_image_rs, hexdec( substr($fill, 1, 2) ), hexdec( substr($fill, 3, 2) ), hexdec( substr($fill, 5, 2) ));
 			}
 			else {
 				// for now we don't support color names, but we will in future
 				return $src_image_rs;
 			}
 
 			imagefill($fill_image_rs, 0, 0, $color);
 			imagecopy($fill_image_rs, $src_image_rs, $x_position, $y_position, 0, 0, $params['target_width'], $params['target_height']);
 
 			return $fill_image_rs;
 		}
 
 		/**
 		 * Crop given image resource using given params and return resulting image resource
 		 *
 		 * @param resource $src_image_rs resized image resource
 		 * @param Array $params crop parameters
 		 * @return resource
 		 */
 		function &_cropImage(&$src_image_rs, $params)
 		{
 			if ($params['crop_x'] == 'c') {
 				$x_position = round(($params['max_width'] - $params['target_width']) / 2); // center
 			}
 			elseif ($params['crop_x'] >= 0) {
 				$x_position = $params['crop_x']; // margin from left
 			}
 			else {
 				$x_position = $params['target_width'] - ($params['max_width'] - $params['crop_x']); // margin from right
 			}
 
 			if ($params['crop_y'] == 'c') {
 				$y_position = round(($params['max_height'] - $params['target_height']) / 2); // center
 			}
 			elseif ($params['crop_y'] >= 0) {
 				$y_position = $params['crop_y']; // margin from top
 			}
 			else {
 				$y_position = $params['target_height'] - ($params['max_height'] - $params['crop_y']); // margin from bottom
 			}
 
 			// crop resized image
 			$crop_image_rs = imagecreatetruecolor($params['max_width'], $params['max_height']);
 			$crop_image_rs =& $this->_applyFill($crop_image_rs, $params);
 
 			imagecopy($crop_image_rs, $src_image_rs, $x_position, $y_position, 0, 0, $params['target_width'], $params['target_height']);
 
 			return $crop_image_rs;
 		}
 
 		/**
 		 * Apply watermark (transparent PNG image) to given resized image resource
 		 *
 		 * @param resource $src_image_rs
 		 * @param int $max_width
 		 * @param int $max_height
 		 * @param Array $params
 		 * @return resource
 		 */
 		function &_applyWatermark(&$src_image_rs, $max_width, $max_height, $params)
 		{
 			$watermark_file = array_key_exists('wm_filename', $params) ? $params['wm_filename'] : false;
 
 			if (!$watermark_file || !file_exists($watermark_file)) {
 				// no watermark required, or provided watermark image is missing
 				return $src_image_rs;
 			}
 
 			$watermark_img_rs = imagecreatefrompng($watermark_file);
 			list ($watermark_width, $watermark_height) = $this->getImageInfo($watermark_file);
 
 			imagealphablending($src_image_rs, true);
 
 			if ($params['h_margin'] == 'c') {
 				$x_position = round($max_width / 2 - $watermark_width / 2); // center
 			}
 			elseif ($params['h_margin'] >= 0) {
 				$x_position = $params['h_margin']; // margin from left
 			}
 			else {
 				$x_position = $max_width - ($watermark_width - $params['h_margin']); // margin from right
 			}
 
 			if ($params['v_margin'] == 'c') {
 				$y_position = round($max_height / 2 - $watermark_height / 2); // center
 			}
 			elseif ($params['v_margin'] >= 0) {
 				$y_position = $params['v_margin']; // margin from top
 			}
 			else {
 				$y_position = $max_height - ($watermark_height - $params['v_margin']); // margin from bottom
 			}
 
 			imagecopy($src_image_rs, $watermark_img_rs, $x_position, $y_position, 0, 0, $watermark_width, $watermark_height);
 
 			return $src_image_rs;
 		}
 
 		/**
 		 * Returns destination image size without actual resizing (useful for <img .../> HTML tag)
 		 *
 		 * @param string $src_image full path to source image (already existing)
 		 * @param int $dst_width destination image width (in pixels)
 		 * @param int $dst_height destination image height (in pixels)
 		 * @param Array $params
 		 * @return Array resized image dimensions (0 - width, 1 - height)
 		 */
 		function GetImageDimensions($src_image, $dst_width, $dst_height, $params)
 		{
 			$image_info = $this->getImageInfo($src_image);
 			if (!$image_info) {
 				return false;
 			}
 
 			$orig_width = $image_info[0];
 			$orig_height = $image_info[1];
 
 			$too_large = is_numeric($dst_width) ? ($orig_width > $dst_width) : false;
 			$too_large = $too_large || (is_numeric($dst_height) ? ($orig_height > $dst_height) : false);
 
 			if ($too_large) {
 				$width_ratio = $dst_width ? $dst_width / $orig_width : 1;
 				$height_ratio = $dst_height ? $dst_height / $orig_height : 1;
 
 				if (array_key_exists('crop_x', $params) || array_key_exists('crop_y', $params)) {
 					// resize by smallest inverted radio
 					$resize_by = $this->_getCropImageMinRatio($image_info, $dst_width, $dst_height);
 					$ratio = $resize_by == 'width' ? $width_ratio : $height_ratio;
 				}
 				else {
 					$ratio = min($width_ratio, $height_ratio);
 				}
 
 				$width = ceil($orig_width * $ratio);
 				$height = ceil($orig_height * $ratio);
 			}
 			else {
 				$width = $orig_width;
 				$height = $orig_height;
 			}
 
 			return Array ($width, $height, $too_large);
 		}
 
 		/**
 		 * Returns ratio type with smaller relation of original size to target size
 		 *
 		 * @param Array $image_info image information from "ImageHelper::getImageInfo"
 		 * @param int $dst_width destination image width (in pixels)
 		 * @param int $dst_height destination image height (in pixels)
 		 * @return Array
 		 */
 		function _getCropImageMinRatio($image_info, $dst_width, $dst_height)
 		{
 			$width_ratio = $dst_width ? $image_info[0] / $dst_width : 1;
 			$height_ratio = $dst_height ? $image_info[1] / $dst_height : 1;
 
 			return $width_ratio < $height_ratio ? 'width' : 'height';
 		}
 
 		/**
 		 * Returns image dimensions + checks if given file is existing image
 		 *
 		 * @param string $src_image full path to source image (already existing)
 		 * @return mixed
 		 */
 		function getImageInfo($src_image)
 		{
 			if (!file_exists($src_image)) {
 				return false;
 			}
 
 			$image_info = @getimagesize($src_image);
 			if (!$image_info) {
 				trigger_error('Image <b>'.$src_image.'</b> <span class="debug_error">missing or invalid</span>', E_USER_WARNING);
 				return false;
 			}
 
 			return $image_info;
 		}
 
 		/**
 		 * Returns maximal image size (width & height) among fields specified
 		 *
 		 * @param kDBItem $object
 		 * @param string $fields
 		 * @param string $format any format, that returns full url (e.g. files_resized:WxH, resize:WxH, full_url, full_urls)
 		 * @return string
 		 */
 		function MaxImageSize(&$object, $fields, $format = null)
 		{
 			static $cached_sizes = Array ();
 
 			$cache_key = $object->getPrefixSpecial().'_'.$object->GetID();
 			if (!isset($cached_sizes[$cache_key])) {
 				$images = Array ();
 
 				$fields = explode(',', $fields);
 				foreach ($fields as $field) {
 					$image_data = $object->GetField($field, $format);
 					if (!$image_data) {
 						continue;
 					}
 
 					$images = array_merge($images, explode('|', $image_data));
 				}
 
 				$max_width = 0;
 				$max_height = 0;
 				$base_url = rtrim($this->Application->BaseURL(), '/');
 
 				foreach ($images as $image_url) {
 					$image_path = preg_replace('/^'.preg_quote($base_url, '/').'(.*)/', FULL_PATH.'\\1', $image_url);
 					$image_info = $this->getImageInfo($image_path);
 					$max_width = max($max_width, $image_info[0]);
 					$max_height = max($max_height, $image_info[1]);
 				}
 
 				$cached_sizes[$cache_key] = Array ($max_width, $max_height);
 			}
 
 			return $cached_sizes[$cache_key];
 		}
 
 		/**
 		 * Puts existing item images (from subitem) to virtual fields (in main item)
 		 *
 		 * @param kCatDBItem $object
 		 */
 		function LoadItemImages(&$object)
 		{
 			if (!$this->_canUseImages($object)) {
 				return ;
 			}
 
 			$max_image_count = $this->Application->ConfigValue($object->Prefix.'_MaxImageCount');
 
 			$sql = 'SELECT *
 					FROM '.TABLE_PREFIX.'Images
 					WHERE ResourceId = '.$object->GetDBField('ResourceId').'
 					ORDER BY Priority DESC
 					LIMIT 0, ' . (int)$max_image_count;
 			$item_images = $this->Conn->Query($sql);
 
 			$image_counter = 1;
 			foreach ($item_images as $item_image) {
 				$image_path = $item_image['ThumbPath'];
 				if ($item_image['DefaultImg'] == 1 || $item_image['Name'] == 'main') {
 					// process primary image separately
 					if (array_key_exists('PrimaryImage', $object->Fields)) {
 						$object->SetDBField('PrimaryImage', $image_path);
 						$object->SetOriginalField('PrimaryImage', $image_path);
 						$object->Fields['PrimaryImage']['original_field'] = $item_image['Name'];
 
 						$this->_loadCustomFields($object, $item_image, 0);
 					}
 					continue;
 				}
 
 				if (abs($item_image['Priority'])) {
 					// use Priority as image counter, when specified
 					$image_counter = abs($item_image['Priority']);
 				}
 
 				if (array_key_exists('Image'.$image_counter, $object->Fields)) {
 					$object->SetDBField('Image'.$image_counter, $image_path);
 					$object->SetOriginalField('Image'.$image_counter, $image_path);
 					$object->Fields['Image'.$image_counter]['original_field'] = $item_image['Name'];
 
 					$this->_loadCustomFields($object, $item_image, $image_counter);
 				}
 				$image_counter++;
 			}
 		}
 
 		/**
 		 * Saves newly uploaded images to external image table
 		 *
 		 * @param kCatDBItem $object
 		 */
 		function SaveItemImages(&$object)
 		{
 			if (!$this->_canUseImages($object)) {
 				return ;
 			}
 
 			$table_name = $this->Application->getUnitOption('img', 'TableName');
 			$max_image_count = $this->Application->getUnitOption($object->Prefix, 'ImageCount'); // $this->Application->ConfigValue($object->Prefix.'_MaxImageCount');
 
 			$i = 0;
 			while ($i < $max_image_count) {
 				$field = $i ? 'Image'.$i : 'PrimaryImage';
 				$field_options = $object->GetFieldOptions($field);
 
 				$image_src = $object->GetDBField($field);
 				if ($image_src) {
 					if (isset($field_options['original_field'])) {
 						$key_clause = 'Name = '.$this->Conn->qstr($field_options['original_field']).' AND ResourceId = '.$object->GetDBField('ResourceId');
 
 						if ($object->GetDBField('Delete'.$field)) {
 							// if item was cloned, then new filename is in db (not in $image_src)
 							$sql = 'SELECT ThumbPath
 									FROM '.$table_name.'
 									WHERE '.$key_clause;
 							$image_src = $this->Conn->GetOne($sql);
 							if (@unlink(FULL_PATH.$image_src)) {
 								$sql = 'DELETE FROM '.$table_name.'
 										WHERE '.$key_clause;
 								$this->Conn->Query($sql);
 							}
 						}
 						else {
 							// image record found -> update
 							$fields_hash = Array (
 								'ThumbPath' => $image_src,
 							);
 							$this->_saveCustomFields($object, $fields_hash, $i);
 
 							$this->Conn->doUpdate($fields_hash, $table_name, $key_clause);
 						}
 					}
 					else {
 						// image record not found -> create
 						$fields_hash = Array (
 							'ResourceId' => $object->GetDBField('ResourceId'),
 							'Name' => $field,
 							'AltName' => $field,
 							'Enabled' => STATUS_ACTIVE,
 							'DefaultImg' => $i ? 0 : 1, // first image is primary, others not primary
 							'ThumbPath' => $image_src,
 							'Priority' => ($i == 0)? 0 : $i * (-1),
 						);
 						$this->_saveCustomFields($object, $fields_hash, $i);
 
 						$this->Conn->doInsert($fields_hash, $table_name);
 						$field_options['original_field'] = $field;
 						$object->SetFieldOptions($field, $field_options);
 					}
 				}
 				$i++;
 			}
 		}
 
 		/**
 		 * Adds ability to load custom fields along with main image field
 		 *
 		 * @param kCatDBItem $object
 		 * @param Array $fields_hash
 		 * @param int $counter 0 - primary image, other number - additional image number
 		 */
 		function _loadCustomFields(&$object, $fields_hash, $counter)
 		{
 			$field_name = $counter ? 'Image' . $counter . 'Alt' : 'PrimaryImageAlt';
 
 			$object->SetDBField($field_name, (string)$fields_hash['AltName']);
 		}
 
 		/**
 		 * Adds ability to save custom field along with main image save
 		 *
 		 * @param kCatDBItem $object
 		 * @param Array $fields_hash
 		 * @param int $counter 0 - primary image, other number - additional image number
 		 */
 		function _saveCustomFields(&$object, &$fields_hash, $counter)
 		{
 			$field_name = $counter ? 'Image' . $counter . 'Alt' : 'PrimaryImageAlt';
 
 			$fields_hash['AltName'] = (string)$object->GetDBField($field_name);
 		}
 
 		/**
 		 * Checks, that item can use image upload capabilities
 		 *
 		 * @param kCatDBItem $object
 		 * @return bool
 		 */
 		function _canUseImages(&$object)
 		{
 			$prefix = $object->Prefix == 'p' ? 'img' : $object->Prefix . '-img';
 
 			return $this->Application->prefixRegistred($prefix);
 		}
 	}
\ No newline at end of file