<?php
// (c) Copyright 2002-2010 by authors of the Tiki Wiki/CMS/Groupware Project
// 
// All Rights Reserved. See copyright.txt for details and a complete list of authors.
// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
// $Id: imagegallib.php 31215 2010-12-06 21:39:17Z sylvieg $

//this script may only be included - so its better to die if called directly.
if (strpos($_SERVER["SCRIPT_NAME"],basename(__FILE__)) !== false) {
  header("location: index.php");
  exit;
}

include_once('lib/reportslib.php');

class ImageGalsLib extends TikiLib
{
	function __construct() {
		parent::__construct();
		global $prefs;

		$exts=get_loaded_extensions();

		// Which GD Version do we have?
		if (in_array('gd',$exts)) {
			$this->havegd = true;

			if (function_exists("gd_info")) {
				$this->gdinfo = gd_info();

				preg_match("/[0-9]+\.[0-9]+/", $this->gdinfo["GD Version"], $gdversiontmp);
				$this->gdversion = $gdversiontmp[0];
			} else {
				//next try
				ob_start();

				phpinfo (INFO_MODULES);

				if (preg_match('/GD Version.*2.0/', ob_get_contents())) {
					$this->gdversion = "2.0";
				} else {
					// I have no experience ... maybe someone knows better
					$this->gdversion = "1.0";
				}

				$this->gdinfo["JPG Support"] = preg_match('/JPE?G Support.*enabled/', ob_get_contents());
				$this->gdinfo["PNG Support"] = preg_match('/PNG Support.*enabled/', ob_get_contents());
				$this->gdinfo["GIF Create Support"] = preg_match('/GIF Create Support.*enabled/', ob_get_contents());
				$this->gdinfo["WBMP Support"] = preg_match('/WBMP Support.*enabled/', ob_get_contents());
				$this->gdinfo["XBM Support"] = preg_match('/XBM Support.*enabled/', ob_get_contents());
				ob_end_clean();
			}
		} else {
			$this->havegd = false;
		}

		// Do we have the imagick PECL module?
		// Module can be downloaded at http://pecl.php.net/package/imagick
		// Also check on 'imagick_rotate' function because the first check may detect imagick 2.x which has a completely different API
		if ( in_array('imagick',$exts) && function_exists('imagick_rotate') ) {
			$this->haveimagick = true;
		} else {
			$this->haveimagick = false;
		}

		//what shall we use?

		//$this->uselib = "gd";
		$this->uselib = $prefs['gal_use_lib'];

		//Fallback to GD
		if ($this->uselib == "imagick" && $this->haveimagick == false) {
			$this->uselib = "gd";
			$this->set_preference('gal_use_lib', 'gd');
		}

		if ($this->uselib == "imagick") {
			$this->canrotate = true;
		} else {
			$this->canrotate = false;
		}

		// get variables to determine if we can upload and how many data
		// we can upload
		$this->file_uploads=ini_get('file_uploads');
		$this->upload_max_filesize=ini_get('upload_max_filesize');
		$this->post_max_size=ini_get('post_max_size');
		if($this->file_uploads==0) {
		   $this->max_img_upload_size=0;
		} else {
		}

	}

	function max_img_upload_size() {
		global $tikilib;
	   $this->upload_max_filesize=$tikilib->return_bytes($this->upload_max_filesize);
	   $this->post_max_size=$tikilib->return_bytes($this->post_max_size);
	   if($this->file_uploads==0) {
		  return(0);
	   } else {
		  return(($this->post_max_size > $this->upload_max_filesize) ? $this->post_max_size : $this->upload_max_filesize);
	   }
	}

	// Features
	function canrotate() {
		return $this->canrotate;
	}

	//
	// Wrappers
	//
	function validhandle() {
		if (isset($this->imagehandle)) {
			if ($this->uselib == "imagick") {
				// seems not to work in imagick 0.95 aahrgh
				if (imagick_iserror($this->imagehandle))
					return false;

				return true;
			} else if ($this->uselib == "gd") {
				if (imagesx($this->imagehandle) == 0)
					return false;

				return true;
			}
		}

		return false;
	}

	function readimagefromstring() {
		if (!isset($this->image)) {
			return false;
		}

		//avoid error messages
		if (isset($this->filetype)) {
			if (!$this->issupported($this->filetype)) {
				return false;
			}
		}

		if ($this->uselib == "imagick") {
			$this->imagehandle = imagick_blob2image($this->image);
		} else if ($this->uselib == "gd") {
			$this->imagehandle = imagecreatefromstring($this->image);
		}
	}

	function writeimagetostring() {
		if ($this->uselib == "imagick") {
			$this->image = imagick_image2blob($this->imagehandle);
		} else if ($this->uselib == "gd") {
			ob_start();

			imagejpeg ($this->imagehandle);
			$this->image = ob_get_contents();
			ob_end_clean();
		}
	}

	function readimagefromfile($fname) {
		@$fp = fopen($fname, "rb");

		if ($fp) {
			$size = filesize($fname);

			$this->image = fread($fp, $size);
			fclose ($fp);
			// convert to imagehandle to be able to check if its 
			// valid image data
			$this->readimagefromstring();
			// check if imagehandle is a image:
			return($this->validhandle());
		} else {
			return false;
		}
	}

	// for piping out a image
	function pipeimage($fname) {
		$fp = fopen($fname, "rb");

		$size = filesize($fname);
		$this->image = fread($fp, $size);
		fclose ($fp);
		$this->readimagefromstring();

		if($this->validhandle()) echo $data;
	}

	//Get sizes. Image must be loaded before
	function getimageinfo() {
		if ($this->uselib == "imagick") {
			$this->filetype = imagick_getmimetype($this->imagehandle);

			$this->xsize = imagick_getwidth($this->imagehandle);
			$this->ysize = imagick_getheight($this->imagehandle);
		} else if ($this->uselib == "gd") {
			$this->xsize = imagesx($this->imagehandle);

			$this->ysize = imagesy($this->imagehandle);
		}
	}

	//Repair Image info. Is called if someone inserts unsupported images (like gif)
	//and switches to imagick
	function repairimageinfo() {
		if (!isset($this->imageId))
			die();

		if (!$this->issupported($this->filetype))
			die();

		$this->getimageinfo();
		//update
		$query = "update `tiki_images_data` set `xsize`=? , `ysize`=? where `imageId`=? and `type`=?";
		$this->query($query,array((int)$this->xsize,(int)$this->ysize,(int)$this->imageId,$this->type));
	}

	// GD can only get the mimetype from the file
	function getfileinfo($fname) {
		$this->filesize = filesize($fname);

		if ($this->uselib == "imagick") {
		} else if ($this->uselib == "gd") {
			unset ($this->filetype);

			$imageinfo = getimagesize($fname);

			if ($imageinfo["0"] > 0 && $imageinfo["1"] > 0 && $imageinfo["2"] > 0) {
				if ($this->gdversion >= 2.0) {
					$this->filetype = $imageinfo["mime"];
				} else {
					$mimetypes = array(
						"1" => "gif",
						"2" => "jpg",
						"3" => "png",
						"4" => "swf",
						"5" => "psd",
						"6" => "bmp",
						"7" => "tiff",
						"8" => "tiff",
						"9" => "jpc",
						"10" => "jp2",
						"11" => "jpx",
						"12" => "jb2",
						"13" => "swc",
						"14" => "iff"
					);

					$this->filetype = "image/" . $mimetypes[$imageinfo["2"]];
				}
			}
		}
	}

	// resize Image
	function resizeImage($newx, $newy) {
		if (!isset($this->imagehandle)) {
			$this->readimagefromstring();
		}

		if (!isset($this->xsize)) {
			$this->getimageinfo();
		}

		if ($this->xsize * $this->ysize == 0)
			$this->repairimageinfo();

		if ($this->uselib == "imagick") {
			if (!imagick_scale($this->imagehandle, $newx, $newy, "!")) {
				$reason = imagick_failedreason($handle);

				$description = imagick_faileddescription($handle);
				// todo: Build in error handler in imagegallib
				exit;
			}
		} else if ($this->uselib == "gd") {
			if ($this->gdversion >= 2.0) {
				$t = imagecreatetruecolor($newx, $newy);

				imagecopyresampled($t, $this->imagehandle, 0, 0, 0, 0, $newx, $newy, $this->xsize, $this->ysize);
			} else {
				$t = imagecreate($newx, $newy);

				$this->ImageCopyResampleBicubic($t, $this->imagehandle, 0, 0, 0, 0, $newx, $newy, $this->xsize, $this->ysize);
			}

			$this->imagehandle = $t;
		}

		// fill $this->image for writing or output
		$this->writeimagetostring();
		// reget sizes
		$this->getimageinfo();
		//set new sizes
		$this->xsize = $newx;
		$this->ysize = $newy;
		return true;
	}

	// rescale Image, almost the same as resize, but keeps apect ratio
	// bbx and bby give the boundary box
	function rescaleImage($bbx, $bby) {
		if (!$bbx || !$bby)
			return true;
		if (!isset($this->imagehandle)) {
			$this->readimagefromstring();
		}
		if (!isset($this->xsize)) {
			$this->getimageinfo();
		}

		if ($this->xsize * $this->ysize == 0)
			$this->repairimageinfo();

		if ($this->xsize > $this->ysize) {
			$tscale = ((int)$this->xsize / $bbx);
		} else {
			$tscale = ((int)$this->ysize / $bby);
		}

		$newx = round($this->xsize / $tscale);
		$newy = round($this->ysize / $tscale);
		if ($newx > $this->xsize && $newy > $this->ysize)
			return true;
		return $this->resizeImage($newx, $newy);
	}

	function rotateimage($angle) {
		if ($this->uselib == "imagick") {
			//Imagick and GD have different opinion what is 90 degree. right or left?
			imagick_rotate($this->imagehandle, -$angle);
		} else if ($this->uselib == "gd") {
			if ($this->gdversion > 2.0) { //I know, it's PHP <= 4.3.0. It destroys images if u try to rotate them
				$this->imagehandle = imagerotate($this->imagehandle, $angle, 0);
			}
		}

		// update the $this->image
		$this->writeimagetostring();
		//get new sizex,sizey
		$this->oldxsize = $this->xsize;
		$this->oldysize = $this->ysize;
		$this->getimageinfo();
	}

	// function to determine supported image types
	// imagick has no function to get the supported image types
	function issupported($imagetype) {
		if ($this->uselib == "imagick") {
			//imagick can read everything ... we assume
			return true;
		} else if ( $this->uselib == "gd" &&
								$this->havegd == true ) {
			switch (strtolower($imagetype)) {
				case 'jpeg':
				case 'pjpeg':
				case 'jpg':
				case 'image/jpeg':
				case 'image/pjpeg':
				case 'image/jpg':
					return ($this->gdinfo["JPG Support"] || $this->gdinfo["JPEG Support"]);
					break;
				case 'png':
				case 'image/png':
					return ($this->gdinfo["PNG Support"]);
					break;
				case 'gif':
				case 'image/gif':
					return ($this->gdinfo["GIF Create Support"]);
					break;
				case 'bmp':
				case 'image/bmp':
					return ($this->gdinfo["WBMP Support"]);
					break;
				case 'xbm':
				case 'image/xbm':
					return ($this->gdinfo["XBM Support"]);
					break;
				default:
					return false;
					break;
			}
		} else {
			return false;
		}
	}

	// Batch image uploads todo
	function process_batch_image_upload($galleryId, $file, $user) {
		global $prefs;

		$numimages = 0;
		include_once ('lib/pclzip/pclzip.lib.php');
		$archive = new PclZip($file);
		// Read Archive contents
		$ziplist = $archive->listContent();

		if (!$ziplist)
			return (false); // Archive invalid

		foreach($ziplist as $zipfile) {
			$file = $zipfile["filename"];

			if (!$zipfile["folder"]) {
				//copied
				$gal_info = $this->get_gallery($galleryId);

				$upl = 1;

				if (!empty($prefs['gal_match_regex'])) {
					if (!preg_match('/'.$prefs['gal_match_regex'].'/', $file, $reqs))
						$upl = 0;
				}

				if (!empty($prefs['gal_nmatch_regex'])) {
					if (preg_match('/'.$prefs['gal_nmatch_regex'].'/', $file, $reqs))
						$upl = 0;
				}
				//extract file
				$archive->extractByIndex($zipfile["index"],
					$prefs['tmpDir'], dirname($file)); //extract and remove (dangerous) pathname
				$file = basename($file);

				//unset variables
				unset ($this->filetype);
				unset ($this->xsize);
				unset ($this->ysize);

				//determine filetype and dimensions
				$this->getfileinfo($prefs['tmpDir'] . "/" . $file);
				
				$foo=explode(".",$file);
				$exp=end($foo);
				// read image and delete it after
				$this->readimagefromfile($prefs['tmpDir'] . "/" . $file);
				unlink ($prefs['tmpDir'] . "/" . $file);

				if ($this->issupported($exp)) {
					// convert to handle
					$this->readimagefromstring();

					if ($this->validhandle()) {
						$this->getimageinfo();
					}
				}

				//if there is no mimetype, we don't got a image
				if (isset($this->filetype)) {
					if (!isset($this->xsize)) {
						$this->xsize = $this->ysize = 0;
					}

					$imageId = $this->insert_image($galleryId, $file,
						'', $file, $this->filetype, $this->image, $this->filesize, $this->xsize, $this->ysize, $user, '', '', NULL, NULL,$gal_info);

					$numimages++;
				}
			}
		}

		return $numimages;
	}

	function add_image_hit($id) {
		global $prefs, $user;

		if ($prefs['count_admin_pvs'] == 'y' || $user != 'admin') {
			$query = "update `tiki_images` set `hits`=`hits`+1 where `imageId`=?";
			$result = $this->query($query,array((int)$id));
		}

		if ($prefs['feature_score'] == 'y') {
			$this->score_event($user, 'igallery_see_img', $id);
			$query = "select `user` from `tiki_images` where `imageId`=?";
			$owner = $this->getOne($query, array((int)$id));
			$this->score_event($owner, 'igallery_img_seen', "$user:$id");
		}

		return true;
	}

	function add_gallery_hit($id) {
		global $prefs, $user;

		if ($prefs['count_admin_pvs'] == 'y' || $user != 'admin') {
			$query = "update `tiki_galleries` set `hits`=`hits`+1 where `galleryId`=?";

			$result = $this->query($query,array((int) $id));
		}

		if ($prefs['feature_score'] == 'y') {
			$this->score_event($user, 'igallery_see', $id);
			$query = "select `user` from `tiki_galleries` where `galleryId`=?";
			$owner = $this->getOne($query, array((int)$id));
			$this->score_event($owner, 'igallery_seen', "$user:$id");
		}

		return true;
	}

	function ImageCopyResampleBicubic(&$dst_img, &$src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h)
	// port to PHP by John Jensen July 10 2001 (updated 4/21/02) -- original code (in C, for the PHP GD Module) by jernberg@fairytale.se////
		{
		$palsize = ImageColorsTotal($src_img);

		for ($i = 0; $i < $palsize; $i++) { // get palette.
			$colors = ImageColorsForIndex($src_img, $i);

			ImageColorAllocate($dst_img, $colors['red'], $colors['green'], $colors['blue']);
		}

		$scaleX = ($src_w - 1) / $dst_w;
		$scaleY = ($src_h - 1) / $dst_h;
		$scaleX2 = (int)($scaleX / 2);
		$scaleY2 = (int)($scaleY / 2);

		for ($j = $src_y; $j < $dst_h; $j++) {
			$sY = (int)($j * $scaleY);

			$y13 = $sY + $scaleY2;

			for ($i = $src_x; $i < $dst_w; $i++) {
				$sX = (int)($i * $scaleX);

				$x34 = $sX + $scaleX2;
				$color1 = ImageColorsForIndex($src_img, ImageColorAt($src_img, $sX, $y13));
				$color2 = ImageColorsForIndex($src_img, ImageColorAt($src_img, $sX, $sY));
				$color3 = ImageColorsForIndex($src_img, ImageColorAt($src_img, $x34, $y13));
				$color4 = ImageColorsForIndex($src_img, ImageColorAt($src_img, $x34, $sY));
				$red = ($color1['red'] + $color2['red'] + $color3['red'] + $color4['red']) / 4;
				$green = ($color1['green'] + $color2['green'] + $color3['green'] + $color4['green']) / 4;
				$blue = ($color1['blue'] + $color2['blue'] + $color3['blue'] + $color4['blue']) / 4;
				ImageSetPixel($dst_img, $i + $dst_x - $src_x, $j + $dst_y - $src_y, ImageColorClosest($dst_img, $red, $green, $blue));
			}
		}
	}

	function store_image_data($overwrite = false) {
		global $prefs;

		$size = strlen($this->image);
		$fhash = "";

		if ($prefs['gal_use_db'] == 'y') {
			// Prepare to store data in database
		} else {
			// Store data in directory
			switch ($this->type) {
			case 't':
				$ext = ".thumb";

				break;

			case 's':
				$ext = ".scaled_" . $this->xsize . "x" . $this->ysize;

				break;

			case 'b':
				// for future use
				$ext = ".backup";

				break;

			default:
				$ext = '';
			}

			$fhash = $this->path . $ext; //Path+extension
			@$fw = fopen($prefs['gal_use_dir'] . $fhash, "wb");

			if (!$fw) {
				return false;
			}

			fwrite($fw, $this->image);
			fclose ($fw);
			$data = '';
		}

		$this->filename = $this->xsize . "x" . $this->ysize . "_" . $this->name; // rebuild filename for downloading images
		// insert data
		$fn = $this->filename;

		if ($overwrite) {
			//overwrites all except the colums of the primary key
			//if there is no oldxsize, we use xsize
			if (!isset($this->oldxsize)) {
				$this->oldxsize = $this->xsize;

				$this->oldysize = $this->ysize;
			}

			$query = "update `tiki_images_data` set `filetype`=?,
					`filename`=?,`data`=?,
					`filesize`=? ,`xsize`=?, 
					`ysize`=?
				where
					`imageId`=? and `type`=? and
					`xsize`=? and `ysize`=?";
			$bindvars=array($this->filetype,$this->filename,($prefs['gal_use_db'] == 'y')?$this->image:'',(int)$size,(int)$this->xsize,(int)$this->ysize,(int)$this->imageId,$this->type,(int)$this->oldxsize,(int)$this->oldysize);
		} else {
			$query = "insert into `tiki_images_data`(`imageId`,`xsize`,`ysize`,
							`type`,`filesize`,`filetype`,`filename`,`data`)
							values (?,?,?,?,?,?,?,?)";
			$bindvars=array((int)$this->imageId,(int)$this->xsize,(int)$this->ysize,$this->type,(int)$size,$this->filetype,$this->filename,($prefs['gal_use_db'] == 'y')?$this->image:'');
		}

		$result = $this->query($query,$bindvars);
		return true;
	}

	function rebuild_image($imageid, $itype, $xsize, $ysize=0) {
		global $prefs;
	        
		$galid = $this->get_gallery_from_image($imageid);
		if($ysize==0) {
			$ysize=$xsize;
		}

		//we don't rebuild original images
		if ($itype == 'o')
			return false;

		//if it is a scaled image, test the gallery settings
		if ($itype == 's') {
			$hasscale = false;

			if ($prefs["preset_galleries_info"] == 'y' && $prefs["scaleSizeGalleries"] > 0) {
				$scaleinfo = $prefs["scaleSizeGalleries"];
				if ((($scaleinfo == $xsize) && ($scaleinfo >= $ysize)) || (($scaleinfo == $ysize) && ($scaleinfo >= $xsize))) {
					$hasscale = true;
					$newx = $scaleinfo;
					$newy = $scaleinfo;
				}
			} else {
				$scaleinfo = $this->get_gallery_scale_info($galid);
				while (list($num, $sci) = each($scaleinfo)) {
					if ((($sci['scale'] == $xsize) && ($sci['scale'] >= $ysize)) || 
							(($sci['scale'] == $ysize) && ($sci['scale'] >= $xsize))) {
						$hasscale = true;
						$newx = $sci['scale'];
						$newy = $sci['scale'];
					}
				}
			}

			if (!$hasscale) {
				return false;
			}
		}

		// now we can start rebuilding the image
		//if(!function_exists("ImageCreateFromString")) return false;
		#get image and other infos
		$this->get_image($imageid);
		$galinfo = $this->get_gallery_info($galid);

		// determine new size
		if ($itype == 't') {
			$newx = $galinfo["thumbSizeX"];
			$newy = $galinfo["thumbSizeY"];
		}

		// do it
		if ($this->issupported($this->filetype)) {
			if (!$this->rescaleImage($newx, $newy)) {
				die;
			}
		} else {
			// filetype is not supported, but we store the data
			// assiming newx,newy as new size
			$this->xsize = $newx;
			$this->ysize = $newy;
		}

		// we always rescale to jpegs.
		$t_type = 'image/jpeg';

		// some more infos
		$filename = $this->filename; // filename of original image
		$this->type = $itype;

		//store (needs overwrite param to be true to update, not create new)
		$this->store_image_data(true);

		//return new size
		$newsize["xsize"] = $this->xsize;
		$newsize["ysize"] = $this->ysize;
		return $newsize;
	}

	function rebuild_thumbnails($galleryId) {
		global $prefs;

		// rewritten by flo
		$query = "select `imageId`, `path` from `tiki_images` where `galleryId`=?";
		$result = $this->query($query,array((int)$galleryId));

		while ($res = $result->fetchRow()) {
			$query2 = "delete from `tiki_images_data` where `imageId`=? and `type`=?";

			$result2 = $this->query($query2,array((int)$res["imageId"],'t'));

			if (strlen($res["path"]) > 0) {
				$ftn = $prefs['gal_use_dir'] . $res["path"] . ".thumb";

				if (file_exists($ftn)) {
					unlink ($ftn);
				}
			}
		}

		return true;
	}

	function rebuild_scales($galleryId, $imageId = -1) {
		// doesn't really rebuild, it deletes the scales and thumbs for 
		// automatic rebuild
		// give either a galleryId for rebuild complete gallery or
		// a imageId for a image rebuild
		global $prefs;
		if ($imageId == -1) {
			//gallery mode
			//mysql does'nt have subqueries. Bad.
			$bindvars=array();
			$query1 = "select `imageId`,`path` from `tiki_images`";
			if($galleryId>-1) { // if galleryid == -1 then all galleries
				$query1 .= ' where `galleryId`=?';
				$bindvars=array((int)$galleryId);
			}

			$result1 = $this->query($query1,$bindvars);

			while ($res = $result1->fetchRow()) {
				$query2 = 'select `xsize`,`ysize`,`type` from `tiki_images_data` where `imageId`=? and not (`type`=?)';
				$query3 = "delete from `tiki_images_data` where `imageId`=? and not (`type`=?)";
				$bindvars2=array((int)$res["imageId"],'o');

				$result2 = $this->query($query2,$bindvars2);
				while($res2=$result2->fetchRow()) {
					if(!empty($res['path'])) {
						if($res2['type']=='s') { $ext = ".scaled_" . $res2['xsize'] . "x" . $res2['ysize'];}
						if($res2['type']=='t') { $ext = ".thumb";}
						if($res2['type']=='s' || $res2['type']=='t') { // in case we add other types later
							@unlink($prefs['gal_use_dir'].$res['path'].$ext );
						}
					}
				}
				// delete images_data entries
				$result3 = $this->query($query3,$bindvars2);
			}
		} else {
			//image mode
			$query = "delete from `tiki_images_data` where `ImageId`=? and not `type`=?";

			$result = $this->query($query,array((int)$ImageId,'o'));
		}
	}

	function edit_image($id, $name, $description, $lat=NULL, $lon=NULL, $file=NULL) {
		global $prefs;
		$name = strip_tags($name);

		$description = strip_tags($description);
		$query = "update `tiki_images` set `name`=?, `description`=?, `lat`=?, `lon`=? where `imageId` = ?";
		$result = $this->query($query,array($name,$description,(float)$lat,(float)$lon,(int)$id));
		if (!empty($file) && !empty($file['name'])) {
			if (!is_uploaded_file($file['tmp_name']) || !($fp = fopen($file['tmp_name'], "rb")))
				return false;
			$data =  fread($fp, $file['size']);
			$etag = md5($data);
			fclose($fp);
			if ($prefs['gal_use_db'] == 'y') {
				$query = "update `tiki_images_data` set `data`=?, `etag`=?, `filename`=? where `imageId` = ? and `type`=?";
				$result = $this->query($query,array($data, $etag, $file['name'], (int)$id, 'o'));
			} else {
				$query = "select `path` from `tiki_images` where `imageId`=?";
				$path = $this->getOne($query, $id);
				if (!move_uploaded_file($file['tmp_name'], $prefs['gal_use_dir'].$path)) {
					return false;
				}
				$query = "update `tiki_images_data` set `etag`=?,`filename`=? where `imageId` = ? and `type`=?";
				$result = $this->query($query,array($etag, $file['name'], (int)$id, 'o'));
			}
			$query = "delete from `tiki_images_data` where `imageId`=? and `type`!=?";
			$result = $this->query($query, array((int)$id, 'o'));
		}

		if ( $prefs['feature_search'] == 'y' && $prefs['feature_search_fulltext'] != 'y' && $prefs['search_refresh_index_mode'] == 'normal' ) {
			require_once('lib/search/refresh-functions.php');
			refresh_index('images', $id);
		}

		return true;
	}

	function insert_image($galleryId, $name, $description, $filename, $filetype, &$data, $size, $xsize, $ysize, $user, $t_data, $t_type ,$lat=NULL, $lon=NULL, $gal_info=NULL) {
		global $prefs;

		$name = strip_tags($name);
		$description = strip_tags($description);
		if ($t_data && is_string($t_data)) {
			$t_data = array('data' => $t_data, 'xsize' => 0, 'ysize' => 0);
		}
		$path = '';

		if ($prefs['gal_use_db'] == 'y') {
			// Prepare to store data in database
		} else {
			// Store data in directory
			$fhash = md5(uniqid($filename));
			if (!($fw = fopen($prefs['gal_use_dir'] . $fhash, "wb"))) {
				return false;
			}
			fwrite($fw, $data);
			fclose ($fw);
			$data = '';

			if ($t_data) {
				if (!($fw = fopen($prefs['gal_use_dir'] . $fhash . '.thumb', "wb"))) {
					return false;
				}
				fwrite($fw, $t_data['data']);
				fclose ($fw);
				$t_data['data'] = '';
			}
			$path = $fhash;
		}

		$query = "insert into `tiki_images`(`galleryId`,`name`,`description`,`user`,`created`,`hits`,`path`,`lat`,`lon`)
		          values(?,?,?,?,?,?,?,?,?)";
		$result = $this->query($query,array((int)$galleryId,$name,$description,$user,(int)$this->now,0,$path,$lat,$lon));
		$query = "select max(`imageId`) from `tiki_images` where `created`=?";
		$imageId = $this->getOne($query,array((int)$this->now));
		// insert data
		//$this->blob_encode($data);
		$query = "insert into `tiki_images_data`(`imageId`,`xsize`,`ysize`, `type`,`filesize`,`filetype`,`filename`,`data`)
		                 values (?,?,?,?,?,?,?,?)";
		$result = $this->query($query,array((int)$imageId,(int)$xsize,(int)$ysize,'o',(int)$size,$filetype,$filename,$data));

		// insert thumb
		if ($t_data) {
			//$this->blob_encode($t_data['data']);
			$query = "insert into `tiki_images_data`(`imageId`,`xsize`,`ysize`, `type`,`filesize`,`filetype`,`filename`,`data`)
			                 values (?,?,?,?,?,?,?,?)";
			$result = $this->query($query,array((int)$imageId,(int)$t_data['xsize'],(int)$t_data['ysize'],'t',(int)$size,$t_type,$filename,$t_data['data']));
		}

		$query = "update `tiki_galleries` set `lastModif`=? where `galleryId`=?";
		$result = $this->query($query,array((int)$this->now,(int)$galleryId));

		if ($prefs['feature_score'] == 'y') {
			$this->score_event($user, 'igallery_new_img');
		}

		if ($prefs['feature_actionlog'] == 'y') {
			global $logslib; include_once('lib/logs/logslib.php');
			$logslib->add_action('Uploaded', $galleryId, 'image gallery', 'imageId='.$imageId);
		}

		if ( $prefs['feature_search'] == 'y' && $prefs['feature_search_fulltext'] != 'y' && $prefs['search_refresh_index_mode'] == 'normal' ) {
			require_once('lib/search/refresh-functions.php');
			refresh_index('images', $imageId);
		}
		
		$this->notify($imageId, $galleryId, $name, $filename, $description, isset($gal_info['name'])?$gal_info['name']: '', 'upload image', $user);

		return $imageId;
	}

	function notify($imageId, $galleryId, $name, $filename, $description, $galleryName, $action, $user) {
		global $prefs, $smarty, $tikilib;
		if ($prefs['feature_user_watches'] == 'y') {
			$event = 'image_gallery_changed';
			$nots = $this->get_event_watches($event, $galleryId);
			
			if ($prefs['feature_daily_report_watches'] == 'y') {
				global $reportslib; include_once ('lib/reportslib.php');
				$reportslib->makeReportCache($nots, array("event"=>$event, "imageId"=>$imageId, "imageName"=>$name, "fileName"=>$filename, "galleryId"=>$galleryId, "galleryName"=>$galleryName, "action"=>$action, "user"=>$user));
			}
			
			include_once('lib/notifications/notificationemaillib.php');
			$smarty->assign_by_ref('galleryId', $galleryId);
			$smarty->assign_by_ref('galleryName', $galleryName);
			$smarty->assign_by_ref('mail_date', date('U'));
			$smarty->assign_by_ref('author', $user);
			$foo = parse_url($_SERVER["REQUEST_URI"]);
			$machine = $tikilib->httpPrefix( true ). dirname( $foo["path"] );
			$smarty->assign_by_ref('mail_machine', $machine);
			$smarty->assign_by_ref('fname', $name);
			$smarty->assign_by_ref('filename', $filename);
			$smarty->assign_by_ref('description', $description);
			$smarty->assign_by_ref('imageId', $imageId);
			sendEmailNotification($nots, 'watch', 'user_watch_image_gallery_changed_subject.tpl', NULL, 'user_watch_image_gallery_upload.tpl');
		}
	}

	function rotate_image($id, $angle) {
		//get image
		global $prefs;

		$this->get_image($id);

		$this->rotateimage($angle);
		$this->store_image_data(true);
		// delete all scaled images. Will be rebuild when requested
		$query = "delete from `tiki_images_data` where `imageId`=? and `type` !=?";
		$result = $this->query($query,array((int)$id,'o'));
	}

	function rotate_right_image($id) {
		$this->rotate_image($id, 270);
	}

	function rotate_left_image($id) {
		$this->rotate_image($id, 90);
	}

	function remove_image($id, $user) {
		global $prefs;

		$path = $this->getOne("select `path` from `tiki_images` where `imageId`=?",array($id));
		$imageInfo = $this->get_image_info($id);
		$gal_info = $this->get_gallery($imageInfo['galleryId']);
		
		if ($path) {
			@unlink ($prefs['gal_use_dir'] . $path);

			@unlink ($prefs['gal_use_dir'] . $path . '.thumb');
			// remove scaled images
			$query = "select i.`path`, d.`xsize`, d.`ysize` from `tiki_images` i, `tiki_images_data` d where i.`imageId`=d.`imageId` and i.`imageId`=? and d.`type`=?";
			$result=$this->query($query,array($id,'s'));
			while($res = $result->fetchRow()) {
				@unlink ($prefs['gal_use_dir'] . $path . '.scaled_'.$res['xsize'].'x'.$res['ysize']);
			}
		}

		$query = "delete from `tiki_images` where `imageId`=?";
		$result = $this->query($query,array((int)$id));
		$query = "delete from `tiki_images_data` where `imageId`=?";
		$result = $this->query($query,array((int)$id));
		$this->remove_object('image', $id);
		$this->notify($imageInfo['imageId'], $imageInfo['galleryId'], $imageInfo['name'], $imageInfo['filename'], $imageInfo['description'], isset($gal_info['name'])?$gal_info['name']: '', 'remove image', $user);
		return true;
	}

	function get_images($offset, $maxRecords, $sort_mode, $find, $galleryId = -1) {

		if ($find) {
			$findesc = '%' . $find . '%';

			$mid = " and (`name` like ? or `description` like ?)";
			$bindvars=array($findesc,$findesc);
		} else {
			$mid = "";
			$bindvars=array();
		}

		if ($galleryId != -1 && is_numeric($galleryId)) {
			$mid .= " and i.`galleryId`=? ";
			$bindvars[]=(int) $galleryId;
		} else if ($galleryId == -1) {//don't show system gallery
			$mid .= 'and i.`galleryId`!=? ';
			$bindvars[] = 0;
		}

		$query_cant = "select count(*) from `tiki_images` i  where 1 $mid";
		$cant = $this->getOne($query_cant, $bindvars);
		$query = "select i.`path` ,i.`imageId`,i.`name`,i.`description`,i.`created`,
		                 d.`filename`,d.`filesize`,d.`xsize`,d.`ysize`,
		                 i.`user`,i.`hits`
		          from `tiki_images` i , `tiki_images_data` d
		          where i.`imageId`=d.`imageId`
		                 $mid
		                 and d.`type`=?
		          order by ".$this->convertSortMode($sort_mode);
		$bindvars[] = 'o';
		$result = $this->query($query,$bindvars,$maxRecords,$offset);
		$ret = array();

		while ($res = $result->fetchRow()) {
			$ret[] = $res;
		}

		$retval = array();
		$retval["data"] = $ret;
		$retval["cant"] = $cant;
		return $retval;
	}

	function get_subgalleries($offset, $maxRecords, $sort_mode, $find, $galleryId = -1) {
		
		if ($sort_mode == '') {
			$sort_mode = 'name_asc';
		} else {		//filesize is for listing images. equivalent is images
			$sort_mode=preg_replace('/(filesize_)/','images_',$sort_mode);
		}

		if ($find) {
			$findesc = '%' . $find . '%';

			$mid = " and (`name` like ? or `description` like ?)";
			$bindvars=array($galleryId,$findesc,$findesc);
		} else {
			$mid = "";
			$bindvars=array($galleryId);
		}

		$query = "select g.`galleryId`,g.`name`,g.`description`,
		            g.`created`,g.`lastModif`,g.`visible`,g.`theme`,g.`user`,
		            g.`hits`,g.`maxRows`,g.`rowImages`,g.`thumbSizeX`,
		            g.`thumbSizeY`,g.`public`,g.`sortorder`,g.`sortdirection`,
		            g.`galleryimage`,g.`parentgallery`,count(i.`imageId`) as images
		          from `tiki_galleries` g, `tiki_images` i
		          where i.`galleryId`=g.`galleryId` and
		            `parentgallery`=? $mid group by 
		            g.`galleryId`, g.`name`,g.`description`,
		            g.`created`,g.`lastModif`,g.`visible`,g.`theme`,g.`user`,
		            g.`hits`,g.`maxRows`,g.`rowImages`,g.`thumbSizeX`,
		            g.`thumbSizeY`,g.`public`,g.`sortorder`,g.`sortdirection`,
		            g.`galleryimage`,g.`parentgallery`
		          order by ".$this->convertSortMode($sort_mode);
		$result = $this->query($query,$bindvars,$maxRecords,$offset);
		$ret = array();

		while ($res = $result->fetchRow()) {
			// get the number of the gallery representation image
			$res['imageId']=$this->get_gallery_image($res['galleryId'],$res['galleryimage']);
			$ret[] = $res;
		}

		$retval = array();
		$retval["data"] = $ret;
		$query_cant = "select count(*) from `tiki_galleries` where `parentgallery`=? $mid";
		$cant = $this->getOne($query_cant,$bindvars);
		$retval["cant"] = $cant;
		return $retval;
	}

	function get_gallery_image($galleryId,$rule='',$sort_mode = '') {
		$query='select i.`imageId` from `tiki_images` i, `tiki_images_data` d
where i.`imageId`=d.`imageId` and i.`galleryId`=? and d.`type`=? order by ';
		/* if sort by filesize while browsing images it needs to be read from tiki_image_data table */
		if ($sort_mode == 'filesize_asc' || $sort_mode == 'filesize_desc') {
			$query.='d.';
		} else {
			$query.='i.';
		}
		$bindvars=array($galleryId,'o');
		switch($rule) {
			case 'firstu':
				// first uploaded
				$query.=$this->convertSortMode('created_asc');
				$imageId=$this->getOne($query,$bindvars);
				break;
			case 'lastu':
				// last uploaded
				$query.=$this->convertSortMode('created_desc');
				$imageId=$this->getOne($query,$bindvars);
				break;
			case 'all':
			case 'first':
				if (!$sort_mode) {
					// first image in default gallery sortorder
					$query2='select `sortorder`,`sortdirection` from `tiki_galleries` where `galleryId`=?';
					$result=$this->query($query2, array($galleryId));
					$res = $result->fetchRow();
					$sort_mode=$res['sortorder'].'_'.$res['sortdirection'];
				}
				$query.=$this->convertSortMode($sort_mode);
				if ($rule != 'all') {
					$imageId=$this->getOne($query,$bindvars);
					break;
				}
				$result=$this->query($query,$bindvars);
				$imageId=array();
				while ($res = $result->fetchRow()) {
					$imageId[]=reset($res);
				}
				break;
			case 'last':
				if ($sort_mode) {
					$invsor = explode('_', $sort_mode);
					$sort_mode = $invsor[0] . '_' . ($invsor[1] == 'asc' ? 'desc' : 'asc');
				} else {
					// last image in default gallery sortorder
					$query2='select `sortorder`,`sortdirection` from `tiki_galleries` where `galleryId`=?';
					$result=$this->query($query2,$bindvars);
					$res = $result->fetchRow();
					if($res['sortdirection'] == 'asc') {
						$res['sortdirection']='desc';
					} else {
						$res['sortdirection']='asc';
					}
					$sort_mode=$res['sortorder'].'_'.$res['sortdirection'];
				}
				$query.=$this->convertSortMode($sort_mode);
				$imageId=$this->getOne($query,$bindvars);
				break;
			case 'random':
				//random image of gallery
				$ret=$this->get_random_image($galleryId);
				$imageId=$ret['imageId'];
				break;
			case 'default':
				//check gallery settings and re-run this function
				$query='select `galleryimage` from `tiki_galleries` where `galleryId`=?';
				$rule=$this->getOne($query,array($galleryId));
				$imageId=$this->get_gallery_image($galleryId,$rule);
				break;
			default:
				// imageId is listed in gallery settings
				if (is_numeric($rule)) {
					$imageId=(int) $rule;
				} else {
					// unknown.
					$imageId=-1;
				}
				break;
			}
			return($imageId);
	}

	function get_prev_and_next_image($sort_mode, $find, $imageId, $galleryId = -1) {

		if ($find) {
			$findesc = '%' . $find . '%';

			$mid = " and (`name` like ? or `description` like ?)";
			$bindvars=array('o',$findesc,$findesc);
		} else {
			$mid = "";
			$bindvars=array('o');
		}

		$midcant = "";
		$cantvars=array();

		if ($galleryId != -1 && is_numeric($galleryId)) {
			$mid .= " and i.`galleryId`=? ";
			$bindvars[]=(int)$galleryId;
			$midcant = "where `galleryId`=? ";
			$cantvars[]=(int)$galleryId;
		}

		$query = "select i.`imageId`
		          from `tiki_images` i , `tiki_images_data` d
		          where i.`imageId`=d.`imageId`
		          and d.`type`=?
		          $mid
		          order by ";
		/* if sort by filesize while browsing images it needs to be read from tiki_image_data table */
		if ($sort_mode == 'filesize_asc' || $sort_mode == 'filesize_desc') {
			$query.='d.';
		} else {
			$query.='i.';
		}
		$query .= $this->convertSortMode($sort_mode);
		$result = $this->query($query,$bindvars);
		$prev=-1; $next=0; $tmpid=0;
		while ($res = $result->fetchRow()) {
			if ($imageId == $res['imageId']) {
				$prev=$tmpid;
			} else if ($prev >= 0) { // $prev is set, so, this one is the next
				$next=$res['imageId'];
				break;
			}
			$tmpid=$res['imageId'];
		}
		return array('prev' => ($prev > 0 ? $prev : 0), 'next' => $next);
	}

	function get_first_image($sort_mode, $find, $galleryId = -1) {

		if ($find) {
			$findesc = '%' . $find . '%';

			$mid = " and (`name` like ? or `description` like ?)";
			$bindvars=array('o',$findesc,$findesc);
		} else {
			$mid = "";
			$bindvars=array('o');
		}

		$midcant = "";
		$cantvars=array();

		if ($galleryId != -1 && is_numeric($galleryId)) {
			$mid .= " and i.`galleryId`=? ";
			$bindvars[]=(int)$galleryId;
			$midcant = "where `galleryId`=? ";
			$cantvars[]=(int)$galleryId;
		}

		$query = "select i.`imageId`
		            from `tiki_images` i , `tiki_images_data` d
		            where i.`imageId`=d.`imageId`
		             and d.`type`=?
		             $mid
		            order by ".$this->convertSortMode($sort_mode);
		$result = $this->query($query,$bindvars,1,0);
		$res = $result->fetchRow();
		return $res['imageId'];
	}

	function get_last_image($sort_mode, $find, $galleryId = -1) {
		if (strstr($sort_mode, 'asc')) {
			$sort_mode = str_replace('asc', 'desc', $sort_mode);
		} else {
			$sort_mode = str_replace('desc', 'asc', $sort_mode);
		}

		if ($find) {
			$findesc = '%' . $find . '%';

			$mid = " and (`name` like ? or `description` like ?)";
			$bindvars=array('o',$findesc,$findesc);
		} else {
			$mid = "";
			$bindvars=array('o');
		}

		$midcant = "";
		$cantvars=array();

		if ($galleryId != -1 && is_numeric($galleryId)) {
			$mid .= " and i.`galleryId`=? ";
			$bindvars[]=(int)$galleryId;
			$midcant = "where `galleryId`=? ";
			$cantvars[]=(int)$galleryId;
		}

		$query = "select i.`imageId`
			        from `tiki_images` i , `tiki_images_data` d
			        where i.`imageId`=d.`imageId`
			          and d.`type`=?
			          $mid
			        order by ".$this->convertSortMode($sort_mode);
		$result = $this->query($query,$bindvars,1,0);
		$res = $result->fetchRow();
		return $res['imageId'];
	}

	function list_images($offset, $maxRecords, $sort_mode, $find, $galleryId = -1) {
		return $this->get_images($offset, $maxRecords, $sort_mode, $find, $galleryId);
	}

	function get_random_image($galleryId = -1) {
		$whgal = "";
		$bindvars = array();
		if (((int)$galleryId) != -1) {
			$whgal = " where `galleryId`=? ";
			$bindvars[] = (int) $galleryId;
		}

		$query = "select count(*) from `tiki_images` $whgal";
		$cant = $this->getOne($query,$bindvars);
		$ret = array();

		if ($cant) {
			$pick = rand(0, $cant - 1);

			$query = "select `imageId` ,`description`, `galleryId`,`name` from `tiki_images` $whgal";
			$result = $this->query($query,$bindvars,1,$pick);
			$res = $result->fetchRow();
			$ret["galleryId"] = $res["galleryId"];
			$ret["imageId"] = $res["imageId"];
			$ret["name"] = $res["name"];
			$ret["description"] = $res["description"];
			$query = "select `name`  from `tiki_galleries` where `galleryId` = ?";
			$ret["gallery"] = $this->getOne($query,array((int)$res["galleryId"]));
		} else {
			$ret["galleryId"] = 0;

			$ret["imageId"] = 0;
			$ret["name"] = tra("No image yet, sorry.");
		}

		return ($ret);
	}

	function list_galleries($offset = 0, $maxRecords = -1, $sort_mode = 'name_desc', $user, $find=false) {
		// If $user is admin then get ALL galleries, if not only user galleries are shown
		global $tiki_p_admin_galleries, $tiki_p_admin;

		$old_sort_mode = '';

		if (in_array($sort_mode, array(
				'images_desc',
				'images_asc'
				))) {
			$old_offset = $offset;

			$old_maxRecords = $maxRecords;
			$old_sort_mode = $sort_mode;
			$sort_mode = 'name_desc';
			$offset = 0;
			$maxRecords = -1;
		}

		// If the user is not admin then select `it` 's own galleries or public galleries
		if (($tiki_p_admin_galleries == 'y') or ($tiki_p_admin == 'y') or ($user == 'admin')) {
			$whuser = "";
			$bindvars=array();
		} else {
			$whuser = "where g.`user`=? or g.public=?";
			$bindvars=array($user,'y');
		}

		if ($find) {
			$findesc = '%' . $find . '%';

			if (empty($whuser)) {
				$whuser = "where g.`name` like ? or g.`description` like ?";
				$bindvars=array($findesc,$findesc);
			} else {
				$whuser .= " and g.`name` like ? or g.`description` like ?";
				$bindvars[]=$findesc;
				$bindvars[]=$findesc;
			}
		}

		// If sort mode is versions then offset is 0, maxRecords is -1 (again) and sort_mode is nil
		// If sort mode is links then offset is 0, maxRecords is -1 (again) and sort_mode is nil
		// If sort mode is backlinks then offset is 0, maxRecords is -1 (again) and sort_mode is nil
		$query = "select g.*, a.`name` as parentgalleryName from `tiki_galleries` g left join `tiki_galleries` a on g.`parentgallery` = a.`galleryId` $whuser order by ".$this->convertSortMode($sort_mode);
		$query_cant = "select count(*) from `tiki_galleries` g $whuser";
		$result = $this->query($query,$bindvars,$maxRecords,$offset);
		$cant = $this->getOne($query_cant,$bindvars);
		$ret = array();

		global $prefs, $userlib, $user, $tiki_p_admin;
		while ($res = $result->fetchRow()) {
			$res['perms'] = $this->get_perm_object($res['galleryId'], 'image gallery', $res, false);
			if ($res['perms']['tiki_p_view_image_gallery'] == 'y') {
				$res['images'] = $this->getOne("select count(*) from `tiki_images` where `galleryId`=?",array($res['galleryId']));
				$ret[] = $res;
			}
		}

		if ($old_sort_mode == 'images_asc') {
			usort($ret, 'compare_images');
		}

		if ($old_sort_mode == 'images_desc') {
			usort($ret, 'r_compare_images');
		}

		if (in_array($old_sort_mode, array(
			    'images_desc',
			    'images_asc'
			    ))) {
			$ret = array_slice($ret, $old_offset, $old_maxRecords);
		}

		$retval = array();
		$retval["data"] = $ret;
		$retval["cant"] = $cant;
		return $retval;
	}

	function list_visible_galleries($offset = 0, $maxRecords = -1, $sort_mode = 'name_desc', $user, $find) {
		global $tiki_p_admin_galleries, $tikilib;
		// If $user is admin then get ALL galleries, if not only user galleries are shown

		$old_sort_mode = '';

		if (in_array($sort_mode, array(
			    'images desc',
			    'images asc'
			    ))) {
			$old_offset = $offset;

			$old_maxRecords = $maxRecords;
			$old_sort_mode = $sort_mode;
			$sort_mode = 'user desc';
			$offset = 0;
			$maxRecords = -1;
		}

		$whuser = "";
		$bindvars=array('y');

		if ($find) {
			$findesc = '%' . $find . '%';

			if (empty($whuser)) {
				$whuser = " and (`name` like ? or `description` like ?)";
				$bindvars=array('y',$findesc,$findesc);
			} else {
				$whuser .= " and (`name` like ? or `description` like ?)";
				$bindvars[]=$findesc;
				$bindvars[]=$findesc;
			}
		}

		// If sort mode is versions then offset is 0, maxRecords is -1 (again) and sort_mode is nil
		// If sort mode is links then offset is 0, maxRecords is -1 (again) and sort_mode is nil
		// If sort mode is backlinks then offset is 0, maxRecords is -1 (again) and sort_mode is nil
		$query = "select * from `tiki_galleries` where `visible`=? $whuser order by ".$this->convertSortMode($sort_mode);
		$query_cant = "select count(*) from `tiki_galleries` where `visible`=? $whuser";
		$result = $this->query($query,$bindvars,$maxRecords,$offset);
		$cant = $this->getOne($query_cant,$bindvars);
		$ret = array();

		while ($res = $result->fetchRow()) {
			if (!$tikilib->user_has_perm_on_object($user, $res['galleryId'], 'image gallery', 'tiki_p_view_image_gallery')) {
				continue;
			}
			$aux = array();

			$aux["name"] = $res["name"];
			$gid = $res["galleryId"];
			$aux["visible"] = $res["visible"];
			$aux["id"] = $gid;
			$aux["galleryId"] = $res["galleryId"];
			$aux["description"] = $res["description"];
			$aux["created"] = $res["created"];
			$aux["lastModif"] = $res["lastModif"];
			$aux["user"] = $res["user"];
			$aux["hits"] = $res["hits"];
			$aux["public"] = $res["public"];
			$aux["theme"] = $res["theme"];
			$aux["geographic"] = $res["geographic"];
			$aux["images"] = $this->getOne("select count(*) from `tiki_images` where `galleryId`=?",array($gid));
			$ret[] = $aux;
		}

		if ($old_sort_mode == 'images asc') {
			usort($ret, 'compare_images');
		}

		if ($old_sort_mode == 'images desc') {
			usort($ret, 'r_compare_images');
		}

		if (in_array($old_sort_mode, array(
			    'images desc',
			    'images asc'
			    ))) {
			$ret = array_slice($ret, $old_offset, $old_maxRecords);
		}

		$retval = array();
		$retval["data"] = $ret;
		$retval["cant"] = $cant;
		return $retval;
	}

	function get_gallery($id) {
		$query = "select * from `tiki_galleries` where `galleryId`=?";
		$result = $this->query($query,array((int) $id));
		$res = $result->fetchRow();
		return $res;
	}

	function get_gallery_owner($galleryId) {
		$query = "select `user` from `tiki_galleries` where `galleryId`=?";

		$user = $this->getOne($query,array((int)$galleryId));
		return $user;
	}

	function get_gallery_from_image($imageid) {
		$query = "select `galleryId` from `tiki_images` where `imageId`=?";

		$galid = $this->getOne($query,array((int)$imageid));
		return $galid;
	}

	function move_image($imgId, $galId) {
		$query = "update `tiki_images` set `galleryId`=? where `imageId`=?";

		$result = $this->query($query,array((int)$galId,(int)$imgId));
		return true;
	}

	function get_image_info($id, $itype = 'o', $xsize = 0, $ysize = 0) {
		// code may be merged with get_image
		$mid = "";

		if ($xsize != 0 && $ysize == 0) {
			// bounding box
			$ysize=$xsize;
		} 

		if ($xsize != 0 && $ysize != 0) {
			$bindvars=array((int)$id,$itype,(int)$xsize,(int)$ysize);
			if($xsize == $ysize) {
				// we don't know yet.
				$mid = "and (d.`xsize` = ? or d.`ysize` = ?) order by `xysize` desc";
			} else {
				$mid = 'and d.`xsize` = ? and d.`ysize` = ?';
			}
		}
		
		if(!isset($bindvars) || !is_array($bindvars)) {
			$bindvars=array((int)$id,$itype);
		}

		$query = "select i.`imageId`, i.`galleryId`, i.`name`,
                     i.`description`, i.`created`, i.`user`,
                     i.`hits`, i.`path`, i.`lat`, i.`lon`,
                     d.`xsize`,d.`ysize`,d.`type`,d.`filesize`,
                     d.`filetype`,d.`filename`,d.`xsize` * d.`ysize` as `xysize`
                 from `tiki_images` i, `tiki_images_data` d where
                     i.`imageId`=? and d.`imageId`=i.`imageId`
                     and d.`type`=?
                     $mid";
		$result = $this->query($query,$bindvars,1);
		$res = $result->fetchRow();
		return $res;
	}

	// Add an option to establish Image size (x,y)
	function get_image($id, $itype = 'o', $xsize = 0, $ysize = 0) {
		global $prefs;

		$mid = "";

		if ($itype == 't') {
			$galid = $this->get_gallery_from_image($id);

			$galinfo = $this->get_gallery_info($galid);
			$xsize = $galinfo["thumbSizeX"];
			$ysize = $galinfo["thumbSizeY"];
		}

		if ($xsize != 0 && $ysize == 0) {
			// first parameter (xsize) represents a scale
			// so we select a bounding box
			$ysize=$xsize;
		} 

		if ($xsize != 0 && $ysize != 0) {
			if ($ysize == $xsize) {
				// we don't know yet.
				$mid = "and (d.`xsize`=? or d.`ysize`=?) order by `xysize` desc ";
				$bindvars=array((int)$id,$itype,(int)$xsize,(int)$ysize);
			} else {
				//exact match
				$mid = "and d.`xsize`=? and d.`ysize`=? ";
				$bindvars=array((int)$id,$itype,(int)$xsize,(int)$ysize);
			}
		}

		
		
		if(!isset($bindvars) || !is_array($bindvars)) {
			$bindvars=array((int)$id,$itype);
		}

		$query = "select i.`imageId`, i.`galleryId`, i.`name`,
                     i.`description`, i.`created`, i.`user`,
                     i.`hits`, i.`path`,i.`lat`, i.`lon`,
                     d.`xsize`,d.`ysize`,d.`type`,d.`filesize`,
                     d.`filetype`,d.`filename`,d.`data`,
		     d.`xsize` * d.`ysize` as `xysize`, d.`etag`
                 from `tiki_images` i, `tiki_images_data` d where
                     i.`imageId`=? and d.`imageId`=i.`imageId`
                     and d.`type`=?
                     $mid";

		$result = $this->query($query,$bindvars,1);

		if ($result===false || $result===null) {
			die;
		}
		
		$res = $result->fetchRow();		

		$this->imageId = $res["imageId"];
		$this->galleryId = $res["galleryId"];
		$this->name = $res["name"];
		$this->description = $res["description"];
		$this->lat = $res["lat"];
		$this->lon = $res["lon"];
		$this->created = $res["created"];
		$this->user = $res["user"];
		$this->hits = $res["hits"];
		$this->path = $res["path"];
		$this->xsize = $res["xsize"];
		$this->ysize = $res["ysize"];
		$this->type = $res["type"];
		$this->filesize = $res["filesize"];
		$this->filetype = $res["filetype"];
		$this->filename = $res["filename"];
		$this->etag= $res["etag"];

		# build scaled images or thumb if not available
		if ($itype != 'o' && !isset($this->imageId)) {
			if ($newsize = $this->rebuild_image($id, $itype, $xsize, $ysize)) {
				// removed because this causes endless recursion
				//return $this->get_image($id, $itype, $newsize["xsize"], $newsize["ysize"]);

				// Since the rescaled image is the one we want, we have to switch to its path and data
				$res['path'] = $this->path;
				$res['data'] = $this->image;
			}
		}

		// get image data from fs
		if (strlen($res["data"]) < 3) { // this is needed by postgres, because it inserts '' in the data field
			switch ($itype) {
			case 't':
				$ext = ".thumb";

				break;

			case 's':
				$ext = ".scaled_" . $res["xsize"] . "x" . $res["ysize"];

				break;

			case 'b':
				// for future use
				$ext = ".backup";

				break;

			default:
				$ext = '';
			}

			// If the image was a .gif then the thumbnail has 0 bytes if the thumbnail
			// is empty then use the full image as thumbnail
			//  if($ext==".thumb" && filesize($prefs['gal_use_dir'].$res["path"].$ext)==0 ) {
			//   $ext='';
			//}
			$this->readimagefromfile($prefs['gal_use_dir'] . $res["path"] . $ext);
		} else {
			$this->image = $res["data"];
		}

		if (!isset($this->imagehandle))
			$this->readimagefromstring();

		// etag checks
		if($this->etag=='') {
		   $this->add_etag();
		}

		return $res;
	}

   function add_etag() {
      // stores md5 based etag in the tables
      // this function assumes that the $this->imageId and other
      // are loaded before (through $this->get_image() or similar)
      if(isset($this->image)) {//avoid broken images through warning
        $etag=md5($this->image);
        $query='update `tiki_images_data` set `etag`=? where `imageId`=? and `xsize`=? and `ysize`=? and `type`=?';
        $bindvars=array($etag,(int) $this->imageId,(int) $this->xsize,(int) $this->ysize,$this->type);
        $this->query($query,$bindvars);
      }

   }

   function get_etag($id, $itype = 'o', $xsize = 0, $ysize = 0) {
      // used to get the etag of a image. This function can be called
      // before we load the image into memory to check if the browser
      // has the image cached.
       $mid = "";

       if ($itype == 't') {
	       $galid = $this->get_gallery_from_image($id);

	       $galinfo = $this->get_gallery_info($galid);
	       $xsize = $galinfo["thumbSizeX"];
	       $ysize = $galinfo["thumbSizeY"];
       }

       if ($xsize != 0 && $ysize == 0) {
	       // first parameter (xsize) represents a scale
	       // so we select a bounding box
	       $ysize=$xsize;
       }

       if ($xsize != 0 && $ysize != 0) {
	       if ($ysize == $xsize) {
		       // we don't know yet.
		       $mid = "and (d.`xsize`=? or d.`ysize`=?) order by `xysize` desc ";
		       $bindvars=array((int)$id,$itype,(int)$xsize,(int)$ysize);
	       } else {
		       //exact match
		       $mid = "and d.`xsize`=? and d.`ysize`=? ";
		       $bindvars=array((int)$id,$itype,(int)$xsize,(int)$ysize);
	       }
       }

       if(!@is_array($bindvars)) {
	       $bindvars=array((int)$id,$itype);
       }

       $query = "select d.`xsize` * d.`ysize` as `xysize`, d.`etag`
	from `tiki_images_data` d where d.`imageId`=? and d.`type`=?
	    $mid";

       $result = $this->query($query,$bindvars,1);

       if ($result===false || $result===null) {
	       return(false);
       }

       $res = $result->fetchRow();
       $this->etag=$res["etag"];

       return($res["etag"]);
    }


   function get_imageid_byname($name, $galleryId=0) {
	
		$bindvars=array($name);

		$query = "select `imageId` from `tiki_images` 
						where `name` like ?";
		if (!empty($galleryId)) {
			$query .= ' and galleryId=?';
			$bindvars[] = $galleryId;
		}

		$result = $this->query($query,$bindvars,1);
		$res = $result->fetchRow(); 
		
		return($res["imageId"]);
			  
   }

	function get_image_thumb($id) {
		return $this->get_image($id, 't');
	}

	function replace_gallery($galleryId, $name, $description, $theme, $user, $maxRows, $rowImages, $thumbSizeX, $thumbSizeY, $public, $visible = 'y', $sortorder='created', $sortdirection='desc', 
$galleryimage='first',$parentgallery=-1,$showname='y',$showimageid='n',$showdescription='n',$showcreated='n',$showuser='n',$showhits='y',$showxysize='y',$showfilesize='n',$showfilename='n',$defaultscale='o',$geographic= 'n',$showcategories='n') {
		global $prefs;

		// if the user is admin or the user is the same user and the gallery exists then replace if not then
		// create the gallary if the name is unused.
		$name = strip_tags($name);

		$description = strip_tags($description);

		// check if the gallery already exists. if yes: do update, if no: update it
		if ($galleryId<1)
		$galleryId = $this->getOne("select `galleryId` from `tiki_galleries` where `name`=? and `parentgallery`=?",array($name,$parentgallery));

		if ($galleryId > 0) {
			//$res = $result->fetchRow();
			//if( ($user == 'admin') || ($res["user"]==$user) ) {
			$query = "update `tiki_galleries` set `name`=?,`visible`=?, `geographic`=?,`maxRows`=? , `rowImages`=?, 
                `thumbSizeX`=?, `thumbSizeY`=?, `description`=?, `theme`=?,
                `lastModif`=?, `public`=?, `sortorder`=?, `sortdirection`=?, `galleryimage`=?,
		`parentgallery`=?,`showname`=?,`showimageid`=?,`showdescription`=?,`showcategories`=?,
		`showcreated`=?,`showuser`=?,`showhits`=?,`showxysize`=?,`showfilesize`=?,
		`showfilename`=?,`defaultscale`=?, `user`=?
	       	where `galleryId`=?";

			$result = 
$this->query($query,array($name,$visible,$geographic,(int)$maxRows,(int)$rowImages,(int)$thumbSizeX,(int)$thumbSizeY,$description,$theme,(int)$this->now,$public,$sortorder,$sortdirection,$galleryimage,(int)$parentgallery,$showname,$showimageid,$showdescription,$showcategories,$showcreated,$showuser,$showhits,$showxysize,$showfilesize,$showfilename,$defaultscale,$user,(int)$galleryId));
		} else {
			// Create a new record
			$query = "insert into 
`tiki_galleries`(`name`,`description`,`theme`,`created`,`user`,`lastModif`,`maxRows`,`rowImages`,`thumbSizeX`,`thumbSizeY`,`public`,`hits`,`visible`,`sortorder`,`sortdirection`,`galleryimage`,`parentgallery`,`showname`,`showimageid`,`showdescription`,`showcategories`,`showcreated`,`showuser`,`showhits`,`showxysize`,`showfilesize`,`showfilename`,`defaultscale`,`geographic`) 
values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
			$bindvars=array($name,$description,$theme,(int) $this->now,$user,(int) $this->now,(int) $maxRows,(int) $rowImages,(int) $thumbSizeX,(int) 
$thumbSizeY,$public,0,$visible,$sortorder,$sortdirection,$galleryimage,(int)$parentgallery,$showname,$showimageid,$showdescription,$showcategories,$showcreated,$showuser,$showhits,$showxysize,$showfilesize,$showfilename,$defaultscale,$geographic);
			$result = $this->query($query,$bindvars);
			$galleryId = $this->getOne("select max(`galleryId`) from `tiki_galleries` where `name`=? and `created`=?",array($name,(int) $this->now));

			if ($prefs['feature_score'] == 'y') {
			    $this->score_event($user, 'igallery_new');
			}
		}

		if ( $prefs['feature_search'] == 'y' && $prefs['feature_search_fulltext'] != 'y' && $prefs['search_refresh_index_mode'] == 'normal' ) {
			require_once('lib/search/refresh-functions.php');
			refresh_index('galleries', $galleryId);
		}

		return $galleryId;
	}

	function add_gallery_scale($galleryId, $scale) {
	        $old_scale = $this->getOne("select scale from tiki_galleries_scales where galleryId = ? AND scale = ?", array((int)$galleryId, (int)$scale));
		if ($scale != $old_scale) {
		    $query = "insert into `tiki_galleries_scales`(`galleryId`,`scale`)
            values(?,?)";
		    $result = $this->query($query,array((int)$galleryId,(int)$scale));
		}
	}

	function remove_gallery_scale($galleryId, $scale= 0) {
                $mid = "";
                $bindvars=array((int) $galleryId);
                if ($scale != 0) {
                        $mid = " and `scale`=? ";
                        $bindvars[]=(int) $scale;
                }
                $query = "delete from `tiki_galleries_scales` where
            `galleryId`=? $mid";
                $result = $this->query($query,$bindvars);
        }

	function remove_gallery($id) {
		global $prefs;

		$query = "select `imageId`,path from `tiki_images` where `galleryId`=?";
		$result = $this->query($query,array((int) $id));

		while ($res = $result->fetchRow()) {
			$path = $res["path"];

			$query2 = "select `xsize`,`ysize`,`type` from `tiki_images_data` where `imageId`=?";
			$result2 = $this->query($query2,array((int)$res["imageId"]));

			while ($res2 = $result2->fetchRow()) {
				switch ($res2["type"]) {
				case 't':
					$ext = ".thumb";

					break;

				case 's':
					$ext = ".scaled_" . $res2["xsize"] . "x" . $res2["ysize"];

					break;

				case 'b':
					// for future use
					$ext = ".backup";

					break;

				default:
					$ext = '';
				}

				if ($path) {
					@unlink ($prefs['gal_use_dir'] . $path . $ext);
				}
			}

			$query3 = "delete from `tiki_images_data` where `imageId`=?";
			$result3 = $this->query($query3,array((int)$res["imageId"]));

			$this->remove_object('image', $res["imageId"]);
		}

		$query = "delete from `tiki_galleries` where `galleryId`=?";
		$result = $this->query($query,array((int) $id));
		$query = "delete from `tiki_images` where `galleryId`=?";
		$result = $this->query($query,array((int) $id));
		$this->remove_gallery_scale($id);
		$this->remove_object('image gallery', $id);
		return true;
	}

	function get_gallery_info($id) {
		// alias for get_gallery
		return $this->get_gallery($id);
	}

	function get_gallery_scale_info($id) {
		$query = "select * from `tiki_galleries_scales` where `galleryId`=?
              order by `scale` asc";

		$result = $this->query($query,array((int) $id));
		$resa = array();

		while ($res = $result->fetchRow()) {
			$resa[] = $res;
		}

		return $resa;
	}

	function get_gallery_next_scale($id, $scale= 0) {
		$query = "select * from `tiki_galleries_scales` where `galleryId`=?
              and `scale` > ? order by `scale` asc";
		$result = $this->query($query,array((int) $id,(int) $scale));
		$res = $result->fetchRow();
		return $res;
	}

	function get_gallery_default_scale($id) {
		$query = "select `defaultscale` from `tiki_galleries` where `galleryId`=?";
		$ret=$this->getOne($query,array((int) $id));
		return $ret;
	}

	function get_gallery_prevnext_scale($id,$currentscale) {
		$ret=array();
		$bindvars=array((int) $id, (int) $currentscale);
		$query = 'select `scale` from `tiki_galleries_scales` where `galleryId`=? ';
		$query2 =$query.'and `scale`>? order by `scale` asc';
		$ret['nextscale']=$this->getOne($query2,$bindvars);
		$query2 =$query.'and `scale`<? order by `scale` desc';
		$ret['prevscale']=$this->getOne($query2,$bindvars);
		if($ret['nextscale']) {
			$ret['nexttype']='s';
		} else {
			$ret['nexttype']='o';
		}
		if($ret['prevscale']) {
			$ret['prevtype']='s';
		} else {
			$ret['prevtype']='o';
		}
		return($ret);
	}

	//Capture Images from wiki, blogs, ....
	function capture_images($data) {
		global $prefs, $tikilib;
		if ($prefs['cacheimages'] != 'y')
			return $data;

		preg_match_all("/src=\"([^\"]+)\"/", $data, $reqs1);
		preg_match_all("/src=\'([^\']+)\'/", $data, $reqs2);
		preg_match_all("/src=([A-Za-z0-9\:\?\=\/\\\.\-\_]+)\}/", $data, $reqs3);
		preg_match_all("/src=([A-Za-z0-9\:\?\=\/\\\.\-\_]+) /", $data, $reqs4);
		$merge = array_merge($reqs1[1], $reqs2[1], $reqs3[1], $reqs4[1]);
		$merge = array_unique($merge);
		//print_r($merge);
		// Now for each element in the array capture the image and
		// if the capture was successful then change the reference to the
		// internal image
		$page_data = $data;

		foreach ($merge as $img) {
			// This prevents caching images
			if (!strstr($img, "img/wiki_up") && !strstr($img, "show_image.php") && !strstr($img, "nocache") && @getimagesize($img)) {
				//print("Procesando: $img<br />");
				@$fp = fopen($img, "r");

				if ($fp) {
					$data = '';

					while (!feof($fp)) {
						$data .= fread($fp, 4096);
					}

					//print("Imagen leida:".strlen($data)." bytes<br />");
					fclose ($fp);

					if (strlen($data) > 0) {
						$url_info = parse_url($img);

						$pinfo = pathinfo($url_info["path"]);
						$type = "image/" . $pinfo["extension"];
						$name = $pinfo["basename"];
						$size = strlen($data);
						$url = $img;

						if (function_exists("ImageCreateFromString") && (!strstr($type, "gif"))) {
							$img = imagecreatefromstring($data);

							$size_x = imagesx($img);
							$size_y = imagesy($img);
							// Fix the ratio values for system gallery
							$gal_info["thumbSizeX"] = 90;
							$gal_info["thumbSizeY"] = 90;

							if ($size_x > $size_y)
								$tscale = ((int)$size_x / $gal_info["thumbSizeX"]);
							else
								$tscale = ((int)$size_y / $gal_info["thumbSizeY"]);

							$tw = ((int)($size_x / $tscale));
							$ty = ((int)($size_y / $tscale));

							if (chkgd2()) {
								$t = imagecreatetruecolor($tw, $ty);

								imagecopyresampled($t, $img, 0, 0, 0, 0, $tw, $ty, $size_x, $size_y);
							} else {
								$t = imagecreate($tw, $ty);

								$this->ImageCopyResampleBicubic($t, $img, 0, 0, 0, 0, $tw, $ty, $size_x, $size_y);
							}

							// CHECK IF THIS TEMP IS WRITEABLE OR CHANGE THE PATH TO A WRITEABLE DIRECTORY
							//$tmpfname = 'temp.jpg';
							//$tmpfname = tempnam("/tmp", "img");
							$tmpfname = tempnam($prefs['tmpDir'], "img");
							imagejpeg($t, $tmpfname);
							// Now read the information
							$fp = fopen($tmpfname, "rb");
							$t_data = fread($fp, filesize($tmpfname));
							fclose ($fp);
							unlink ($tmpfname);
							$t_pinfo = pathinfo($tmpfname);
							$t_type = $t_pinfo["extension"];
							$t_type = 'image/' . $t_type;

							$imageId = $this->insert_image(0, '', '', $name, $type, $data, $size, $size_x, $size_y, 'admin', $t_data, $t_type, NULL, NULL, $gal_info);
						//print("Imagen generada en $imageId<br />");
						} else {
							//print("No GD detected generating image without thumbnail<br />");
							$imageId = $this->insert_image(0, '', '', $name, $type, $data, $size, 100, 100, 'admin', '', '', NULL, NULL, $gal_info);
						//print("Imagen en $imageId<br />");
						}

						// Now change it!
						//print("Changing $url to imageId: $imageId");
						$uri = parse_url($_SERVER["REQUEST_URI"]);
						$path = str_replace("tiki-editpage", "show_image", $uri["path"]);
						$path = str_replace("tiki-edit_article", "show_image", $path);
						$page_data = str_replace($url, $tikilib->httpPrefix( true ). $path . '?id=' . $imageId, $page_data);
					} // if strlen
				} // if $fp
			}
		} // foreach
		return $page_data;
	}
	function get_one_image_from_disk($userfile, $galleryId=0, $name='', $description='', $gal_info='') {
		global $prefs, $user;
		$ret = array();
		if (is_uploaded_file($_FILES[$userfile]['tmp_name'])) {
			$file_name = $_FILES[$userfile]['name'];
			$ret['filename'] = $file_name;
			if (!empty($prefs['gal_match_regex']) && !preg_match('/'.$prefs['gal_match_regex'].'/', $file_name, $reqs)) {
				$ret['msg'] = tra('Invalid imagename (using filters for filenames)');
				return $ret;
			}
			if (!empty($prefs['gal_nmatch_regex']) && preg_match('/'.$prefs['gal_nmatch_regex'].'/', $file_name, $reqs)) {
				$ret['msg'] = tra('Invalid imagename (using filters for filenames)');
				return $ret;
			}
			$type = $_FILES[$userfile]['type'];
			$size = $_FILES[$userfile]['size'];
			$file_tmp_name = $_FILES[$userfile]['tmp_name'];
			$tmp_dest = $prefs['tmpDir'] . '/' . $file_name.'.tmp'; // add .tmp to not overwrite existing files (like index.php)
			if (!move_uploaded_file($file_tmp_name, $tmp_dest)) {
				$ret['msg'] = tra('Errors detected');
				@unlink($tmp_dest);
				return $ret;
			}
			$fp = fopen($tmp_dest, "rb");
			$ret['data'] = fread($fp, filesize($tmp_dest));
			fclose ($fp);
			$imginfo = @getimagesize($tmp_dest);
			unlink($tmp_dest);
			if (!$ret['data'] || !$imginfo) {
				$ret['msg'] = tra('Errors detected');
				return $ret;
			}
			if (!$galleryId) { // was called just to get and check the file
				$ret['xsize'] = $imginfo[0];
				$ret['ysize'] = $imginfo[1];
				$ret['filetype'] = $type;
				$ret['filesize'] = $size;
				return $ret;
			}
			if ($name == '')
				$name = $file_name;
			if (($imageId = $this->insert_image($galleryId, $name, $description, $file_name, $type, $ret['data'], $size, 0, 0, $user, '', '', NULL, NULL, $gal_info))===false) {
				$ret['msg'] = tra('Upload was not successful');
			} else {
				$ret['imageId'] = $imageId;
			}
		} else {
			$ret['msg'] = tra('Upload was not successful');
			$ret['filename'] = $_FILES[$userfile]['tmp_name'];
		}
		unset($ret['data']);
		return $ret;
	}

  // function to move images from one store to another (fs to db or db to fs)
  function move_image_store($imageId,$direction='to_fs')
  {
    global $prefs;

		global $errstr;
    $this->clear_class_vars(); //cleanup
    
    if($direction!='to_fs' && $direction!='to_db') {
      return(false);
    }
    
		if ($direction == 'to_fs' and !is_dir($prefs['gal_use_dir'])) {
			$errstr = tra("unknown destination directory. Please set it up in <a href='tiki-admin.php?page=galleries'>tiki-admin.php?page=galleries</a>");
			return(0);
		}
    // get the storage location
    $query='select `path` from `tiki_images` where `imageId`=?';
    $path=$this->getOne($query,array($imageId),false);
    if($path===false) { // imageId not found
      return(false);
    }
    
    if((empty($path) && $direction=='to_fs') || (!empty($path) && $direction=='to_db')) {
      // move image
      // load image
      $this->get_image($imageId);
      $query='update `tiki_images` set `path`=? where `imageId`=?';
      if($direction=='to_fs') {
   $this->path=md5(uniqid($this->filename));
        // store_image data did already overwrite the "data" field in tiki_images_data
        $this->query($query,array($this->path,$imageId));
      }
      // write image
      $this->store_image_data(true);
      if($direction=='to_db') {
        // remove image in fs 
        if(!@unlink($prefs['gal_use_dir'].$this->path)) {
          $errstr = tra("unlink failed");
        }
        $this->query($query,array('',$imageId));
      }
      return(1);

    }
    return(0);
  } 

  function move_gallery_store($galId,$direction='to_fs')
  {
    $met=ini_get('max_execution_time');
    $st=time();
    $n=0;
    $errors=0;
    $timeout=false;
    if($direction!='to_fs' && $direction!='to_db') {
      return(false);
    }
    
    // remove all scales. They will be rebuild on access
    $this->rebuild_scales($galId);
    
    // move images store
    if($galId==-1) {
      $query='select `imageId` from `tiki_images`';
      $result=$this->query($query,array());
    } else {
      $query='select `imageId` from `tiki_images` where `galleryId`=?';
      $result=$this->query($query,array($galId));
    }
    while ($res = $result->fetchRow()) {
      $r=$this->move_image_store($res['imageId'],$direction);
      if($r!==false) {
        $n+=$r;
      } else {
  $errors++; 
      }
      if($met-time()+$st < 3) { // avoid timeouts so that we dont end with broken images
   $timeout=true;
   break;
      }
    }
    $resultarray=array('moved_images'=>$n,'timeout'=>$timeout,'errors'=>$errors);
    return($resultarray);
  } 

  function clear_class_vars()
  { // function to clear loaded data. Usable for mass changes
     unset($this->imageId);
     unset($this->galleryId);
     unset($this->name);
     unset($this->description);
     unset($this->lat);
     unset($this->lon);
     unset($this->created);
     unset($this->user); 
     unset($this->hits);
     unset($this->path);
     unset($this->xsize);
     unset($this->oldxsize);
     unset($this->ysize);
     unset($this->oldysize);
     unset($this->type);
     unset($this->filesize);
     unset($this->filetype);
     unset($this->filename);
     unset($this->etag);
     unset($this->image);
  }
  /* compute the ratio the image $xsize,$size must have to go in the box */
  function ratio($xsize, $ysize, $xbox=0, $ybox=0) {
	if (empty($xbox) && empty($ybox))
		return 1;
	if ($xsize <= $xbox && $ysize <= $ybox)
		return 1;
	if (empty($xbox)) {
		return $ybox/xsize;
	} else {
		$t = $xbox/$xsize;
		if (!empty($ybox)) {
			return $t;
		} else {
			return min($t, $ybox/$ysize);
		}
	}
	}
}
global $imagegallib;
$imagegallib = new ImageGalsLib;
