无忧岛

04 十二, 2011

linux零基础教程 vi编辑器常用命令

Posted by: kinglife In: linux

以前从未使用过linux,一直想彻底的去下定决心学习学习,但是因为手上又没有linux的工作学习环境,以前用的linux主机一直是虚拟主机,由服务商把环境完全配置好了,有问题直接就跟服务商反馈,然后他们给你操作的.

前阵子心血来潮在本地服务器上安装了CentOS5,但是也没来得及去好好系统的学习,前些天因为几个站的备案下不来,于是下狠心把网站搬到国外去,于是找大B买了款512M的linux VPS,正好自己也可以多个学习的机会.

今天在装ECSHOP的时候遇到个问题,安装完毕之后登录后台就会有”您的服务器设置了 open_base_dir 且没有包含 /tmp/,您将无法上传文件。“的错误提示.

网上搜索了一下,不少人遇到这个问题,但是大多教程是让到 “/home/httpd/islandcn.com/conf/” 这个目录去修改名为”kloxo.islandcn.com的配置文件.

我的VPS配置是 CentOS和Kloxo面板,可能因为kloxo的面板的版本问题,我打开到”/home/httpd/islandcn.com/“目录根本找不到conf的目录,下面只有个php.ini,看了下php.ini的配置又完全没问题,里面有一个open_basedir的参数,但是是被注释掉的.

最后用查找功能找到了这个文件的目录在”home/apache/conf/domains/islandcn.com.conf“这里. 于是进去修改保存,重启,问题解决了.

解决”您的服务器设置了 open_base_dir 且没有包含 /tmp/,您将无法上传文件。“问题的办法是在此文件中找到 IfModule mod_php5.c这一项的配置:

php_admin_value open_basedir “/home/httpd/…/httpd/script”
将上面粗体部分改成
改为 open_base_dir (basedir中间加了一个下划线)

下面主要把实现的命令说一下:

1.VI编辑器的进入和退出
进入VI编辑器: vi 文件名
退出VI编辑器: :q! – 不做修改直接退出
:wq 保存后退出 等同于 :x

2.文件内容的插入与修改
2.1 光标控制命令

h 光标左移,l 光标右移,j 光标上移,k 光标下移
以上命令在命令符前输入数字n ,则光标会往该方向移n 个字符
2.2 删除命令

x为删除一个字符
2.3 字符插入命令 i

在打开vi编辑器状态之后如果你按下”i” 下面会有 “insert” 的状态提醒,此时你可以在光标处插入你输入的字符.当你不需要插入字符的时候记得按”ESC”来返回来命令模式.

2.4 字符的搜索
搜索命令是”/”,在输入/之后输入你要搜索的关键词,然后回车,如果有多处匹配结果可以用”n”来移动到下一个结果,如果你要返回上一个结果则需要用”N”

2.5 文件的搜索
find搜索,这个命令也是十分重要的,我的配置文件就是用它来找的,面板的类型不一样所以配置文件可能存放的位置也不一样,于是我们需要搜索出文件所在位置加以判断和修改.命令的具体写法是

find -name 文件名(文件名可以写 php.ini 或者 conf等等配置文件名信息)

以上命令足以任意修改文件了,如果确定修改之后需要保存退出,然后重启服务.

更多的教程可以参考此文: http://www.centos.bz/2011/10/linux-file-view-edit/

Tags: , ,

10 十一, 2011

html静态页的最佳化301转向方法 rel=”canonical”

Posted by: kinglife In: SEO

各种动态页的301转向就不用再说了,网上特别多.
但是对于html页面来说,301至今也没有个权威的标准说法.
很多人用js和http-equiv=”refresh”等标签来设置重定向,但是返回的也都是非301状态,今天又试着找了很多资料,得出下面的办法是最佳化的.
先说下rel=”canonical”这个标签吧
这个标签是谷歌首先提出来的,作用是用来规范网页,也就是这么一种情况下使用的:
假设一个产品类目的页面,然后它可能有几种排序方式
A. 按照产品的价格排序 我们记录它的地址是: URLA
B. 按照产品上架时间排序 我们记录它的地址是: URLB
C. 按照产品的热门度排序 我们记录它的地址是: URLC
同样的一类产品可能出现上面几个或者更多的URL,但是实际上对搜索引擎来说它们页面内容除了排序不一样以外,其它实质的内容几乎是相同的.所以这里便出现了规范网页这一说.也就是让你提出一个标准网页.那么这个标签如何使用呢?
假设我们去URLA为标准的规范网页,那么我们只需要在URLB和URLC的HEAD标签中加入


<link rel="canonical" href="URLA" />

这行代码即可了,这里的URLA就是规范网页的地址,也就是你需要301重定向的地址.这里就完成了网页地址的统一.

那么继续说HTML如何应用这个标签做跳转呢?这里很多朋友可能已经如何实现了.其实很简单,因为从搜索引擎的角度来说,它已经明白你的意图了,还剩下的就是用户体验了.再用html或者js实现一个重定向就可以了.可以采用以下代码:


<meta http-equiv="refresh" content="0; url=http://new-domain.com/" />
<link rel="canonical" href="http://new-domain.com" />

问题:百度是否支持canonical标签呢?
答案:网上有人无意中做了个实验,发现其实百度也是支持的,让所有产品页面加上都加上rel=”canonical” 并且指向首页,结果在百度的收录数目减少了2万条,产品页面撤了该标签以后,收录恢复,所以其实百度也支持rel=”canonical”

更多参考资料
谷歌关于rel=”canonical”的详细说明

20 十, 2011

timthumb.php 缩略图处理利器

Posted by: kinglife In: php

先说一下timthumb吧

timthumb.php是一个非常流行的Wordpress的缩略图脚本。通过timthumb.php这个插件脚本,可以方便的实现动态图像裁剪、缩放和调整。很多Wordpress杂志类型的主题都用到它,国外主题普遍采用该脚本自动生成缩略图,使用非常方便。

该项目地址:http://code.google.com/p/timthumb/

补充说明下:应用timthumb的缩略图地址及参数:

http://www.dongcheng.cc/wp-content/themes/corporattica/scripts/timthumb.php?src=http://www.dongcheng.cc/wp-content/uploads/2011/06/XSP-BM22AY.jpg&h=150&w=200&zc=1

譬如我网站中这个主题所应用的缩略图
timthumb.php?src=这里是图片地址&h=高度&w=宽度&zc=是否裁剪

一个问题:今天突然发现所有用到它的图片都不显示了,也就是上面的地址格式的图片都不显示了.由于我的wordpress采用了一个备份插件:BackUpWordPress ,这个插件很好使,个人极力推荐,它可以把站点目录跟数据库全部打包备份,可以每天定期备份,因为定期备份的关系我的虚拟主机空间不够了,所以起初我认为是空间受限的缘故无法生成出缩略图的原因导致的,但是把备份的打包文件全删除了也没见效果.

于是又接着找原因才发现我的timthumb.php的版本太低了是1.09的版本,用谷歌查了下这个版本有安全漏洞,大概漏洞描述为

黑客可以利用这个漏洞(大概是调用外部图像时验证上有缺陷而产生的漏洞),上传任意恶意程序到你的网站,而且作者的网站已被黑客入侵。

于是开始升级到最新版本,升级很简单直接把新文件替换掉源文件就可以了(建议备份原文件).然后就一切正常了…下面附上最新版的代码,当然也可以在谷歌代码的项目上获取.


<?php
/**
 * TimThumb by Ben Gillbanks and Mark Maunder
 * Based on work done by Tim McDaniels and Darren Hoyt
 * http://code.google.com/p/timthumb/
 *
 * GNU General Public License, version 2
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 *
 * Examples and documentation available on the project homepage
 * http://www.binarymoon.co.uk/projects/timthumb/
 */

/*
	-----TimThumb CONFIGURATION-----
	You can either edit the configuration variables manually here, or you can
	create a file called timthumb-config.php and define variables you want
	to customize in there. It will automatically be loaded by timthumb.
	This will save you having to re-edit these variables everytime you download
	a new version of timthumb.

*/
define ('VERSION', '2.8.2');										// Version of this script
//Load a config file if it exists. Otherwise, use the values below
if( file_exists(dirname(__FILE__) . '/timthumb-config.php'))	require_once('timthumb-config.php');
if(! defined('DEBUG_ON') ) 			define ('DEBUG_ON', false);				// Enable debug logging to web server error log (STDERR)
if(! defined('DEBUG_LEVEL') ) 			define ('DEBUG_LEVEL', 1);				// Debug level 1 is less noisy and 3 is the most noisy
if(! defined('MEMORY_LIMIT') ) 			define ('MEMORY_LIMIT', '30M');				// Set PHP memory limit
if(! defined('BLOCK_EXTERNAL_LEECHERS') ) 	define ('BLOCK_EXTERNAL_LEECHERS', false);		// If the image or webshot is being loaded on an external site, display a red "No Hotlinking" gif.

//Image fetching and caching
if(! defined('ALLOW_EXTERNAL') ) 		define ('ALLOW_EXTERNAL', TRUE);			// Allow image fetching from external websites. Will check against ALLOWED_SITES if ALLOW_ALL_EXTERNAL_SITES is false
if(! defined('ALLOW_ALL_EXTERNAL_SITES') ) 	define ('ALLOW_ALL_EXTERNAL_SITES', false);		// Less secure.
if(! defined('FILE_CACHE_ENABLED') ) 		define ('FILE_CACHE_ENABLED', TRUE);			// Should we store resized/modified images on disk to speed things up?
if(! defined('FILE_CACHE_TIME_BETWEEN_CLEANS'))	define ('FILE_CACHE_TIME_BETWEEN_CLEANS', 86400);	// How often the cache is cleaned
if(! defined('FILE_CACHE_MAX_FILE_AGE') ) 	define ('FILE_CACHE_MAX_FILE_AGE', 86400);		// How old does a file have to be to be deleted from the cache
if(! defined('FILE_CACHE_SUFFIX') ) 		define ('FILE_CACHE_SUFFIX', '.timthumb.txt');		// What to put at the end of all files in the cache directory so we can identify them
if(! defined('FILE_CACHE_DIRECTORY') ) 		define ('FILE_CACHE_DIRECTORY', './cache');		// Directory where images are cached. Left blank it will use the system temporary directory (which is better for security)
if(! defined('MAX_FILE_SIZE') ) 		define ('MAX_FILE_SIZE', 10485760);			// 10 Megs is 10485760. This is the max internal or external file size that we'll process.
if(! defined('CURL_TIMEOUT') ) 			define ('CURL_TIMEOUT', 20);				// Timeout duration for Curl. This only applies if you have Curl installed and aren't using PHP's default URL fetching mechanism.
if(! defined('WAIT_BETWEEN_FETCH_ERRORS') ) 	define ('WAIT_BETWEEN_FETCH_ERRORS', 3600);		//Time to wait between errors fetching remote file
//Browser caching
if(! defined('BROWSER_CACHE_MAX_AGE') ) 	define ('BROWSER_CACHE_MAX_AGE', 864000);		// Time to cache in the browser
if(! defined('BROWSER_CACHE_DISABLE') ) 	define ('BROWSER_CACHE_DISABLE', false);		// Use for testing if you want to disable all browser caching

//Image size and defaults
if(! defined('MAX_WIDTH') ) 			define ('MAX_WIDTH', 1500);				// Maximum image width
if(! defined('MAX_HEIGHT') ) 			define ('MAX_HEIGHT', 1500);				// Maximum image height
if(! defined('NOT_FOUND_IMAGE') )		define ('NOT_FOUND_IMAGE', '');				//Image to serve if any 404 occurs
if(! defined('ERROR_IMAGE') )			define ('ERROR_IMAGE', '');				//Image to serve if an error occurs instead of showing error message 

//Image compression is enabled if either of these point to valid paths

//These are now disabled by default because the file sizes of PNGs (and GIFs) are much smaller than we used to generate.
//They only work for PNGs. GIFs and JPEGs are not affected.
if(! defined('OPTIPNG_ENABLED') ) 		define ('OPTIPNG_ENABLED', false);
if(! defined('OPTIPNG_PATH') ) 			define ('OPTIPNG_PATH', '/usr/bin/optipng'); //This will run first because it gives better compression than pngcrush.
if(! defined('PNGCRUSH_ENABLED') ) 		define ('PNGCRUSH_ENABLED', false);
if(! defined('PNGCRUSH_PATH') ) 		define ('PNGCRUSH_PATH', '/usr/bin/pngcrush'); //This will only run if OPTIPNG_PATH is not set or is not valid

/*
	-------====Website Screenshots configuration - BETA====-------

	If you just want image thumbnails and don't want website screenshots, you can safely leave this as is.	

	If you would like to get website screenshots set up, you will need root access to your own server.

	Enable ALLOW_ALL_EXTERNAL_SITES so you can fetch any external web page. This is more secure now that we're using a non-web folder for cache.
	Enable BLOCK_EXTERNAL_LEECHERS so that your site doesn't generate thumbnails for the whole Internet.

	Instructions to get website screenshots enabled on Ubuntu Linux:

	1. Install Xvfb with the following command: sudo apt-get install subversion libqt4-webkit libqt4-dev g++ xvfb
	2. Go to a directory where you can download some code
	3. Check-out the latest version of CutyCapt with the following command: svn co https://cutycapt.svn.sourceforge.net/svnroot/cutycapt
	4. Compile CutyCapt by doing: cd cutycapt/CutyCapt
	5. qmake
	6. make
	7. cp CutyCapt /usr/local/bin/
	8. Test it by running: xvfb-run --server-args="-screen 0, 1024x768x24" CutyCapt --url="http://markmaunder.com/" --out=test.png
	9. If you get a file called test.png with something in it, it probably worked. Now test the script by accessing it as follows:
	10. http://yoursite.com/path/to/timthumb.php?src=http://markmaunder.com/&webshot=1

	Notes on performance:
	The first time a webshot loads, it will take a few seconds.
	From then on it uses the regular timthumb caching mechanism with the configurable options above
	and loading will be very fast.

	--ADVANCED USERS ONLY--
	If you'd like a slight speedup (about 25%) and you know Linux, you can run the following command which will keep Xvfb running in the background.
	nohup Xvfb :100 -ac -nolisten tcp -screen 0, 1024x768x24 > /dev/null 2>&1 &
	Then set WEBSHOT_XVFB_RUNNING = true below. This will save your server having to fire off a new Xvfb server and shut it down every time a new shot is generated.
	You will need to take responsibility for keeping Xvfb running in case it crashes. (It seems pretty stable)
	You will also need to take responsibility for server security if you're running Xvfb as root. 

*/
if(! defined('WEBSHOT_ENABLED') ) 	define ('WEBSHOT_ENABLED', false);			//Beta feature. Adding webshot=1 to your query string will cause the script to return a browser screenshot rather than try to fetch an image.
if(! defined('WEBSHOT_CUTYCAPT') ) 	define ('WEBSHOT_CUTYCAPT', '/usr/local/bin/CutyCapt'); //The path to CutyCapt.
if(! defined('WEBSHOT_XVFB') ) 		define ('WEBSHOT_XVFB', '/usr/bin/xvfb-run');		//The path to the Xvfb server
if(! defined('WEBSHOT_SCREEN_X') ) 	define ('WEBSHOT_SCREEN_X', '1024');			//1024 works ok
if(! defined('WEBSHOT_SCREEN_Y') ) 	define ('WEBSHOT_SCREEN_Y', '768');			//768 works ok
if(! defined('WEBSHOT_COLOR_DEPTH') ) 	define ('WEBSHOT_COLOR_DEPTH', '24');			//I haven't tested anything besides 24
if(! defined('WEBSHOT_IMAGE_FORMAT') ) 	define ('WEBSHOT_IMAGE_FORMAT', 'png');			//png is about 2.5 times the size of jpg but is a LOT better quality
if(! defined('WEBSHOT_TIMEOUT') ) 	define ('WEBSHOT_TIMEOUT', '20');			//Seconds to wait for a webshot
if(! defined('WEBSHOT_USER_AGENT') ) 	define ('WEBSHOT_USER_AGENT', "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.2.18) Gecko/20110614 Firefox/3.6.18"); //I hate to do this, but a non-browser robot user agent might not show what humans see. So we pretend to be Firefox
if(! defined('WEBSHOT_JAVASCRIPT_ON') ) define ('WEBSHOT_JAVASCRIPT_ON', true);			//Setting to false might give you a slight speedup and block ads. But it could cause other issues.
if(! defined('WEBSHOT_JAVA_ON') ) 	define ('WEBSHOT_JAVA_ON', false);			//Have only tested this as fase
if(! defined('WEBSHOT_PLUGINS_ON') ) 	define ('WEBSHOT_PLUGINS_ON', true);			//Enable flash and other plugins
if(! defined('WEBSHOT_PROXY') ) 	define ('WEBSHOT_PROXY', '');				//In case you're behind a proxy server.
if(! defined('WEBSHOT_XVFB_RUNNING') )	define ('WEBSHOT_XVFB_RUNNING', false);			//ADVANCED: Enable this if you've got Xvfb running in the background.

// If ALLOW_EXTERNAL is true and ALLOW_ALL_EXTERNAL_SITES is false, then external images will only be fetched from these domains and their subdomains.
if(! isset($ALLOWED_SITES)){
	$ALLOWED_SITES = array (
		'flickr.com',
		'picasa.com',
		'img.youtube.com',
		'upload.wikimedia.org',
		'photobucket.com',
		'imgur.com',
		'imageshack.us',
		'tinypic.com',
	);
}
// -------------------------------------------------------------
// -------------- STOP EDITING CONFIGURATION HERE --------------
// -------------------------------------------------------------

timthumb::start();

class timthumb {
	protected $src = "";
	protected $is404 = false;
	protected $docRoot = "";
	protected $lastURLError = false;
	protected $localImage = "";
	protected $localImageMTime = 0;
	protected $url = false;
	protected $myHost = "";
	protected $isURL = false;
	protected $cachefile = '';
	protected $errors = array();
	protected $toDeletes = array();
	protected $cacheDirectory = '';
	protected $startTime = 0;
	protected $lastBenchTime = 0;
	protected $cropTop = false;
	protected $salt = "";
	protected $fileCacheVersion = 1; //Generally if timthumb.php is modifed (upgraded) then the salt changes and all cache files are recreated. This is a backup mechanism to force regen.
	protected $filePrependSecurityBlock = "<?php die('Execution denied!'); //"; //Designed to have three letter mime type, space, question mark and greater than symbol appended. 6 bytes total.
	protected static $curlDataWritten = 0;
	protected static $curlFH = false;
	public static function start(){
		$tim = new timthumb();
		$tim->handleErrors();
		$tim->securityChecks();
		if($tim->tryBrowserCache()){
			exit(0);
		}
		$tim->handleErrors();
		if(FILE_CACHE_ENABLED && $tim->tryServerCache()){
			exit(0);
		}
		$tim->handleErrors();
		$tim->run();
		$tim->handleErrors();
		exit(0);
	}
	public function __construct(){
		global $ALLOWED_SITES;
		$this->startTime = microtime(true);
		date_default_timezone_set('UTC');
		$this->debug(1, "Starting new request from " . $this->getIP() . " to " . $_SERVER['REQUEST_URI']);
		$this->calcDocRoot();
		//On windows systems I'm assuming fileinode returns an empty string or a number that doesn't change. Check this.
		$this->salt = @filemtime(__FILE__) . '-' . @fileinode(__FILE__);
		$this->debug(3, "Salt is: " . $this->salt);
		if(FILE_CACHE_DIRECTORY){
			if(! is_dir(FILE_CACHE_DIRECTORY)){
				@mkdir(FILE_CACHE_DIRECTORY);
				if(! is_dir(FILE_CACHE_DIRECTORY)){
					$this->error("Could not create the file cache directory.");
					return false;
				}
			}
			$this->cacheDirectory = FILE_CACHE_DIRECTORY;
			if (!touch($this->cacheDirectory . '/index.html')) {
				$this->error("Could note create the index.html file.");
			}
		} else {
			$this->cacheDirectory = sys_get_temp_dir();
		}
		//Clean the cache before we do anything because we don't want the first visitor after FILE_CACHE_TIME_BETWEEN_CLEANS expires to get a stale image.
		$this->cleanCache();

		$this->myHost = preg_replace('/^www\./i', '', $_SERVER['HTTP_HOST']);
		$this->src = $this->param('src');
		$this->url = parse_url($this->src);
		if(strlen($this->src) <= 3){
			$this->error("No image specified");
			return false;
		}
		if(BLOCK_EXTERNAL_LEECHERS && array_key_exists('HTTP_REFERER', $_SERVER) && (! preg_match('/^https?:\/\/(?:www\.)?' . $this->myHost . '(?:$|\/)/i', $_SERVER['HTTP_REFERER']))){
			// base64 encoded red image that says 'no hotlinkers'
			// nothing to worry about! :)
			$imgData = base64_decode("R0lGODlhUAAMAIAAAP8AAP///yH5BAAHAP8ALAAAAABQAAwAAAJpjI+py+0Po5y0OgAMjjv01YUZ\nOGplhWXfNa6JCLnWkXplrcBmW+spbwvaVr/cDyg7IoFC2KbYVC2NQ5MQ4ZNao9Ynzjl9ScNYpneb\nDULB3RP6JuPuaGfuuV4fumf8PuvqFyhYtjdoeFgAADs=");
			header('Content-Type: image/gif');
			header('Content-Length: ' . sizeof($imgData));
			header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
			header("Pragma: no-cache");
			header('Expires: ' . gmdate ('D, d M Y H:i:s', time()));
			echo $imgData;
			return false;
			exit(0);
		}
		if(preg_match('/https?:\/\/(?:www\.)?' . $this->myHost . '(?:$|\/)/i', $this->src)){
			$this->src = preg_replace('/https?:\/\/(?:www\.)?' . $this->myHost . '/i', '', $this->src);
		}
		if(preg_match('/^https?:\/\/[^\/]+/i', $this->src)){
			$this->debug(2, "Is a request for an external URL: " . $this->src);
			$this->isURL = true;
		} else {
			$this->debug(2, "Is a request for an internal file: " . $this->src);
		}
		if($this->isURL && (! ALLOW_EXTERNAL)){
			$this->error("You are not allowed to fetch images from an external website.");
			return false;
		}
		if($this->isURL){
			if(ALLOW_ALL_EXTERNAL_SITES){
				$this->debug(2, "Fetching from all external sites is enabled.");
			} else {
				$this->debug(2, "Fetching only from selected external sites is enabled.");
				$allowed = false;
				foreach($ALLOWED_SITES as $site){
					if ((strtolower(substr($this->url['host'],-strlen($site)-1)) === strtolower(".$site")) || (strtolower($this->url['host'])===strtolower($site))) {
						$this->debug(3, "URL hostname {$this->url['host']} matches $site so allowing.");
						$allowed = true;
					}
				}
				if(! $allowed){
					return $this->error("You may not fetch images from that site. To enable this site in timthumb, you can either add it to \$ALLOWED_SITES and set ALLOW_EXTERNAL=true. Or you can set ALLOW_ALL_EXTERNAL_SITES=true, depending on your security needs.");
				}
			}
		}

		$cachePrefix = ($this->isURL ? 'timthumb_ext_' : 'timthumb_int_');
		if($this->isURL){
			$this->cachefile = $this->cacheDirectory . '/' . $cachePrefix . md5($this->salt . $_SERVER ['QUERY_STRING'] . $this->fileCacheVersion) . FILE_CACHE_SUFFIX;
		} else {
			$this->localImage = $this->getLocalImagePath($this->src);
			if(! $this->localImage){
				$this->debug(1, "Could not find the local image: {$this->localImage}");
				$this->error("Could not find the internal image you specified.");
				$this->set404();
				return false;
			}
			$this->debug(1, "Local image path is {$this->localImage}");
			$this->localImageMTime = @filemtime($this->localImage);
			//We include the mtime of the local file in case in changes on disk.
			$this->cachefile = $this->cacheDirectory . '/' . $cachePrefix . md5($this->salt . $this->localImageMTime . $_SERVER ['QUERY_STRING'] . $this->fileCacheVersion) . FILE_CACHE_SUFFIX;
		}
		$this->debug(2, "Cache file is: " . $this->cachefile);

		return true;
	}
	public function __destruct(){
		foreach($this->toDeletes as $del){
			$this->debug(2, "Deleting temp file $del");
			@unlink($del);
		}
	}
	public function run(){
		if($this->isURL){
			if(! ALLOW_EXTERNAL){
				$this->debug(1, "Got a request for an external image but ALLOW_EXTERNAL is disabled so returning error msg.");
				$this->error("You are not allowed to fetch images from an external website.");
				return false;
			}
			$this->debug(3, "Got request for external image. Starting serveExternalImage.");
			if($this->param('webshot')){
				if(WEBSHOT_ENABLED){
					$this->debug(3, "webshot param is set, so we're going to take a webshot.");
					$this->serveWebshot();
				} else {
					$this->error("You added the webshot parameter but webshots are disabled on this server. You need to set WEBSHOT_ENABLED == true to enable webshots.");
				}
			} else {
				$this->debug(3, "webshot is NOT set so we're going to try to fetch a regular image.");
				$this->serveExternalImage();

			}
		} else {
			$this->debug(3, "Got request for internal image. Starting serveInternalImage()");
			$this->serveInternalImage();
		}
		return true;
	}
	protected function handleErrors(){
		if($this->haveErrors()){
			if(NOT_FOUND_IMAGE && $this->is404()){
				if($this->serveImg(NOT_FOUND_IMAGE)){
					exit(0);
				} else {
					$this->error("Additionally, the 404 image that is configured could not be found or there was an error serving it.");
				}
			}
			if(ERROR_IMAGE){
				if($this->serveImg(ERROR_IMAGE)){
					exit(0);
				} else {
					$this->error("Additionally, the error image that is configured could not be found or there was an error serving it.");
				}
			}

			$this->serveErrors();
			exit(0);
		}
		return false;
	}
	protected function tryBrowserCache(){
		if(BROWSER_CACHE_DISABLE){ $this->debug(3, "Browser caching is disabled"); return false; }
		if(!empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) ){
			$this->debug(3, "Got a conditional get");
			$mtime = false;
			//We've already checked if the real file exists in the constructor
			if(! is_file($this->cachefile)){
				//If we don't have something cached, regenerate the cached image.
				return false;
			}
			if($this->localImageMTime){
				$mtime = $this->localImageMTime;
				$this->debug(3, "Local real file's modification time is $mtime");
			} else if(is_file($this->cachefile)){ //If it's not a local request then use the mtime of the cached file to determine the 304
				$mtime = @filemtime($this->cachefile);
				$this->debug(3, "Cached file's modification time is $mtime");
			}
			if(! $mtime){ return false; }

			$iftime = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
			$this->debug(3, "The conditional get's if-modified-since unixtime is $iftime");
			if($iftime < 1){
				$this->debug(3, "Got an invalid conditional get modified since time. Returning false.");
				return false;
			}
			if($iftime < $mtime){ //Real file or cache file has been modified since last request, so force refetch.
				$this->debug(3, "File has been modified since last fetch.");
				return false;
			} else { //Otherwise serve a 304
				$this->debug(3, "File has not been modified since last get, so serving a 304.");
				header ($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified');
				$this->debug(1, "Returning 304 not modified");
				return true;
			}
		}
		return false;
	}
	protected function tryServerCache(){
		$this->debug(3, "Trying server cache");
		if(file_exists($this->cachefile)){
			$this->debug(3, "Cachefile {$this->cachefile} exists");
			if($this->isURL){
				$this->debug(3, "This is an external request, so checking if the cachefile is empty which means the request failed previously.");
				if(filesize($this->cachefile) < 1){
					$this->debug(3, "Found an empty cachefile indicating a failed earlier request. Checking how old it is.");
					//Fetching error occured previously
					if(time() - @filemtime($this->cachefile) > WAIT_BETWEEN_FETCH_ERRORS){
						$this->debug(3, "File is older than " . WAIT_BETWEEN_FETCH_ERRORS . " seconds. Deleting and returning false so app can try and load file.");
						@unlink($this->cachefile);
						return false; //to indicate we didn't serve from cache and app should try and load
					} else {
						$this->debug(3, "Empty cachefile is still fresh so returning message saying we had an error fetching this image from remote host.");
						$this->set404();
						$this->error("An error occured fetching image.");
						return false;
					}
				}
			} else {
				$this->debug(3, "Trying to serve cachefile {$this->cachefile}");
			}
			if($this->serveCacheFile()){
				$this->debug(3, "Succesfully served cachefile {$this->cachefile}");
				return true;
			} else {
				$this->debug(3, "Failed to serve cachefile {$this->cachefile} - Deleting it from cache.");
				//Image serving failed. We can't retry at this point, but lets remove it from cache so the next request recreates it
				@unlink($this->cachefile);
				return true;
			}
		}
	}
	protected function error($err){
		$this->debug(3, "Adding error message: $err");
		$this->errors[] = $err;
		return false;

	}
	protected function haveErrors(){
		if(sizeof($this->errors) > 0){
			return true;
		}
		return false;
	}
	protected function serveErrors(){
		$html = '<ul>';
		foreach($this->errors as $err){
			$html .= '<li>' . htmlentities($err) . '</li>';
		}
		$html .= '</ul>';
		header ($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request');
		echo '<h1>A TimThumb error has occured</h1>The following error(s) occured:<br />' . $html . '<br />';
		echo '<br />Query String : ' . htmlentities ($_SERVER['QUERY_STRING']);
		echo '<br />TimThumb version : ' . VERSION . '</pre>';
	}
	protected function serveInternalImage(){
		$this->debug(3, "Local image path is $this->localImage");
		if(! $this->localImage){
			$this->sanityFail("localImage not set after verifying it earlier in the code.");
			return false;
		}
		$fileSize = filesize($this->localImage);
		if($fileSize > MAX_FILE_SIZE){
			$this->error("The file you specified is greater than the maximum allowed file size.");
			return false;
		}
		if($fileSize <= 0){
			$this->error("The file you specified is <= 0 bytes.");
			return false;
		}
		$this->debug(3, "Calling processImageAndWriteToCache() for local image.");
		if($this->processImageAndWriteToCache($this->localImage)){
			$this->serveCacheFile();
			return true;
		} else {
			return false;
		}
	}
	protected function cleanCache(){
		$this->debug(3, "cleanCache() called");
		$lastCleanFile = $this->cacheDirectory . '/timthumb_cacheLastCleanTime.touch';

		//If this is a new timthumb installation we need to create the file
		if(! is_file($lastCleanFile)){
			$this->debug(1, "File tracking last clean doesn't exist. Creating $lastCleanFile");
			if (!touch($lastCleanFile)) {
				$this->error("Could note create cache clean timestamp file.");
			}
			return;
		}
		if(@filemtime($lastCleanFile) < (time() - FILE_CACHE_TIME_BETWEEN_CLEANS) ){ //Cache was last cleaned more than 1 day ago
			$this->debug(1, "Cache was last cleaned more than " . FILE_CACHE_TIME_BETWEEN_CLEANS . " seconds ago. Cleaning now.");
			// Very slight race condition here, but worst case we'll have 2 or 3 servers cleaning the cache simultaneously once a day.
			if (!touch($lastCleanFile)) {
				$this->error("Could note create cache clean timestamp file.");
			}
			$files = glob($this->cacheDirectory . '/*' . FILE_CACHE_SUFFIX);
			$timeAgo = time() - FILE_CACHE_MAX_FILE_AGE;
			foreach($files as $file){
				if(@filemtime($file) < $timeAgo){
					$this->debug(3, "Deleting cache file $file older than max age: " . FILE_CACHE_MAX_FILE_AGE . " seconds");
					@unlink($file);
				}
			}
			return true;
		} else {
			$this->debug(3, "Cache was cleaned less than " . FILE_CACHE_TIME_BETWEEN_CLEANS . " seconds ago so no cleaning needed.");
		}
		return false;
	}
	protected function processImageAndWriteToCache($localImage){
		$sData = getimagesize($localImage);
		$origType = $sData[2];
		$mimeType = $sData['mime'];

		$this->debug(3, "Mime type of image is $mimeType");
		if(! preg_match('/^image\/(?:gif|jpg|jpeg|png)$/i', $mimeType)){
			return $this->error("The image being resized is not a valid gif, jpg or png.");
		}

		if (!function_exists ('imagecreatetruecolor')) {
		    return $this->error('GD Library Error: imagecreatetruecolor does not exist - please contact your webhost and ask them to install the GD library');
		}

		if (function_exists ('imagefilter') && defined ('IMG_FILTER_NEGATE')) {
			$imageFilters = array (
				1 => array (IMG_FILTER_NEGATE, 0),
				2 => array (IMG_FILTER_GRAYSCALE, 0),
				3 => array (IMG_FILTER_BRIGHTNESS, 1),
				4 => array (IMG_FILTER_CONTRAST, 1),
				5 => array (IMG_FILTER_COLORIZE, 4),
				6 => array (IMG_FILTER_EDGEDETECT, 0),
				7 => array (IMG_FILTER_EMBOSS, 0),
				8 => array (IMG_FILTER_GAUSSIAN_BLUR, 0),
				9 => array (IMG_FILTER_SELECTIVE_BLUR, 0),
				10 => array (IMG_FILTER_MEAN_REMOVAL, 0),
				11 => array (IMG_FILTER_SMOOTH, 0),
			);
		}

		// get standard input properties
		$new_width =  (int) abs ($this->param('w', 0));
		$new_height = (int) abs ($this->param('h', 0));
		$zoom_crop = (int) $this->param('zc', 1);
		$quality = (int) abs ($this->param('q', 90));
		$align = $this->cropTop ? 't' : $this->param('a', 'c');
		$filters = $this->param('f', '');
		$sharpen = (bool) $this->param('s', 0);
		$canvas_color = $this->param('cc', 'ffffff');

		// set default width and height if neither are set already
		if ($new_width == 0 && $new_height == 0) {
		    $new_width = 100;
		    $new_height = 100;
		}

		// ensure size limits can not be abused
		$new_width = min ($new_width, MAX_WIDTH);
		$new_height = min ($new_height, MAX_HEIGHT);

		// set memory limit to be able to have enough space to resize larger images
		$this->setMemoryLimit();

		// open the existing image
		$image = $this->openImage ($mimeType, $localImage);
		if ($image === false) {
			return $this->error('Unable to open image.');
		}

		// Get original width and height
		$width = imagesx ($image);
		$height = imagesy ($image);
		$origin_x = 0;
		$origin_y = 0;

		// generate new w/h if not provided
		if ($new_width && !$new_height) {
			$new_height = floor ($height * ($new_width / $width));
		} else if ($new_height && !$new_width) {
			$new_width = floor ($width * ($new_height / $height));
		}

		// scale down and add borders
		if ($zoom_crop == 3) {

			$final_height = $height * ($new_width / $width);

			if ($final_height > $new_height) {
				$new_width = $width * ($new_height / $height);
			} else {
				$new_height = $final_height;
			}

		}

		// create a new true color image
		$canvas = imagecreatetruecolor ($new_width, $new_height);
		imagealphablending ($canvas, false);

		if (strlen ($canvas_color) < 6) {
			$canvas_color = 'ffffff';
		}

		$canvas_color_R = hexdec (substr ($canvas_color, 0, 2));
		$canvas_color_G = hexdec (substr ($canvas_color, 2, 2));
		$canvas_color_B = hexdec (substr ($canvas_color, 2, 2));

		// Create a new transparent color for image
		$color = imagecolorallocatealpha ($canvas, $canvas_color_R, $canvas_color_G, $canvas_color_B, 127);

		// Completely fill the background of the new image with allocated color.
		imagefill ($canvas, 0, 0, $color);

		// scale down and add borders
		if ($zoom_crop == 2) {

			$final_height = $height * ($new_width / $width);

			if ($final_height > $new_height) {

				$origin_x = $new_width / 2;
				$new_width = $width * ($new_height / $height);
				$origin_x = round ($origin_x - ($new_width / 2));

			} else {

				$origin_y = $new_height / 2;
				$new_height = $final_height;
				$origin_y = round ($origin_y - ($new_height / 2));

			}

		}

		// Restore transparency blending
		imagesavealpha ($canvas, true);

		if ($zoom_crop > 0) {

			$src_x = $src_y = 0;
			$src_w = $width;
			$src_h = $height;

			$cmp_x = $width / $new_width;
			$cmp_y = $height / $new_height;

			// calculate x or y coordinate and width or height of source
			if ($cmp_x > $cmp_y) {

				$src_w = round ($width / $cmp_x * $cmp_y);
				$src_x = round (($width - ($width / $cmp_x * $cmp_y)) / 2);

			} else if ($cmp_y > $cmp_x) {

				$src_h = round ($height / $cmp_y * $cmp_x);
				$src_y = round (($height - ($height / $cmp_y * $cmp_x)) / 2);

			}

			// positional cropping!
			if ($align) {
				if (strpos ($align, 't') !== false) {
					$src_y = 0;
				}
				if (strpos ($align, 'b') !== false) {
					$src_y = $height - $src_h;
				}
				if (strpos ($align, 'l') !== false) {
					$src_x = 0;
				}
				if (strpos ($align, 'r') !== false) {
					$src_x = $width - $src_w;
				}
			}

			imagecopyresampled ($canvas, $image, $origin_x, $origin_y, $src_x, $src_y, $new_width, $new_height, $src_w, $src_h);

		} else {

			// copy and resize part of an image with resampling
			imagecopyresampled ($canvas, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);

		}

		if ($filters != '' && function_exists ('imagefilter') && defined ('IMG_FILTER_NEGATE')) {
			// apply filters to image
			$filterList = explode ('|', $filters);
			foreach ($filterList as $fl) {

				$filterSettings = explode (',', $fl);
				if (isset ($imageFilters[$filterSettings[0]])) {

					for ($i = 0; $i < 4; $i ++) {
						if (!isset ($filterSettings[$i])) {
							$filterSettings[$i] = null;
						} else {
							$filterSettings[$i] = (int) $filterSettings[$i];
						}
					}

					switch ($imageFilters[$filterSettings[0]][1]) {

						case 1:

							imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1]);
							break;

						case 2:

							imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2]);
							break;

						case 3:

							imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2], $filterSettings[3]);
							break;

						case 4:

							imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2], $filterSettings[3], $filterSettings[4]);
							break;

						default:

							imagefilter ($canvas, $imageFilters[$filterSettings[0]][0]);
							break;

					}
				}
			}
		}

		// sharpen image
		if ($sharpen && function_exists ('imageconvolution')) {

			$sharpenMatrix = array (
					array (-1,-1,-1),
					array (-1,16,-1),
					array (-1,-1,-1),
					);

			$divisor = 8;
			$offset = 0;

			imageconvolution ($canvas, $sharpenMatrix, $divisor, $offset);

		}
		//Straight from WordPress core code. Reduces filesize by up to 70% for PNG's
		if ( (IMAGETYPE_PNG == $origType || IMAGETYPE_GIF == $origType) && function_exists('imageistruecolor') && !imageistruecolor( $image ) && imagecolortransparent( $image ) > 0 ){
			imagetruecolortopalette( $canvas, false, imagecolorstotal( $image ) );
		}

		$imgType = "";
		$tempfile = tempnam($this->cacheDirectory, 'timthumb_tmpimg_');
		if(preg_match('/^image\/(?:jpg|jpeg)$/i', $mimeType)){
			$imgType = 'jpg';
			imagejpeg($canvas, $tempfile, $quality);
		} else if(preg_match('/^image\/png$/i', $mimeType)){
			$imgType = 'png';
			imagepng($canvas, $tempfile, floor($quality * 0.09));
		} else if(preg_match('/^image\/gif$/i', $mimeType)){
			$imgType = 'gif';
			imagegif($canvas, $tempfile);
		} else {
			return $this->sanityFail("Could not match mime type after verifying it previously.");
		}

		if($imgType == 'png' && OPTIPNG_ENABLED && OPTIPNG_PATH && @is_file(OPTIPNG_PATH)){
			$exec = OPTIPNG_PATH;
			$this->debug(3, "optipng'ing $tempfile");
			$presize = filesize($tempfile);
			$out = `$exec -o1 $tempfile`; //you can use up to -o7 but it really slows things down
			clearstatcache();
			$aftersize = filesize($tempfile);
			$sizeDrop = $presize - $aftersize;
			if($sizeDrop > 0){
				$this->debug(1, "optipng reduced size by $sizeDrop");
			} else if($sizeDrop < 0){
				$this->debug(1, "optipng increased size! Difference was: $sizeDrop");
			} else {
				$this->debug(1, "optipng did not change image size.");
			}
		} else if($imgType == 'png' && PNGCRUSH_ENABLED && PNGCRUSH_PATH && @is_file(PNGCRUSH_PATH)){
			$exec = PNGCRUSH_PATH;
			$tempfile2 = tempnam($this->cacheDirectory, 'timthumb_tmpimg_');
			$this->debug(3, "pngcrush'ing $tempfile to $tempfile2");
			$out = `$exec $tempfile $tempfile2`;
			$todel = "";
			if(is_file($tempfile2)){
				$sizeDrop = filesize($tempfile) - filesize($tempfile2);
				if($sizeDrop > 0){
					$this->debug(1, "pngcrush was succesful and gave a $sizeDrop byte size reduction");
					$todel = $tempfile;
					$tempfile = $tempfile2;
				} else {
					$this->debug(1, "pngcrush did not reduce file size. Difference was $sizeDrop bytes.");
					$todel = $tempfile2;
				}
			} else {
				$this->debug(3, "pngcrush failed with output: $out");
				$todel = $tempfile2;
			}
			@unlink($todel);
		}

		$this->debug(3, "Rewriting image with security header.");
		$tempfile4 = tempnam($this->cacheDirectory, 'timthumb_tmpimg_');
		$context = stream_context_create ();
		$fp = fopen($tempfile,'r',0,$context);
		file_put_contents($tempfile4, $this->filePrependSecurityBlock . $imgType . ' ?' . '>'); //6 extra bytes, first 3 being image type
		file_put_contents($tempfile4, $fp, FILE_APPEND);
		fclose($fp);
		@unlink($tempfile);
		$this->debug(3, "Locking and replacing cache file.");
		$lockFile = $this->cachefile . '.lock';
		$fh = fopen($lockFile, 'w');
		if(! $fh){
			return $this->error("Could not open the lockfile for writing an image.");
		}
		if(flock($fh, LOCK_EX)){
			@unlink($this->cachefile); //rename generally overwrites, but doing this in case of platform specific quirks. File might not exist yet.
			rename($tempfile4, $this->cachefile);
			flock($fh, LOCK_UN);
			fclose($fh);
			@unlink($lockFile);
		} else {
			fclose($fh);
			@unlink($lockFile);
			@unlink($tempfile4);
			return $this->error("Could not get a lock for writing.");
		}
		$this->debug(3, "Done image replace with security header. Cleaning up and running cleanCache()");
		imagedestroy($canvas);
		imagedestroy($image);
		return true;
	}
	protected function calcDocRoot(){
		$docRoot = @$_SERVER['DOCUMENT_ROOT'];
		if(!isset($docRoot)){
			$this->debug(3, "DOCUMENT_ROOT is not set. This is probably windows. Starting search 1.");
			if(isset($_SERVER['SCRIPT_FILENAME'])){
				$docRoot = str_replace( '\\', '/', substr($_SERVER['SCRIPT_FILENAME'], 0, 0-strlen($_SERVER['PHP_SELF'])));
				$this->debug(3, "Generated docRoot using SCRIPT_FILENAME and PHP_SELF as: $docRoot");
			}
		}
		if(!isset($docRoot)){
			$this->debug(3, "DOCUMENT_ROOT still is not set. Starting search 2.");
			if(isset($_SERVER['PATH_TRANSLATED'])){
				$docRoot = str_replace( '\\', '/', substr(str_replace('\\\\', '\\', $_SERVER['PATH_TRANSLATED']), 0, 0-strlen($_SERVER['PHP_SELF'])));
				$this->debug(3, "Generated docRoot using PATH_TRANSLATED and PHP_SELF as: $docRoot");
			}
		}
		if($docRoot && $_SERVER['DOCUMENT_ROOT'] != '/'){ $docRoot = preg_replace('/\/$/', '', $docRoot); }
		$this->debug(3, "Doc root is: " . $docRoot);
		$this->docRoot = $docRoot;

	}
	protected function getLocalImagePath($src){
		$src = preg_replace('/^\//', '', $src); //strip off the leading '/'
		$realDocRoot = realpath($this->docRoot);  //See issue 224. Using realpath as a windows fix.
		if(! $this->docRoot){
			$this->debug(3, "We have no document root set, so as a last resort, lets check if the image is in the current dir and serve that.");
			//We don't support serving images outside the current dir if we don't have a doc root for security reasons.
			$file = preg_replace('/^.*?([^\/\\\\]+)$/', '$1', $src); //strip off any path info and just leave the filename.
			if(is_file($file)){
				return realpath($file);
			}
			return $this->error("Could not find your website document root and the file specified doesn't exist in timthumbs directory. We don't support serving files outside timthumb's directory without a document root for security reasons.");
		} //Do not go past this point without docRoot set

		//Try src under docRoot
		if(file_exists ($this->docRoot . '/' . $src)) {
			$this->debug(3, "Found file as " . $this->docRoot . '/' . $src);
			$real = realpath($this->docRoot . '/' . $src);
			if(strpos($real, $realDocRoot) === 0){
				return $real;
			} else {
				$this->debug(1, "Security block: The file specified occurs outside the document root.");
				//allow search to continue
			}
		}
		//Check absolute paths and then verify the real path is under doc root
		$absolute = realpath('/' . $src);
		if($absolute && file_exists($absolute)){ //realpath does file_exists check, so can probably skip the exists check here
			$this->debug(3, "Found absolute path: $absolute");
			if(! $this->docRoot){ $this->sanityFail("docRoot not set when checking absolute path."); }
			if(strpos($absolute, $realDocRoot) === 0){
				return $absolute;
			} else {
				$this->debug(1, "Security block: The file specified occurs outside the document root.");
				//and continue search
			}
		}
		$base = $this->docRoot;
		foreach (explode('/', str_replace($this->docRoot, '', $_SERVER['SCRIPT_FILENAME'])) as $sub){
			$base .= $sub . '/';
			$this->debug(3, "Trying file as: " . $base . $src);
			if(file_exists($base . $src)){
				$this->debug(3, "Found file as: " . $base . $src);
				$real = realpath($base . $src);
				if(strpos($real, $realDocRoot) === 0){
					return $real;
				} else {
					$this->debug(1, "Security block: The file specified occurs outside the document root.");
					//And continue search
				}
			}
		}
		return false;
	}
	protected function toDelete($name){
		$this->debug(3, "Scheduling file $name to delete on destruct.");
		$this->toDeletes[] = $name;
	}
	protected function serveWebshot(){
		$this->debug(3, "Starting serveWebshot");
		$instr = "Please follow the instructions at http://code.google.com/p/timthumb/ to set your server up for taking website screenshots.";
		if(! is_file(WEBSHOT_CUTYCAPT)){
			return $this->error("CutyCapt is not installed. $instr");
		}
		if(! is_file(WEBSHOT_XVFB)){
			return $this->Error("Xvfb is not installed. $instr");
		}
		$cuty = WEBSHOT_CUTYCAPT;
		$xv = WEBSHOT_XVFB;
		$screenX = WEBSHOT_SCREEN_X;
		$screenY = WEBSHOT_SCREEN_Y;
		$colDepth = WEBSHOT_COLOR_DEPTH;
		$format = WEBSHOT_IMAGE_FORMAT;
		$timeout = WEBSHOT_TIMEOUT * 1000;
		$ua = WEBSHOT_USER_AGENT;
		$jsOn = WEBSHOT_JAVASCRIPT_ON ? 'on' : 'off';
		$javaOn = WEBSHOT_JAVA_ON ? 'on' : 'off';
		$pluginsOn = WEBSHOT_PLUGINS_ON ? 'on' : 'off';
		$proxy = WEBSHOT_PROXY ? ' --http-proxy=' . WEBSHOT_PROXY : '';
		$tempfile = tempnam($this->cacheDirectory, 'timthumb_webshot');
		$url = $this->src;
		if(! preg_match('/^https?:\/\/[a-zA-Z0-9\.\-]+/i', $url)){
			return $this->error("Invalid URL supplied.");
		}
		$url = preg_replace('/[^A-Za-z0-9\-\.\_\~:\/\?\#\[\]\@\!\$\&\'\(\)\*\+\,\;\=]+/', '', $url); //RFC 3986
		//Very important we don't allow injection of shell commands here. URL is between quotes and we are only allowing through chars allowed by a the RFC
		// which AFAIKT can't be used for shell injection.
		if(WEBSHOT_XVFB_RUNNING){
			putenv('DISPLAY=:100.0');
			$command = "$cuty $proxy --max-wait=$timeout --user-agent=\"$ua\" --javascript=$jsOn --java=$javaOn --plugins=$pluginsOn --js-can-open-windows=off --url=\"$url\" --out-format=$format --out=$tempfile";
		} else {
			$command = "$xv --server-args=\"-screen 0, {$screenX}x{$screenY}x{$colDepth}\" $cuty $proxy --max-wait=$timeout --user-agent=\"$ua\" --javascript=$jsOn --java=$javaOn --plugins=$pluginsOn --js-can-open-windows=off --url=\"$url\" --out-format=$format --out=$tempfile";
		}
		$this->debug(3, "Executing command: $command");
		$out = `$command`;
		$this->debug(3, "Received output: $out");
		if(! is_file($tempfile)){
			$this->set404();
			return $this->error("The command to create a thumbnail failed.");
		}
		$this->cropTop = true;
		if($this->processImageAndWriteToCache($tempfile)){
			$this->debug(3, "Image processed succesfully. Serving from cache");
			return $this->serveCacheFile();
		} else {
			return false;
		}
	}
	protected function serveExternalImage(){
		if(! preg_match('/^https?:\/\/[a-zA-Z0-9\-\.]+/i', $this->src)){
			$this->error("Invalid URL supplied.");
			return false;
		}
		$tempfile = tempnam($this->cacheDirectory, 'timthumb');
		$this->debug(3, "Fetching external image into temporary file $tempfile");
		$this->toDelete($tempfile);
		#fetch file here
		if(! $this->getURL($this->src, $tempfile)){
			@unlink($this->cachefile);
			touch($this->cachefile);
			$this->debug(3, "Error fetching URL: " . $this->lastURLError);
			$this->error("Error reading the URL you specified from remote host." . $this->lastURLError);
			return false;
		}

		$mimeType = $this->getMimeType($tempfile);
		if(! preg_match("/^image\/(?:jpg|jpeg|gif|png)$/i", $mimeType)){
			$this->debug(3, "Remote file has invalid mime type: $mimeType");
			@unlink($this->cachefile);
			touch($this->cachefile);
			$this->error("The remote file is not a valid image.");
			return false;
		}
		if($this->processImageAndWriteToCache($tempfile)){
			$this->debug(3, "Image processed succesfully. Serving from cache");
			return $this->serveCacheFile();
		} else {
			return false;
		}
	}
	public static function curlWrite($h, $d){
		fwrite(self::$curlFH, $d);
		self::$curlDataWritten += strlen($d);
		if(self::$curlDataWritten > MAX_FILE_SIZE){
			return 0;
		} else {
			return strlen($d);
		}
	}
	protected function serveCacheFile(){
		$this->debug(3, "Serving {$this->cachefile}");
		if(! is_file($this->cachefile)){
			$this->error("serveCacheFile called in timthumb but we couldn't find the cached file.");
			return false;
		}
		$fp = fopen($this->cachefile, 'rb');
		if(! $fp){ return $this->error("Could not open cachefile."); }
		fseek($fp, strlen($this->filePrependSecurityBlock), SEEK_SET);
		$imgType = fread($fp, 3);
		fseek($fp, 3, SEEK_CUR);
		if(ftell($fp) != strlen($this->filePrependSecurityBlock) + 6){
			@unlink($this->cachefile);
			return $this->error("The cached image file seems to be corrupt.");
		}
		$imageDataSize = filesize($this->cachefile) - (strlen($this->filePrependSecurityBlock) + 6);
		$this->sendImageHeaders($imgType, $imageDataSize);
		$bytesSent = @fpassthru($fp);
		fclose($fp);
		if($bytesSent > 0){
			return true;
		}
		$content = file_get_contents ($this->cachefile);
		if ($content != FALSE) {
			$content = substr($content, strlen($this->filePrependSecurityBlock) + 6);
			echo $content;
			$this->debug(3, "Served using file_get_contents and echo");
			return true;
		} else {
			$this->error("Cache file could not be loaded.");
			return false;
		}
	}
	protected function sendImageHeaders($mimeType, $dataSize){
		if(! preg_match('/^image\//i', $mimeType)){
			$mimeType = 'image/' . $mimeType;
		}
		if(strtolower($mimeType) == 'image/jpg'){
			$mimeType = 'image/jpeg';
		}
		$gmdate_expires = gmdate ('D, d M Y H:i:s', strtotime ('now +10 days')) . ' GMT';
		$gmdate_modified = gmdate ('D, d M Y H:i:s') . ' GMT';
		// send content headers then display image
		header ('Content-Type: ' . $mimeType);
		header ('Accept-Ranges: none'); //Changed this because we don't accept range requests
		header ('Last-Modified: ' . $gmdate_modified);
		header ('Content-Length: ' . $dataSize);
		if(BROWSER_CACHE_DISABLE){
			$this->debug(3, "Browser cache is disabled so setting non-caching headers.");
			header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
			header("Pragma: no-cache");
			header('Expires: ' . gmdate ('D, d M Y H:i:s', time()));
		} else {
			$this->debug(3, "Browser caching is enabled");
			header('Cache-Control: max-age=' . BROWSER_CACHE_MAX_AGE . ', must-revalidate');
			header('Expires: ' . $gmdate_expires);
		}
		return true;
	}
	protected function securityChecks(){
	}
	protected function param($property, $default = ''){
		if (isset ($_GET[$property])) {
			return $_GET[$property];
		} else {
			return $default;
		}
	}
	protected function openImage($mimeType, $src){
		switch ($mimeType) {
			case 'image/jpg': //This isn't a valid mime type so we should probably remove it
			case 'image/jpeg':
				$image = imagecreatefromjpeg ($src);
				break;

			case 'image/png':
				$image = imagecreatefrompng ($src);
				break;

			case 'image/gif':
				$image = imagecreatefromgif ($src);
				break;
		}

		return $image;
	}
	protected function getIP(){
		$rem = @$_SERVER["REMOTE_ADDR"];
		$ff = @$_SERVER["HTTP_X_FORWARDED_FOR"];
		$ci = @$_SERVER["HTTP_CLIENT_IP"];
		if(preg_match('/^(?:192\.168|172\.16|10\.|127\.)/', $rem)){
			if($ff){ return $ff; }
			if($ci){ return $ci; }
			return $rem;
		} else {
			if($rem){ return $rem; }
			if($ff){ return $ff; }
			if($ci){ return $ci; }
			return "UNKNOWN";
		}
	}
	protected function debug($level, $msg){
		if(DEBUG_ON && $level <= DEBUG_LEVEL){
			$execTime = sprintf('%.6f', microtime(true) - $this->startTime);
			$tick = sprintf('%.6f', 0);
			if($this->lastBenchTime > 0){
				$tick = sprintf('%.6f', microtime(true) - $this->lastBenchTime);
			}
			$this->lastBenchTime = microtime(true);
			error_log("TimThumb Debug line " . __LINE__ . " [$execTime : $tick]: $msg");
		}
	}
	protected function sanityFail($msg){
		return $this->error("There is a problem in the timthumb code. Message: Please report this error at <a href='http://code.google.com/p/timthumb/issues/list'>timthumb's bug tracking page</a>: $msg");
	}
	protected function getMimeType($file){
		$info = getimagesize($file);
		if(is_array($info) && $info['mime']){
			return $info['mime'];
		}
		return '';
	}
	protected function setMemoryLimit(){
		$inimem = ini_get('memory_limit');
		$inibytes = timthumb::returnBytes($inimem);
		$ourbytes = timthumb::returnBytes(MEMORY_LIMIT);
		if($inibytes < $ourbytes){
			ini_set ('memory_limit', MEMORY_LIMIT);
			$this->debug(3, "Increased memory from $inimem to " . MEMORY_LIMIT);
		} else {
			$this->debug(3, "Not adjusting memory size because the current setting is " . $inimem . " and our size of " . MEMORY_LIMIT . " is smaller.");
		}
	}
	protected static function returnBytes($size_str){
		switch (substr ($size_str, -1))
		{
			case 'M': case 'm': return (int)$size_str * 1048576;
			case 'K': case 'k': return (int)$size_str * 1024;
			case 'G': case 'g': return (int)$size_str * 1073741824;
			default: return $size_str;
		}
	}
	protected function getURL($url, $tempfile){
		$this->lastURLError = false;
		$url = preg_replace('/ /', '%20', $url);
		if(function_exists('curl_init')){
			$this->debug(3, "Curl is installed so using it to fetch URL.");
			self::$curlFH = fopen($tempfile, 'w');
			if(! self::$curlFH){
				$this->error("Could not open $tempfile for writing.");
				return false;
			}
			self::$curlDataWritten = 0;
			$this->debug(3, "Fetching url with curl: $url");
			$curl = curl_init($url);
			curl_setopt ($curl, CURLOPT_TIMEOUT, CURL_TIMEOUT);
			curl_setopt ($curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.122 Safari/534.30");
			curl_setopt ($curl, CURLOPT_RETURNTRANSFER, TRUE);
			curl_setopt ($curl, CURLOPT_HEADER, 0);
			curl_setopt ($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
			curl_setopt ($curl, CURLOPT_WRITEFUNCTION, 'timthumb::curlWrite');
			@curl_setopt ($curl, CURLOPT_FOLLOWLOCATION, true);
			@curl_setopt ($curl, CURLOPT_MAXREDIRS, 10);

			$curlResult = curl_exec($curl);
			fclose(self::$curlFH);
			$httpStatus = curl_getinfo($curl, CURLINFO_HTTP_CODE);
			if($httpStatus == 404){
				$this->set404();
			}
			if($curlResult){
				curl_close($curl);
				return true;
			} else {
				$this->lastURLError = curl_error($curl);
				curl_close($curl);
				return false;
			}
		} else {
			$img = @file_get_contents ($url);
			if($img === false){
				$err = error_get_last();
				if(is_array($err) && $err['message']){
					$this->lastURLError = $err['message'];
				} else {
					$this->lastURLError = $err;
				}
				if(preg_match('/404/', $this->lastURLError)){
					$this->set404();
				}

				return false;
			}
			if(! file_put_contents($tempfile, $img)){
				$this->error("Could not write to $tempfile.");
				return false;
			}
			return true;
		}

	}
	protected function serveImg($file){
		$s = getimagesize($file);
		if(! ($s && $s['mime'])){
			return false;
		}
		header ('Content-Type: ' . $s['mime']);
		header ('Content-Length: ' . filesize($file) );
		header ('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
		header ("Pragma: no-cache");
		$bytes = @readfile($file);
		if($bytes > 0){
			return true;
		}
		$content = @file_get_contents ($file);
		if ($content != FALSE){
			echo $content;
			return true;
		}
		return false;

	}
	protected function set404(){
		$this->is404 = true;
	}
	protected function is404(){
		return $this->is404;
	}
}

25 九, 2011

Discuz X2头像上传判断解析

Posted by: kinglife In: php

首先总结下前一次遇到的一个问题,就是设置了强制上传头像才可以发贴,但是实际上传完头像依然提示需要上传头像
解决方法:打开后台 -> 站长 -> Ucenter设置 ->在”UCenter IP 地址:”这栏写实际IP或者不写即可,默认的是”127.0.0.1″
这里要注意的是 别直接打开后台菜单的”Ucenter”,而是左边的”站长”

补充下X2的头像在数据库中的判断,表 “bbs_common_member” 字段 ‘avatarstatus”,默认值是0,如果上传完它会变成1
如果你想批量让会员变成上传过头像的状态只需要运行下面的SQL语句.


UPDATE `bbs_common_member` SET avatarstatus=1 //后面也可以加条件等等

这三个控件在.NET的工具箱里面默认是没有的,需要手工添加
右击工具箱中的任意单元 点击选择项
然后在.NET Framework组件中找到对应的选项在前面勾上即可.
附三者的关系代码,三者控件名分别为 drive1 dir1,实现代码:


    Private Sub Drive1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Drive1.SelectedIndexChanged
        Dir1.Path = Drive1.Drive
    End Sub

    Private Sub Dir1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Dir1.SelectedIndexChanged
        File1.Path = Dir1.Path
    End Sub
Tags:

22 七, 2011

为什么drupal安装只能选择SQLite数据库?

Posted by: kinglife In: php

由于drupal使用的是pdo连接数据库,如果没有开启pdo的话,在安装drupal时,不会出现mysql供选择。
解决方法:
打开php.ini
extension=php_pdo.dll
extension=php_pdo_mysql.dll
将前面的注释取消掉以加载pdo
保存后重启服务即可

05 七, 2011

php_mcrypt.dll无法加载解决方法

Posted by: kinglife In: php

今天用AppServ搭建了个PHP的环境,无论如何都加载不了php_mcrypt.dll
晚上流传的集中解决办法:
1.php.ini里面查找extension=php_mcrypt.dll,去掉前面的分号”;” ,重启apache.无效(注意:在AppServ中php.ini在dinwos目录下)

2.复制php目录下的libmcrypt.dll到windows/system32目录下,重启IIS ,无效

3.自己总结的办法:试着尝试了一下,将libmcrypt.dll复制到apache的bin目录下,生效

打开配置文件httpd.conf,找到下面这行代码


Options FollowSymLinks
AllowOverride None
Order deny,allow
deny from all
Satisfy all

将”deny from all“修改为”allow from all“,变成以下代码


Options FollowSymLinks
AllowOverride None
Order deny,allow
allow from all
Satisfy all

保存后重启apache即可

07 六, 2011

WordPress国外模板不显示中文字符的解决方法

Posted by: kinglife In: php

WordPress的国外主题的确非常多 毕竟是来是全世界的WordPress设计师和开发者一起参与的
所以别把资源局限在国内的中文主题上.
今天找了个主题,在使用wordpress的一个主题中发现个问题:所有中文字符都不显示了,剩下的只有英文和数字.
于是查了下相关资料整理如下:
如有发现这种情况的主题大多都是用Cufon这种网页文字渲染特效使字体达到更好看的效果.

首先解释下什么是 Cufon
Cufon 是一个用来替代 sIFR 框架, 实现在网页中对文字字体进行渲染功能的纯 JavaScript 开源类库(cufon-yui.js)。
为什么要使用 Cufon:
在web开发中,经常面对的一种“冲突”,即“字体(Font Family)冲突”。
通常的这一冲突总是爆发于 Web 页面的设计者(Designer)和开发者(Coder)之间。在很多场合下,Web 页面的设计者都会倾向于在他们的页面设计稿中,为文字附加使用一些“特殊”的字体和特效,以此来展示他们卓越的设计能力。比如设计一个公司的Logo,图片上的一些特殊字体是从ps字库中调出的,当然这些文字在图片上显示肯定是没有问题的,但是如果要在网页中用文本来显示这些效果,就是会让开发人员抓狂了,因为浏览器并不支持所有的字体,这种情况Cufon就会大显身手了。

由此我们可以看出原来是Cufon在捣乱,因为它不支持中文字体的缘故所以中文字符都无法显示.

那么知道核心问题我们就知道该如何解决了,只要找到对应的目录文件和引用的地方给它删除了就可以了.
一般引用文件基本都是在header.php中,直接用编辑器的查找功能查找关键词”Cufon”即可. 找到引用的哪行然后删除即可.当然为了文件的整洁,多余的文件也可以删除,一般都在js目录中.

31 五, 2011

网站关闭12天百度权重恢复全过程

Posted by: kinglife In: SEO

本站记录权重恢复过程
记录下自5月13日 站点被关闭之后的一些情况
5月13日 站点关闭进入备案阶段,独立IP,用IP依然可以访问

5月26日 站点恢复正常
百度收录了七百多页的站点 收录还剩几十页.
用site命令查看已经不见首页了.
站点依然正常更新.

5月30日 站点收录多出几页
用site命令查看已经看到首页,快照停留在5月11日

持续查看更新中.

Tags: ,

Flickr PhotoStream

    flickrRSS probably needs to be setup

About

Name:KingLife
Email:lifewz#163.com