为什么要用安全模式?

2011年8月1日 effect 没有评论

什么是安全模式?

为了解决一些共享服务器上的安全问题而设立的模式,有一些文件操作的属主检查和一些函数的限制等等。在一些ISP供应商提供的服务器上面,一台服务器往往运行了N个web site,所以为了保证每个站点以及操作系统的安全,这些服务器往往启用了安全模式。

有什么影响?

安全模式才初衷是为了保证操作系统的安全性以及各个web site的安全性。操作系统的安全性可以防止用户恶意的调用一些系统命令以及限制一些文件的访问,所以会限制了exec、system等函数有一个目录检查,如果执行的命令在safe_mode_exec_dir 下面才可以被允许执行。其次会限制一些文件操作的相关函数,比如fopen、mkdir、copy、unlink、link、rename、chown等,这里会检查被操作的目录或者文件是否与被执行的脚本有相同的 UID(所有者)。其他的影响请参看手册/安全/安全模式。

真的有用吗?

正如手册所说:在PHP这一层解决服务器的安全性问题,似乎不太靠谱。对于ISP提供商来说,启用安全模式是必须的,但是还需要其他的安全性限制,比如限制配置disable_functions、disable_classes,每个用户建立自己的执行账户等。而对于公司的服务器来说,没必要启用安全模式,但是代码的安全要严格查询,尤其是一些根据用户的输入来处理对应的文件,这一步要检查是否有漏掉导致引入了一个系统文件等。

分类: php 标签: ,

ini_set知多少

2011年7月20日 effect 没有评论

想必大家都用过这个函数,可以动态的修改php的配置项。但是是不是所有的配置项都可以用ini_set来修改呢?答案肯定是否定的!因为如果都可以修改,那么有些ISP的disable_functions等安全性配置可以轻松被突破,那么哪些是可以修改的呢?本文就来寻找一下答案。

打开你的PHP手册,找到附录中的php.ini配置选项列表,每个配置选项都有一个可修改范围,范围有下面几种值:

PHP_INI_PERDIR 可以在php.ini    .htaccess   http.conf中设置。.htaccess和http.conf只能适用于apache的web server,并且是模块安装的才可以。手册中看到upload_max_filesize的配置范围就是PHP_INI_PERDIR,那么在.htaccess或者http.conf中这样配置:

php_value upload_max_filesize 180M

。这样你的上传文件的最大文件大小是180M了。

PHP_INI_SYSTEM 只能在php.ini和http.conf中配置。http.conf中的配置方法参看上面实例。

PHP_INI_ALL 可以在任何地方配置,所以只有访问是这个的才能在脚本中配置,所以ini_set可配置的选项只能是这个范围之内的

PHP_INI_USER 手册上说是可以在用户的脚本中可以配置,但是没有找到一个范围是这个的配置选项。

分类: php 标签:

给你的PHP加速

2011年7月19日 effect 没有评论

PHP作为一种解释性的语言,可以快速的构建各种WEB服务,并且有着良好的扩展性和维护性。然而每次请求时候,都会把PHP源码解释编译成操作系统可识别的机器码然后再执行,这样下来每次请求都会重复的进行解释编译,那有没有什么方法可以不重复解释编译呢?本文就介绍几种常用的PHP加速器。

什么是PHP加速器?

通过前面的了解,每次HTTP的请求都会进行一个过程:把编译解释成操作系统可以直接运行的机器码。这是一个重复的工作,加速器的功能就是把这一过程缓存起来重复使用。常用的加速器有:Alternative PHP Cache (APC)、XCache、eAccelerator。

Xcache

安装方式无非就是标准的PECL的按照方式,下面就说一下关键的配置文件和查看统计信息的方法。

配置

xcache.cacher = On    开启opcode 缓存器  当size为0时候无效

xcache.size  = 64M 缓存大小一般的网站64M足够,如果此台WEB SERVER有多个vhosts,那么可以适当的增加到256M或者512M等

xcache.count  CPU个数,如果是双核算2,8核的是8

xcache.var_size 同xcache.size

xcache.var_count 同xcache.count

xcache.ttl  缓存项目的ttl(Time To Live) 生命周期,0是永远

xcache.gc_interval  扫描过期项目的时间间隔, 0不扫描,

xcache.coverager  是否启用代码覆盖,测试时候发现关闭次选项加速效果更好

统计信息

拷贝源码中的admin目录下的文件到你的网站的目光目录下(比如是xcacheadmin),那么输入http://yourdomain/xcacheadmin/,这里会有验证框弹出,输入配置中的admin和pass即可。

eaccelerator

安装方式也是标准的PECL安装方式

配置

eaccelerator.shm_size = “8″     eAccelerator 可以使用的共享内存的数量 (以兆为单位) . “0″ 是指操作系统的默认值. 默认值是 “0″.
eaccelerator.cache_dir = “/tmp/eaccelerator”
eaccelerator.enable = “1″  是否开启 1打开 0关闭
eaccelerator.optimizer = “1″    是否开启内部优化 1打开
eaccelerator.check_mtime = “1″  是否开启文件修改的检测 1开启 0关闭
eaccelerator.debug = 0  是否打开日志记录。”1″ 为开启,”0″ 为关闭。默认值为 “0″。会将缓存命中得记录写入日志。
eaccelerator.filter = “”   判断缓存的文件,如果以叹号!开头,那么匹配的将不缓存,否则匹配的加入缓存,默认是空,表示所有的都缓存
eaccelerator.shm_max = “0″
eaccelerator.shm_ttl = 0
eaccelerator.prune_period = 0
eaccelerator.shm_only = 0
eaccelerator.compress = 1  是否压缩缓存内容  1允许
eacceleratorcompress_level = 9  压缩内容的等级 9是最高级

其他加速方法

编译

尽可能的只编译你需要的模块、很少用的模块编译成共享模式,执行时动态加载

配置

禁用register_globals

关闭magic_quotes_*

关闭expose_php

后记

加速PHP只是给PHP编译解析这一重复的过程进行优化,而一个WEB服务本身的执行速度还是取决于是否合理的使用了数据库、是否很好的使用了一些缓存系统(比如memcached)、整个架构是否是最优的。当然在这些条件都一致的情况下,使用这些加速软件还是能有一些效果。

APC一直没有实验,对比了一下xcache和eaccelerator,eacce稍微占优,而且配置文件也相对简单一点,所以个人倾向于使用eacce,当然每个项目可能结果不太一样,大家可以对比后再取舍。

分类: php 标签: ,

kohana3在nginx中的重写配置

2011年7月18日 effect 没有评论

在公司内部推广过kohana3,反应还算可以。不过有好几次同事来咨询在nginx下的重写配置,下面作为备忘:

 location / {
         root   /data/vhosts/k3.com/public_html;#这里改为你对应的目录
         index  index.php index.html index.htm;
          if (!-e $request_filename) {
                rewrite ^/(.*)$ /index.php/$1 last;
          }
        }
 
        location ~ ^(.+\.php)(.*)$  {
                root /data/vhosts/k3.com/public_html;#这里改为你对应的目录
                fastcgi_pass 127.0.0.1:9000;
                fastcgi_index index.php;
                set $script $fastcgi_script_name;
            if ($uri ~ "^/index.php(/.+)$") {  ###这个if语句表示如果是如果是以/index.php开头的URL,那么设置sectip为index.php path_info为后面部分
                set $script 'index.php';
                set $path_info  $1;<span style="color: #800000;">###这一行很重要</span>
            }
                fastcgi_param SCRIPT_FILENAME /data/vhosts/k3.com/public_html/$fastcgi_script_name;#这里改为你对应的目录
                fastcgi_param  PATH_INFO $path_info;<span style="color: #800000;">###这一行也很重要 在kohana3中是使用path_info来做route</span>
                include fastcgi_params;
        }

kohana3是一个简单高效的PHP5框架,拥有良好的OO特性,很强的扩展性(非修改源码方式来扩展,在这里小小的BS一下总是想通过修改源码来达到扩展目的的同学),强烈推荐!

分类: php 标签:

真的了解memcached吗?

2011年7月18日 effect 没有评论

1 什么是memcached?

Memcached 是一个高性能的分布式内存对象缓存系统,基于一个存储键/值对的hashmap,也就是常说的Key-Value。主要特性是分布式和内存存储,所以读写速度是非常神速的,1.5W/s没问题的。

2 memecached启动参数

memcached -d -m 2048  -p 11211 -P /tmp/memcached.pid

-d 守护模式

-m 分配最大的内存单位MB

-p 监听端口

-P 保存pid的文件,只有-d的时候才有效果

其他的参数见memcached -h

结合上面的启动参数,关闭memcached的命令是:kill `cat /tmp/memcached.pid`   ,需要注意的是:memcached是存储在内存中,所以kill之后,存储的数据全部没了。

3 服务器状态

使用命令:telnet memcached-server-address port,这样就可以连接上memcached服务器,然后输入stats 即可得到服务器各项状态数据,主要状态说明:

pid 服务器进程id

uptime 服务器运行秒数

time 服务器当前时间锉

version 服务器版本

pointer_size 操作系统指针大小(32位的就是32)

rusage_user 进程累计用户时间

rusage_system 进程累计系统时间

curr_connections  当前打开的连接数

total_connections 系统启动后的连接总数

cmd_get   get请求总数

cmd_set  set请求总数

cmd_flush  flush请求总数

get_hits  get请求命中次数

get_misses  get未命中次数

delete_misses   delete未命中次数

delete_hits delete命中次数

threads  线程数

bytes 存储的item占用的 字节数

curr_items 当前item数目

total_items  系统启动后的总字节数目

evictions  为获取空闲内存而删除的items数(分配给memcache的空间用满后需要删除旧的items来得到空间分配给新的items)

limit_maxbytes   分配的内存大小

bytes_read  读取字节数目

bytes_written  发送字节数目

缓存命中率 = get_hits/cmd_get * 100%

4  php-client

有三种php-client:

1)MemcachedClient.php   使用的是php socket和服务器交互,不推荐 。

2)pecl的memcache扩展 推荐

3) pecl的memcached扩展 基于libmemcached的扩展,相比memcache多了很多方法,而且效率各方面也优于memcache扩展。强烈推荐

5 推荐的分布式方式

memcached服务器本身没有分布式的功能,分布式都是通过客户端根据key值算出对应的服务器节点。比较常规的分布式是求余法,但是这个方法有个致命的硬伤:当要增加或者删减一个服务器节点的时候,当时的缓存命中率大大降低。推荐的方法是一致性hash模式。

如果你使用的是memcache扩展,那么想要使用一致性hash模式,请在php.ini中增加或者修改配置:

Memcache.hash_strategy =consistent
Memcache.hash_function =crc32

如果使用的是memcached,那么在代码中使用:
$mem->setOption(Memcached::OPT_DISTRIBUTION,Memcached::DISTRIBUTION_CONSISTENT);
$mem->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE,true);

6 参考资料

memcached api文档翻译:http://blog.csdn.net/lgg201/article/details/6002928

memcached 安装方式:http://www.9enjoy.com/php-memcached/

一致性hash: http://baike.baidu.com/view/1588037.htm

分类: php, 服务器 标签:

httpsqs配置记录&php client

2011年7月13日 effect 没有评论

什么是httpsqs?

基于http的开源队列服务,使用Tokyo Cabinet 的 B+Tree Key/Value来做持久化存储。

适用于什么应用场景?

比较适合于比较慢而又没有特别高的时效性的应用。比如发送邮件(用户进行了某个操作,需要发送邮件给他的email账户通知。)、图片裁剪、视频转换、日志记录等。这些时效性要求不怎么高,这样就可以采用异步方式 ,让后台来集中处理,可以降低前台的服务压力。

具有什么特点?

支持http GET/POST协议,所以支持HTTP协议的都可以和他通信。

非常快速

高并发

更加详细的内容见官方网站:http://blog.s135.com/httpsqs/

官方提供了两种php client。1)php扩展(门槛高、不使用于win下的用户) 2)httpsqs_client.php (这个代码真不敢恭维)。所以自己写了一个httpsqs的类,供大家使用。

<!--?php class Httpsqs{ 	private $host; 	private $port; 	private $auth; 	private $charset; 	private static $sockets=array(); 	public function __construct($host,$port,$auth='',$charset='utf-8'){ 		$this--->host = $host;
		$this-&gt;port = $port;
		$this-&gt;auth = $auth;
		$this-&gt;charset = $charset;
	}
 
	public function get($name,$kt=0){
		$query  = $this-&gt;build_query($name,'get');
		return $this-&gt;execute($query,'GET','',$kt);
	}
 
	public function put($name,$body,$kt=0){
		$query = $this-&gt;build_query($name,'put');
		return $this-&gt;execute($query,'POST',$body,$kt);
	}
 
	public function reset($name){
		$query = $this-&gt;build_query($name,'reset');
		$r = $this-&gt;execute($query);
		if($r &amp;&amp; $r['data'] == "HTTPSQS_RESET_OK"){
			return true;
		}
		else return false;
	}
 
	public function status($name,$type='text'){
		if($type=='json'){
			$cmd = 'status_json';
		}
		else{
			$cmd = 'status';
		}
		$query = $this-&gt;build_query($name,$cmd);
		$r = $this-&gt;execute($query);
		if($r== false || $r['data']==false || $r['data']=='HTTPSQS_ERROR'){
			return false;
		}
		return $r['data'];
	}
 
	public function view($name,$pos){
		$query = $this-&gt;build_query($name,'view',array("pos=".$pos));
		$r = $this-&gt;execute($query);
		if($r==false || $r['data']==false || $r['data']=='HTTPSQS_ERROR'){
			return false;
		}
		else return $r['data'];
	}
 
	private function build_query($name,$cmd,$extra=array()){
		$tmp  = array("name=".$name,"opt=".$cmd);
		if($this-&gt;auth){
			$tmp[]="auth=".$this-&gt;auth;
		}
		$tmp[]="charset=".$this-&gt;charset;
		$tmp = array_merge($tmp , $extra);
		return '/?'.implode('&amp;',$tmp);
	}
 
	private function execute($query,$type='GET',$body='',$kt=0){
		if($kt==1){
			$key = md5($this-&gt;host.':'.$this-&gt;port);
			if(!isset(self::$sockets[$key])){
				self::$sockets[$key] = fsockopen($this-&gt;host,$this-&gt;port,$error,$errstr,5);
			}
			$socket = self::$sockets[$key];
		}
		else{
			$socket = fsockopen($this-&gt;host,$this-&gt;port,$error,$errstr,5);
		}
		if(!$socket){
			return false;
		}
		$out = "{$type} {$query} HTTP/1.1\r\n";
		$out .="Host: {$this-&gt;host}\r\n";
		if($type=='POST'){
			$out.="Content-Length: ".strlen($body)."\r\n";
		}
		if($kt==0){
			$out .="Connection: close\r\n";
		}
		else{
			$out .="Connection: Keep-Alive\r\n";
		}
		$out .="\r\n";
		if($type=='POST' &amp;&amp; $body){
			$out .=$body;
		}
		fwrite($socket,$out);
		$line = trim(fgets($socket));
		list($proto,$rcode,$result) = explode(" ",$line);
		$len = -1;
		$pos_value = 0;
		while(($line = trim(fgets($socket)))!=""){
			if(strstr($line,'Content-Length:')){
				list($cl,$len) = explode(" ",$line);
			}
			elseif(strstr($line,"Pos:")){
				list($pos_key,$pos_value) = explode(" ",$line);
			}
		}
		if($len&lt;0){ 			return false; 		} 		$body = @fread($socket,$len); 		if($kt==0){ 			fclose($socket); 		} 		return array( 			'pos'=&gt;intval($pos_value),
			'data'=&gt;$body
		);
	}
}

使用demo:

//get
$httpsqs = new Httpsqs('192.168.219.128','1218');
$r = $httpsqs-&gt;get('my_query');
 
//put
$httpsqs = new Httpsqs('192.168.219.128','1218');
$r = $httpsqs-&gt;put('my_query',"my_query_value");
 
//其他的请看源码

后感:
这个队列服务真的很实用,以前也有不少类似的应用,可以异步操作,实现方式是通过日志,比如每5分钟创建一个日志文件,然后每隔5分钟来处理,这样的风险很大,很可能造成数据的丢失等。有了这个,居多的应用都可以实现,异步发邮件,异步打日志,异步裁剪图片等等。

分类: php 标签:

再谈pop.js

2011年4月6日 effect 没有评论

弹出层相信是在JS需求中随处可见,之前写过类似的文章,见:http://web302.com/2010/09/v-colombias-pop-pop-up-plug-in-changes-to-the-points/   但是经过一段时间使用,做了如下修改:

/*
1.自动化show,
2.增加onShow和onHide事件
3.自动寻找关闭按钮和移动标题栏
*/
(function($){
	function drop(objs,dragDivid){
		objs.css('cursor','move')
			.unbind('mousedown')
			.bind('mousedown',function(e){
				var posX;
				var posY;
				var fdiv = document.getElementById(dragDivid);
				if(!e) e = window.event;
				posX = e.clientX - parseInt(fdiv.style.left);
				posY = e.clientY - parseInt(fdiv.style.top);
				function mousemove(ev){
					if(ev==null) ev = window.event;
					fdiv.style.left = (ev.clientX - posX) + "px";
					fdiv.style.top = (ev.clientY - posY) + "px";
					return false;
				}
				$(document).unbind('mousemove',mousemove);
				$(document).mousemove(mousemove).mouseup(function(){
					$(document).unbind('mousemove',mousemove);
				});
			});
	}
	function setDivPox(jqBackDiv,jqPopDiv,isScrollEvent)
	{
		//自动判断当前是否支持W3C标准的
		var bodyObj = document.documentElement;
		//文档没有DOCTYPE声明,是 HTML文档,否则是XHTML文档
		if(document.compatMode == 'BackCompat'){
			bodyObj = document.body;
		}
		//--设置遮罩层为满屏
		jqBackDiv.width(Math.max(bodyObj.scrollWidth, document.documentElement.clientWidth));
		jqBackDiv.height(Math.max(bodyObj.scrollHeight, document.documentElement.clientHeight));
		//调整要显示的DIV的位置
		var dleft = bodyObj.clientWidth/2 - jqPopDiv.width()/2;
		var dtop = bodyObj.clientHeight/2 - jqPopDiv.height()/2;
		//如果是Scroll事件
		if(typeof(isScrollEvent)!= 'undefined' &amp;&amp; isScrollEvent){
			dleft += bodyObj.scrollLeft + document.body.scrollLeft;
			dtop += bodyObj.scrollTop + document.body.scrollTop;
		}
		jqPopDiv.css({left:dleft,top:dtop,position:'absolute',zIndex:1001});
	}
	function pop(options,jq){
		$.extend(this.options,options || {});
		this.jq = jq;
	}
	pop.prototype={
		options:{
			backDivColor:'#333',//遮罩层的颜色
			showAnimate:false, //弹出层显示时是否有动画效果
			onHide:function(){},
			onShow:function(){},
			backDivId:'pop__div__id'//遮罩层的ID,一般不在程序中设置
		},
		show:function(){
			var self = this;
			//弹出一个遮罩层
			var backDivId = this.options.backDivId;
			//--如果弹出层不存在则添加
			if($('#'+backDivId).length &lt; 1){
				//--遮罩层追加到 body  //#333
				var divStr = '
 
';
				$(divStr).appendTo('body');
			}
 
			//设置位置
			setDivPox($('#'+backDivId),this.jq);
 
			//动画效果显示出来
			$('#'+backDivId).show();
			this.options.showAnimate ? this.jq.fadeIn("slow") : this.jq.show();
 
			this.jq.data('resize',function(){
				setTimeout(function(){
					setDivPox($('#'+backDivId),self.jq);
				},10);
			});
			this.jq.data('scroll',function(){
				setTimeout(function(){
					setDivPox($('#'+backDivId),self.jq,true);
				},10);
			});
			this.jq.data('_hide',function(){
				self.hide();
			});
 
			$(window).resize(this.jq.data('resize')).scroll(this.jq.data('scroll'));
			this.jq.find('[close]').click(this.jq.data('_hide'));
			drop(this.jq.find('[drop]'),this.jq.attr('id'));
			this.options.onShow.call(this);
			return this;
		},
		hide:function(){
			this.jq.hide();
			$('#'+this.options.backDivId).hide();
			$(window).unbind('resize',this.jq.data('resize')).unbind('scroll',this.jq.data('scroll'));
			this.jq.find('[close]').unbind('click',this.jq.data('_hide'));//取消事件的绑定
			this.jq.removeData('_hide').removeData('scroll').removeData('_hide');//移除data
			this.options.onHide.apply(this);
			return this;
		}
	};
	$.fn.extend({pop:function(config){
		return new pop(config,this).show();
	}});
})(jQuery);

请看下面的demo:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>弹出层</title>
<meta name="Keywords" content="" />
<meta name="description" content="" />
<script src='jquery.tools.min.js'></script>
<script src='pop.js'></script>
<script>
function test(){
	$('#tcc').pop({
		onShow:function(){
			alert('展示')
		},
		onHide:function(){
			alert(this.jq.attr('style'));//通过this.jq可以访问到弹出层的jquery对象
			alert('隐藏');
		}
	});
}
</script>
</head>
<body>
<button onclick="test();">点我</button>
<div id="tcc" style="background-color:red;width:500px;height:300px;display:none">
	<div style="background-color:white;height:20px;" drop=1>我可以拖动</div>
	<a href="###" style="float:right;" close="1">关闭</a><button close="1">关闭</button>
	<div style="background-color:white;height:20px;top:200px;" drop=1>我也可以拖动</div>
</div>
</body>
</html>

说明:
1 在弹出层中的子DOM对象,其属性为drop=1的都可以拖动
2 在弹出层中的子DOM对象,其属性为close=1的都可以关闭

3 onShow和onHide是展示和关闭的回调,可以不设置,回调中的this为pop对象,this.jq可以访问弹出层的jquery对象

分类: javascript 标签:

强大的表单验证工具jquer tools-Validator

2010年10月20日 effect 1 条评论

jQuery的tools插件是很贴近实际需求的UI扩展,有tab,tip等,今天介绍表单验证的插件:Validator。

表单验证在WEB项目中太常见了,很简单,但是很烦琐。toos家族中Validator就是来拯救大家的。 下面来简单介绍一下:

一 基本用法
如果要验证某个表单,你仅仅需要一行代码:

$("#myform").validator();

当表单提交的时候,就会来验证。验证规则写在表单元素的属性中,比如某个输入框是必填项目,那么就这样:

<input required="required" name="name" type="text" />

中间的required就是表示这个表单项目是必填!
更加详细的demo请看:http://flowplayer.org/tools/demos/validator/index.html

二 几个配置说明
1 singleError 是否依次验证,还是一次验证所有。如果你想一次验证一个,就设为ture,否则为false

2 effect 错误信息展示的效果,默认为default。你可以建立自己的effect:

$.tools.validator.addEffect("wall", function(errors, event) {
	$.each(errors, function(index, error) {
		// erroneous input
		var input = error.input;//出错的input表单项目
		// error messages for the input (Array)
		var errors = error.messages;//出错的信息,一般取errors[0]
                          alert(errors[0]);
		input.focus();
                          input.css({borderColor: 'red'});
 
	});
}, function(inputs)  {
	// 当验证成功之后的回调
       inputs.css({borderColor: 'blue'});
});

三 自定义出错信息
有时候出错信息不想用系统预先定义的信息,那么在input选项里面加上属性data-message:

<input date-message="出错啦" type="text" />

四 自定义验证选项
当自定义的一些验证规则,有如下两种方法:
1 给自定义的type增加
如想给type为time增加验证规则,那么就:

$.tools.validator.fn("[type=time]", "时间格式不对", function(input, value) {
	return /^\d\d:\d\d$/.test(value);
});

那么在页面中这样既可:

<input  type="time" />

二 验证属性
这个方法是最方便也是最广泛的,如果想验证最小长度:

$.tools.validator.fn("[minlength]", function(input, value) {
	var min = input.attr("minlength");
 
	return value.length &gt;= min ? true : {
		en: "Please provide at least " +min+ " character" + (min &gt; 1 ? "s" : ""),
		fi: "Kentän minimipituus on " +min+ " merkkiä"
	};
});

那么如果有minlength属性的表单都会验证,如:

<input minlength="6" type="text" />

 

后记:这个表单验证的扩展是我见过最为方便使用和自定义和扩展的。本文只是抛砖引玉,给出在使用表单验证的tools的关键点,更加详细的资料请看:

http://flowplayer.org/tools/validator/index.html

分类: javascript 标签:

IE6中的缓存问题

2010年10月15日 effect 3 条评论

今天碰到一个诡异的问题:IE8,FF访问都是正常的情况下,IE6出现了如下情况:
1 清除缓存的情况下,首次访问,正常
2 刷新页面,JS报错:缺少”,或者报错缺少}

大家都知道,IE6的报错很怪异,找不准文件,行数和字符数不能定位,但是在附近能找到。IE6下也没有JS的调试工具(也许有,但是我没用过)。

好了,说一下我的应用场景:在个人中心的某个业务要展示空间的信息,要展示个人空间的信息。

我是这样处理这个逻辑的:载入个人空间信息的JS文件,然后渲染出来。说通俗一点就是在这个页面加载一段JS,这段JS保存了用户空间的信息,然后展示之。

原来不能确定这个JS错误是这一段JS引起,后来观察,发现到展示个人空间的信息的时候卡住了。但是这个JS文件也是正常的,我下载到本地,然后载入他,也没报错。

好,现在好好分析下问题,抓住几个关键点:

1 清除缓存后,首次访问,正常,第二次访问异常。

2 使用抓包工具,这个URL第二次请求是提示用的cache。

所以可能是浏览器cache导致的问题。

现在解决方法:加载这个JS的时候加个时间锉,确保每次都是拉取最新的文件,而不是从缓存中读取。

为什么会这样呢?

也许是和文件的编码有关,因为我页面的编码是UTF-8,而空间信息JS的编码是GBK,我读取这个JS的时候制定了编码是GBK,但是当使用cache的时候,或许这个charset不起作用。

总结:当页面编码和JS文件编码不一致的时候,要注意IE6下的缓存,导致了JS文件的乱码!

分类: javascript 标签:

多项式的保存–JS版本

2010年10月12日 effect 没有评论

PHP版本的在这里:http://web302.com/2010/09/save-more-options/

下面是JS版本:

function selectToDec(select,all){
	var bin='';
	var selectString=select.join(',');
	for( var i=0;i<all.length;i++){
		if(selectString.indexOf(all[i])!=-1){
			bin+='1';
		}
		else bin+='0';
	}
	return parseInt(bin,2);
}
function DecToSelect(dec,all){
	var bin=dec.toString(2);
	if(bin.length<all.length){
		var j=all.length-bin.length;
		for(var i=0;i<j;i++){
			bin='0'+bin;
		}
	}
	var select=[];
	for(var i=0;i<bin.length;i++){
		if(bin[i]==1) select.push(all[i]);
	}
	return select;
}

DEMO:

var all=['足球','篮球','乒乓球','羽毛球'];
var select = ['羽毛球','篮球'];
var i =(selectToDec(select,all));
alert(i);
alert(DecToSelect(i,all));
分类: javascript 标签: