分类 "CK猪是程序员" 的存档.

CentOS开启SELinux导致samba无法访问的解决办法

安装CentOS默认是开启SELinux的,所以会导致samba、ftp等应用程序无法访问相应目录,解决办法如下
开启Samba用户HOME目录权限

/usr/sbin/setsebool  -P samba_enable_home_dirs=1

开启单个共享目录(path)权限

chcon -t samba_share_t path

开启所有共享目录
只读权限

/usr/sbin/setsebool -P samba_export_all_ro on

读写权限

/usr/sbin/setsebool -P samba_export_all_rw on

查看某个目录(path)是否开启了权限

ls -ldZ path

参考文献:
http://ronald.blog.51cto.com/140996/51053
http://itgroup.blueshop.com.tw/yjhwang/linuxlab?n=convew&i=3422

javascript中new function()的返回值(并不一定是function的“实例”)

今天看mootools的Element源码时发现,Elenment的initialize有返回值,有点不解,initialize有返回值的话那么var div = new Element(‘div’)的话div究竟是initialize的返回值还是一个Element实例。或许有的人会说,当然是Element实例啦。但是,虽然表面上看上去,div似乎是一个Element实例,然而事实上div不是一个Element实例,它是document.createElemetnt(‘div’),然后通过复制Element的prototype到div而来的。下面是Element的部分源码

var Element = new Class({
    initialize: function(el){
        if ($type(el) == 'string') el = document.createElement(el);
        return $(el);
    }

});

function $(el){
    if (!el) return false;
    if (el._element_extended_ || [window, document].test(el)) return el;
    if ($type(el) == 'string') el = document.getElementById(el);
    if ($type(el) != 'element') return false;
    if (['object', 'embed'].test(el.tagName.toLowerCase()) || el.extend) return el;
    el._element_extended_ = true;
    Garbage.collect(el);
    el.extend = Object.extend;
    if (!(el.htmlElement)) el.extend(Element.prototype);
    return el;
};

上面的代码似乎说明了,只要new function()的function有返回值的话那么就应该返回function返回值,但是事实上呢?看下边的例子

function fn()
{
    this.k = 1;
    return 1;
}
fn.prototype = {
    j: 0
};
var f = new fn();  //  f = {}

结果出乎意料,竟然是fn的实例({k:1, j:0});为什么又是function的实例了?继续看下面的实验,在fn中分别return各种数据类型的值,得出一下结果

return 1;                   f = {"j":0,"k":1}
return false;               f = {"j":0,"k":1}
return true;                f = {"j":0,"k":1}
return "string";            f = {"j":0,"k":1}
return null;                f = {"j":0,"k":1}
return undefined;           f = {"j":0,"k":1}


注:Boolean在IE和FIREFOX似乎只要声明而没有定义,不管传入的是true还是false,返回的都是{},而且没有ToString()等方法。而且它的prototype也是{} 。其他浏览器没试过,还不清楚。不过估计也是一样的吧。

[修正]Boolean是有定义的,ToString()应该是toString();

实验的结论很明显,如果function的返回值是对象的话则返回该对象,否则返回function的实例

javascript真是一门神奇的语言,容易入门,但是其中的细节和一些技巧却不是一时半会能掌握,每次回过头学都能学到一些新的东西,好像怎么都学不完,继续加油。

return new Number(1); f = 值为1的Number对象
return new String(“string”); f = 值为”string”的String对象
return new Boolean(true); f = {}
return [1]; f = [1]
return new Object(); f = {}

字符集编码

一、什么是字符集?什么是编码?

字符(Charcter)是文字与符号的总称,包括文字、图形符号、数学符号等。

一组抽象字符的集合就是字符集(Charset)。字符集常常和一种具体的语言文字对应起来,该文字中的所有字符或者大部分常用字符就构成了该文字的字符集,比如英文字符集。一组有共同特征的字符也可以组成字符集,比如繁体汉字字符集、日文汉字字符集。字符集的子集也是字符集。

计算机要处理各种字符,就需要将字符和二进制内码对应起来,这种对应关系就是字符编码(Encoding)。制定编码首先要确定字符集,并将字符集内的字符排序,然后和二进制数字对应起来。根据字符集内字符的多少,会确定用几个字节来编码。每种编码都限定了一个明确的字符集合,叫做被编码过的字符集(Coded Character Set),这是字符集的另外一个含义。通常所说的字符集大多是这个含义。

因为制定编码的同时往往也制定了字符集,所以经常把字符集和编码混为一谈,具体区分细节不用细究。

 二、通用字元集(Universal Character Set,UCS)
通用字元集(Universal Character Set,UCS)是由ISO制定的ISO10646(或称ISO/IEC 10646)标准所定义的字元编码方式,采用4字节编码。又称Universal Multiple-Octet Coded Character Set,大陆译为通用多八位编码字符集,臺湾译为广用多八位元编码字元集。

 表示一个UCS或Unicode值的十六进位数通常在前面加上「U+」,例如「U+0041」代表字元「A」。
通用字元集是所有包括了其他字元集。它保证了与其他字元集的双向相容,即,如果你将任何文本字元串翻译到UCS格式,然後再翻译回原编码,你不会丢失任何信息。

 三、unicode

Unicode统一码万国码单一码)是一种在计算机上使用的字符编码。它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。1990年开始研发,1994年正式公布。随着计算机工作能力的增强,Unicode也在面世以来的十多年里得到普及。

2006年6月的最新版本的 Unicode 是 2005年3月31日推出的Unicode 4.1.0 。另外,5.0 Beta已于2005年12月12日推出,以供各会员评价。

Unicode 的编码和实现

大概来说,Unicode 编码系统可分为编码方式和实现方式两个层次。

 1.编码方式

Unicode 的编码方式与 ISO 10646 的通用字元集(亦称[通用字符集])(Universal Character Set,UCS)概念相对应,目前的用于实用的 Unicode 版本对应于 UCS-2,使用16位的编码空间。也就是每个字符占用2个字节

 2.实现方式

Unicode 的实现方式不同于编码方式。一个字符的 Unicode 编码是确定的。但是在实际传输过程中,由于不同系统平台的设计不一定一致,以及出于节省空间的目的,对 Unicode 编码的实现方式有所不同。Unicode 的实现方式称为Unicode转换格式(Unicode/UCS Transformation Format,简称为 UTF)。

Unicode 的实现方式还包括 UTF-7、Punycode、CESU-8、SCSU、UTF-32等,这些实现方式有些仅在一定的国家和地区使用,有些则属于未来的规划方式。目前通用的实现方式是 UTF-16小尾序(BOM)、UTF-16大尾序(BOM)和 UTF-8。

 UCS 和 Unicode 只是分配整数给字符的编码表,UTF-8、UTF-16、CESU-8等则指定了如何存储!

 

 

参考文献:

http://bk.baidu.com/view/40801.htm   unicode参考

http://bk.baidu.com/view/354447.htm  UCS参考

http://bk.baidu.com/view/25412.html  UTF-8参考

 

 

 

 

 

 

 

 

 

 

PHP中=赋值操作符对不同数据类型的不同行为

作为一个PHP的新手,一直对PHP的引用困惑了很久,今晚仔细看了用户手册和做了一些实验,终于明白了其中的原理和细节,特别是=操作符对于不同类型的不同行为。
首先解释赋值操作符=的行为,看下面的例子:

$i = 0;
$j = $i;
$j = 0;
echo $j;   // 打印输出0

$arr = array(0);
$arr2 = $arr;
$arr2[0] = 1;
echo $arr[0]; //打印输出0

class B
{
    public $i = 0;
}

$b = new B();
$c = $b;
$c->i = 1;
echo($b->i);  // 打印输出1

从这个例子可以看出,如果=操作符右边的变量为基本数据类型或者数组,那么=操作符把右边变量的一份拷贝赋值给左边变量;如果右边变量不是基本数据类型或者数组,如class,那么=会把一个指向右边变量的引用赋值给左边变量。注意:是指向右边变量的引用,而不是指向右边变量所指的内容区域的引用;具体看下边的例子

$a = new A();
$b_a = $a;
$b_r = &$a;

$b_a = null;
var_dump($a);  //打印 object(A)[2],$a所指向的内容还在
$b_r = null;
var_dump($a); // 打印 null,$a所指向的内容被清除了

上面的例子也说明了,如果用 $var = &$a 的方式赋值的话,用$var=null来销毁变量$var的话事实上是把$var所指内容被设置null了,其实这句话也暗示了任何一个指向该内容区域的引用变量均可用来销毁该内容区域的内容。所以,要销毁变量$var的话用 unset($var) 。PS:事实上一这种方式赋值$var只是个引用,占用不了多少内存,要不要销毁没所谓,这里这是说下必须用unset的方式销毁。

下面则是《用户手册》中的“引用的解释”的例子:

$a =& $b;

下边有这么一句解释:
这意味着 $a 和 $b 指向了同一个变量。
注: $a 和 $b 在这里是完全相同的,这并不是 $a 指向了 $b 或者相反,而是 $a 和 $b 指向了同一个地方。
引用是什么?

在 PHP 中引用意味着用不同的名字访问同一个变量内容。这并不像 C 的指针,替代的是,引用是符号表别名。注意在 PHP 中,变量名和变量内容是不一样的,因此同样的内容可以有不同的名字。最接近的比喻是 Unix 的文件名和文件本身――变量名是目录条目,而变量内容则是文件本身。引用可以被看作是 Unix 文件系统中的紧密连接。

关于“引用是什么”的一点解释:

int i = 0;
int j = 0;
int *p = &i;
p = &j;

上面的代码中,p是一个指向i的内存地址的指针,而*p才是其中的内容;p=&j指向改变了p指针的指向,用*p=111的表达式才会改变i的内容。而PHP中则不是,下面的例子

$i = 0;
$p = &$i;

$p = 111则马上会改变$i的值。

PHP输出缓存控制

有时我们需要页面内容完成生成后一次性输出,或者echo之后马上输出页面内存而不缓存,那么我们就会用到PHP的页面输出缓存控制的相关函数。

PHP页面输出缓存控制函数如下:

flush — 刷新输出缓冲
ob_clean — Clean (erase) the output buffer
ob_end_clean — Clean (erase) the output buffer and turn off output buffering
ob_end_flush — Flush (send) the output buffer and turn off output buffering
ob_flush — Flush (send) the output buffer
ob_get_clean — Get current buffer contents and delete current output buffer
ob_get_contents — Return the contents of the output buffer
ob_get_flush — Flush the output buffer, return it as a string and turn off output buffering
ob_get_length — Return the length of the output buffer
ob_get_level — Return the nesting level of the output buffering mechanism
ob_get_status — Get status of output buffers
ob_gzhandler — ob_start callback function to gzip output buffer
ob_implicit_flush — Turn implicit flush on/off
ob_list_handlers — List all output handlers in use
ob_start — Turn on output buffering
output_add_rewrite_var — Add URL rewriter values
output_reset_rewrite_vars — Reset URL rewriter values

更加详细的用法见PHP用户手册,下面举一个简单的示例:

$str = 'Hello world';
echo $str;
sleep(10);

这段代码会在sleep了10秒后在页面打印 Hello world。在看下面这段代码:

$str = 'Hello world';
echo $str . str_repeat(' ', 256);
ob_flush();
flush();
sleep(10);

这段代码则会马上在屏幕上打印 Hello world。关键就在于第2和第3行调用的两个函数 ob_flush() 和 flush()。这两个函数得一起使用才能保证页面马上输出Hello world。其中str_repeat(‘ ‘, 256)则是为了解决某些浏览器必须在接收到256个字符后才会显示内容。下面的内容摘自《PHP用户手册》,很好地解释了上面的代码意图。
引用自《PHP用户手册》的内容

flush() 函数不会对服务器或客户端浏览器的缓存模式产生影响。因此,必须同时使用 ob_flush() 和flush() 函数来刷新输出缓冲。
个别web服务器程序,特别是Win32下的web服务器程序,在发送结果到浏览器之前,仍然会缓存脚本的输出,直到程序结束为止。
有些Apache的模块,比如mod_gzip,可能自己进行输出缓存,这将导致flush()函数产生的结果不会立即被发送到客户端浏览器。
甚至浏览器也会在显示之前,缓存接收到的内容。例如 Netscape 浏览器会在接受到换行或 html 标记的开头之前缓存内容,并且在接受到 标记之前,不会显示出整个表格。
一些版本的 Microsoft Internet Explorer 只有当接受到的256个字节以后才开始显示该页面,所以必须发送一些额外的空格来让这些浏览器显示页面内容。

上面的代码演示了即时输出缓存,一般情况下该部分代码都能正常完成所要的功能,但是也会有例外

1)服务器打开了gzip等压缩功能,导致输出的缓存被压缩后不足256字节,那么在某些版本IE中也会等到凑够了256字节才输出内容(PS:之所以说某些版本的IE是因为我现在用的IE6就没有该问题,WINDOWS XP SP2)

2)如果这段代码之前还有代码,而且前面的代码中多次调用了ob_start()而ob_end_flush()调用的次数比ob_start()少2次,那么这上面的代码也不能正常工作。因为ob_start()的buffer是stackable的。调用多次ob_start()后,ob_flush()只会把buffer输出到上一层的buffer中。例如

调用ob_start(),它的缓存区为 buffer1,再次调用ob_start(),它的缓存区为buffer2。这时调用ob_flush()只会把 buffer2中的内容输出到 buffer1。这时如果调用 ob_end_flush(), 那么buffer2中的内容会被输出到 buffer1并且销毁buffer2。此时再调用ob_flush()就会把buffer1中的内容输出到服务器,然后调用flush()则可以把服务器中的buffer输出到客户端浏览器。

知道了ob_start()和ob_end_flush()的用法后,就可以用下面的代码来实现所有页面内容完全生成后一次性输出所有的缓存。

ob_start();

//do something to generate $content
echo $content;

ob_end_flush();
flush(); //if script is ending, this can be removed.

之所以要这么做是因为服务器会在缓存区满了以后就输出缓存而不是等到所以页面内容生成后再输出