邵珠庆の日记 生命只有一次,你可以用它来做很多伟大的事情–Make the world a little better and easier


46月/10

推荐5个漂亮的jquery主流图表插件

发布在 邵珠庆

5个jQuery图表(生成)插件评测

大多数的图表插件都是免费用于个人,而商业则收费。不过在中国我们用外国的东西,外国人知道个鸟,但不推荐大家使劲用就行!

1. jQuery Visualize Plugin

jQuery Visualize Plugin 是一个非常有用的图表插件,几乎可以将表格数据支持转换成所有图表样式!

支持图表样式: 柱状, 面积, 饼状 & 线型.

环境: jQuery, excanvas (included)

浏览器兼容: IE6*, IE7*, IE8*, Firefox 2, Firefox 3.5, Safari 3 and 4, Opera 9.

* 目前最烂浏览器还不支持HTML5,不过还能支持在ie中运行。

演示网址: http://www.filamentgroup.com/demo/charting_v2/index_2.php

使用条款: MIT and GPL 使用条款,商业付费

2. Highcharts

Highcharts不仅支持点型,柱状,面积形状等等各种图表样式,还有非常强大的交互能力。它是一个实时的图表工具,你可以实时修改、添加、删除数据。在点型图表方面,Highcharts是强项。

例子2:支持行标

支持图表样式: 柱状, 面积, 面积sp线型 , 饼状, 线型, Sp线型, 行标.

环境: jQuery or MooTools

浏览器兼容: IE6, IE7, IE8, Firefox 2, Firefox 3.5, Safari 3 and 4, Opera 9 and iPhone!

演示网址: http://www.highcharts.com/demo/

使用条款: 个人免费,商业 $80.

3. Flot

Flot 大家可能比较熟悉,生成的图表样式也比较好看。它还支持鼠标提示,缩放等功能。

 

支持图表样式: 柱状, 面积, 点型 & 线型.

环境: jQuery

浏览器兼容: IE6, IE7, IE8, Firefox 2, Firefox 3.5, Safari 3 and 4, Opera 9 and Konqueror 4+.

演示网址: http://people.iola.dk/olau/flot/demo/

使用条款: MIT 使用条款,免费

4. jQuery Sparklines

Sparklines是用来生成比较小的图片,但是可能是支持类型最多的插件了,点线面柱无所不能。

支持图表样式: 柱状, 面 ,点& 线型等等

环境: jQuery

浏览器兼容: IE6, IE7, IE8, Firefox 2, Firefox 3.5, Safari 3 and 4, Opera 9 and Google Chrome.

演示网址: http://omnipotent.net/jquery.sparkline/

使用条款: New BSD 使用条款,免费

5. jqPlot

jqPlot看起来非常的朴素,但是它可是在最好的免费图表生成jQuery生成插件之一。

支持图表样式: 柱状, 饼状 & 线型.

环境: jQuery

浏览器兼容: IE6, IE7, IE8, Firefox 2, Firefox 3.5, Safari 3 and 4, Opera 9 and Google Chrome.

演示网址: http://www.jqplot.com/tests/

使用条款: MIT and GPL version 2 使用条款,免费

26月/10

apache的日志access_log分析

发布在 邵珠庆

当网站出问题时分析日志,第一步一般都不会是看访问日志。但是也不能忽视它,在访问日志中记录了很多的客户信息,如果你有心,可以从这个日志中获得很多有 用的信息!

访问日志access_log记录了所有对Web服务器的访问活动。
正如其名字所示,访问日志access_log记录了所有对Web服务器的访问活动。

下面是访问日志中一个典型的记录:

10.1.1.95 - e800 [18/Mar/2005:12:21:42 +0800] "GET /stats/awstats.pl?config=e800 HTTP/1.1" 200 899 "http://10.1.1.1/pv/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon)"

这行内容由9项构成,上面的例子中有两项空白,但整行内容仍旧分成了9项。

第一项信息是远程主机的地址。如果你想知道这个IP地址的域名,可通过nslookup或者host命令来查看。如果你想让Apache自己找出这个IP 的主机名,可以打开这个开关:HostnameLookups。(建议最好不要打开,会影响Apache记录服务器日志的速度)

第二项是空白,用一个"-"占位符替代。实际上绝大多数时候这一项都是如此。这个位置用于记录浏览者的标识,这不只是浏览者的登录名字,而是浏览者的 email地址或者其他唯一标识符。这个信息由identd返回,或者直接由浏览器返回。很早的时候,那时Netscape 0.9还占据着统治地位,这个位置往往记录着浏览者的email地址。然而,由于有人用它来收集邮件地址和发送垃圾邮件,所以它未能保留多久,很久之前市 场上几乎所有的浏览器就取消了这项功能。因此,到了今天,我们在日志记录的第二项看到email地址的机会已经微乎其微了。

第三项也是e800。这个位置用于记录浏览者进行身份验证时提供的名字。当然,如果网站的某些内容要求用户进行身份验证,那么这项信息是不会空白的。但 是,对于大多数网站来说,日志文件的大多数记录中这一项仍旧是空白的。

日志记录的第四项是请求的时间。这个信息用方括号包围,而且采用所谓的"公共日志格式"或"标准英文格式"。因此,上例日志记录表示请求的时间是2005 年3月18日12:21:42。时间信息最后的"+0800"表示服务器所处时区位于UTC之后的8小时。

日志记录的第五项信息或许是整个日志记录中最有用的信息,它告诉我们服务器收到的是一个什么样的请求。该项信息的典型格式是"METHOD RESOURCE PROTOCOL",即"方法 资源 协议"。

RESOURCE是指浏览者向服务器请求的文档,或URL。在这个例子中,浏览者请求的是"/stats/awstats.pl?config=e800 "。

在上例中,METHOD是GET,其他经常可能出现的METHOD还有POST和HEAD。此外还有不少可能出现的合法METHOD,但主要就是这三种。

PROTOCOL通常是HTTP,后面再加上版本号。

日志记录的第六项信息是状态代码。它告诉我们请求是否成功,或者遇到了什么样的错误。大多数时候,这项值是200,它表示服务器已经成功地响应浏览器的 请求,一切正常。一般地说,以2开头的状态代码表示成功,以3开头的状态代码表示由于各种不同的原因用户请求被重定向到了其他位置,以4开头的状态代码表 示客户端存在某种错误,以5开头的状态代码表示服务器遇到了某个错误。

日志记录的第七项表示发送给客户端的总字节数。它告诉我们传输是否被打断(即,该数值是否和文件的大小相同)。把日志记录中的这些值加起来就可以得知服务 器在一天、一周或者一月内发送了多少数据。

日志记录的第八项记录的是客户在提出请求时所在的目录或URL。这次的是"http://10.1.1.1/pv/"即10.1.1.1的pv目录下的首 页。大多数情况下,首页会是在httpd.conf中DocumentRoot 指令后面规定的那些类型和名字的web文件。

日志记录的第九项表示客户端的详细信息,这样你就不难理解为什么有些网站能够在页面中显示你的IP、OS、Browser了。

245月/10

介绍使用php发送邮件类(html格式及附件)

发布在 邵珠庆

以下为邮件类代码:
<?PHP
class Email {
//---设置全局变量
var $mailTo = ""; // 收件人
var $mailCC = ""; // 抄送
var $mailBCC = ""; // 秘密抄送
var $mailFrom = ""; // 发件人
var $mailSubject = ""; // 主题
var $mailText = ""; // 文本格式的信件主体
var $mailHTML = ""; // html格式的信件主体
var $mailAttachments = ""; // 附件
/* 函数setTo($inAddress) :用于处理邮件的地址 参数 $inAddress
为包涵一个或多个字串,email地址变量,使 用逗号来分割多个邮件地址
默认返回值为true
**********************************************************/
function setTo($inAddress){
//--用explode()函数根据”,”对邮件地址进行分割
$addressArray = explode( ",",$inAddress);
//--通过循环对邮件地址的合法性进行检查
for($i=0;$icheckEmail($addressArray[$i])==false) return false; }
//--所有合法的email地址存入数组中
$this->mailTo = implode($addressArray, ",");
return true; }
/**************************************************
函数 setCC($inAddress) 设置抄送人邮件地址
参数 $inAddress 为包涵一个或多个邮件地址的字串,email地址变量,
使用逗号来分割多个邮件地址 默认返回值为true
**************************************************************/
function setCC($inAddress){
//--用explode()函数根据”,”对邮件地址进行分割
$addressArray = explode( ",",$inAddress);
//--通过循环对邮件地址的合法性进行检查
for($i=0;$icheckEmail($addressArray[$i])==false) return false; }
//--所有合法的email地址存入数组中
$this->mailCC = implode($addressArray, ",");
return true; }
/***************************************************
函数setBCC($inAddress) 设置秘密抄送地址 参数 $inAddress 为包涵一个或多
个邮件地址的字 串,email地址变量,使用逗号来分割多个邮件地址 默认返回值为
true
******************************************/
function setBCC($inAddress){
//--用explode()函数根据”,”对邮件地址进行分割
$addressArray = explode( ",",$inAddress);
//--通过循环对邮件地址的合法性进行检查
for($i=0;$i<COUNT($ADDRESSARRAY);$I++)
{ if($this->checkEmail($addressArray[$i])==false)
return false;
}
//--所有合法的email地址存入数组中
$this->mailBCC = implode($addressArray, ",");
return true;
}
/*****************************************************************
函数setFrom($inAddress):设置发件人地址 参数 $inAddress 为包涵邮件
地址的字串默认返回值为 true
***************************************/
function setFrom($inAddress){
if($this->checkEmail($inAddress)){
$this->mailFrom = $inAddress;
return true;
} return false; }
/**********************
函数 setSubject($inSubject) 用于设置邮件主题参数$inSubject为字串,
默认返回的是true
*******************************************/
function setSubject($inSubject){
if(strlen(trim($inSubject)) > 0){
$this->mailSubject = ereg_replace( "n", "",$inSubject);
return true; }
return false; }
/****************************************************
函数setText($inText) 设置文本格式的邮件主体参数 $inText 为文本内容默
认返回值为true
****************************************/
function setText($inText){
if(strlen(trim($inText)) > 0){
$this->mailText = $inText;
return true; }
return false;
}
/**********************************
函数setHTML($inHTML) 设置html格式的邮件主体参数$inHTML为html格式,
默认返回值为true
************************************/
function setHTML($inHTML){
if(strlen(trim($inHTML)) > 0){
$this->mailHTML = $inHTML;
return true; }
return false; }
/**********************
函数 setAttachments($inAttachments) 设置邮件的附件 参数$inAttachments
为一个包 涵目录的字串,也可以包涵多个文件用逗号进行分割 默认返回值为true
*******************************************/
function setAttachments($inAttachments){
if(strlen(trim($inAttachments)) > 0){
$this->mailAttachments = $inAttachments;
return true; }
return false; }
/*********************************
函 数 checkEmail($inAddress) :这个函数我们前面已经调用过了,主要就是
用于检查email地址的合法性
*****************************************/
function checkEmail($inAddress){
return (ereg( "^[^@ ]+@([a-zA-Z0-9-]+.)+([a-zA-Z0-9-]{2}|net|com|gov|mil|org|edu|int)$",$inAddress));
}
/*************************************************
函数 loadTemplate($inFileLocation,$inHash,$inFormat) 读取临时文件并且
替换无用的信息参 数$inFileLocation用于定位文件的目录
$inHash 由于存储临时的值 $inFormat 由于放置邮件主体
***********************************************************/
function loadTemplate($inFileLocation,$inHash,$inFormat){
/* 比如邮件内有如下内容: Dear ~!UserName~,
Your address is ~!UserAddress~ */
//-- 其中”~!”为起始标志”~”为结束标志
$templateDelim = "~";
$templateNameStart = "!";
//--找出这些地方并把他们替换掉
$templateLineOut = ""; //--打开临时文件
if($templateFile = fopen($inFileLocation, "r")){
while(!feof($templateFile)){
$templateLine = fgets($templateFile,1000);
$templateLineArray = explode($templateDelim,$templateLine);
for( $i=0; $i<COUNT($TEMPLATELINEARRAY);$I++){
//--寻找起始位置
if(strcspn($templateLineArray[$i],$templateNameStart)==0){
//--替换相应的值
$hashName = substr($templateLineArray[$i],1);
//-- 替换相应的值
$templateLineArray[$i] = ereg_replace($hashName,(string)$inHash[$hashName],$hashName);
}
}
//--输出字符数组并叠加
$templateLineOut .= implode($templateLineArray, "");
} //--关闭文件fclose($templateFile);
//--设置主体格式(文本或html)
if( strtoupper($inFormat)== "TEXT" )
return($this->setText($templateLineOut));
else if( strtoupper($inFormat)== "HTML" )
return($this->setHTML($templateLineOut));
} return false;
}
/*****************************************
函数 getRandomBoundary($offset) 返回一个随机的边界值
参数 $offset 为整数 – 用于多管道的调用 返回一个md5()编码的字串
****************************************/
function getRandomBoundary($offset = 0){
//--随机数生成
srand(time()+$offset);
//--返回 md5 编码的32位 字符长度的字串
return ( "----".(md5(rand()))); }
/********************************************
函数: getContentType($inFileName)用于判断附件的类型
**********************************************/
function getContentType($inFileName){
//--去除路径
$inFileName = basename($inFileName);
//--去除没有扩展名的文件
if(strrchr($inFileName, ".") == false){
return "application/octet-stream";
}
//--提区扩 展名并进行判断
$extension = strrchr($inFileName, ".");
switch($extension){
case ".gif": return "image/gif";
case ".gz": return "application/x-gzip";
case ".htm": return "text/html";
case ".html": return "text/html";
case ".jpg": return "image/jpeg";
case ".tar": return "application/x-tar";
case ".txt": return "text/plain";
case ".zip": return "application/zip";
default: return "application/octet-stream";
}
return "application/octet-stream";
}
/**********************************************
函数formatTextHeader把文本内容加上text的文件头
*****************************************************/
function formatTextHeader(){ $outTextHeader = "";
$outTextHeader .= "Content-Type: text/plain;
charset=us-asciin";
$outTextHeader .= "Content-Transfer-Encoding: 7bitnn";
$outTextHeader .= $this->mailText. "n";
return $outTextHeader;
} /************************************************
函数 formatHTMLHeader()把邮件主体内容加上html的文件头
******************************************/
function formatHTMLHeader(){
$outHTMLHeader = "";
$outHTMLHeader .= "Content-Type: text/html;
charset=us-asciin";
$outHTMLHeader .= "Content-Transfer-Encoding: 7bitnn";
$outHTMLHeader .= $this->mailHTML. "n";
return $outHTMLHeader;
}
/**********************************
函数 formatAttachmentHeader($inFileLocation) 把邮件中的附件标识出来
********************************/
function formatAttachmentHeader($inFileLocation){
$outAttachmentHeader = "";
//--用上面的函数getContentType($inFileLocation)得出附件类型
$contentType = $this->getContentType($inFileLocation);
//--如果附件是文本型则用标准的7位编码
if(ereg( "text",$contentType)){
$outAttachmentHeader .= "Content-Type: ".$contentType. ";n";
$outAttachmentHeader .= ' name="'.basename($inFileLocation). '"'. "n";
$outAttachmentHeader .= "Content-Transfer-Encoding: 7bitn";
$outAttachmentHeader .= "Content-Disposition: attachment;n";
$outAttachmentHeader .= ' filename="'.basename($inFileLocation). '"'. "nn";
$textFile = fopen($inFileLocation, "r");
while(!feof($textFile)){
$outAttachmentHeader .= fgets($textFile,1000);
}
//--关闭文件 fclose($textFile);
$outAttachmentHeader .= "n";
}
//--非文本格式则用64位进行编码
else{ $outAttachmentHeader .= "Content-Type: ".$contentType. ";n";
$outAttachmentHeader .= ' name="'.basename($inFileLocation). '"'. "n";
$outAttachmentHeader .= "Content-Transfer-Encoding: base64n";
$outAttachmentHeader .= "Content-Disposition: attachment;n";
$outAttachmentHeader .= ' filename="'.basename($inFileLocation). '"'. "nn";
//--调用外部命令uuencode 进行编码
exec( "uuencode -m $inFileLocation nothing_out",$returnArray);
for ($i = 1; $i<(count($returnArray)); $i++){
$outAttachmentHeader .= $returnArray[$i]. "n";
}
} return $outAttachmentHeader;
}
/******************************
函数 send()用于发送邮件,发送成功返回值为true
************************************/
function send(){
//--设置邮件头为空
$mailHeader = "";
//--添加抄送 人
if($this->mailCC != "")
$mailHeader .= "CC: ".$this->mailCC. "n";
//--添加秘密抄送人
if($this->mailBCC != "")
$mailHeader .= "BCC: ".$this->mailBCC. "n";
//--添加发件人
if($this->mailFrom != "")
$mailHeader .= "FROM: ".$this->mailFrom. "n";
//--------------------------- 邮件格式------------------------------
//--文本格式
if($this->mailText != "" && $this->mailHTML == "" && $this->mailAttachments == ""){
return mail($this->mailTo,$this->mailSubject,$this->mailText,$mailHeader);
}
//--html或text格式
else if($this->mailText != "" && $this->mailHTML != "" && $this->mailAttachments == ""){
$bodyBoundary = $this->getRandomBoundary();
$textHeader = $this->formatTextHeader();
$htmlHeader = $this->formatHTMLHeader();
//--设置 MIME-版本
$mailHeader .= "MIME-Version: 1.0n";
$mailHeader .= "Content-Type: multipart/alternative;n";
$mailHeader .= ' boundary="'.$bodyBoundary. '"';
$mailHeader .= "nnn";
//--添加邮件主体 和边界
$mailHeader .= "--".$bodyBoundary. "n";
$mailHeader .= $textHeader;
$mailHeader .= "--".$bodyBoundary. "n";
//--添加html标 签
$mailHeader .= $htmlHeader;
$mailHeader .= "n--".$bodyBoundary. "--";
//--发送邮件
return mail($this->mailTo,$this->mailSubject, "",$mailHeader);
}
//-- 文本加html加附件
else if($this->mailText != "" && $this->mailHTML != "" && $this->mailAttachments != ""){
$attachmentBoundary = $this->getRandomBoundary();
$mailHeader .= "Content-Type: multipart/mixed;n";
$mailHeader .= ' boundary="'.$attachmentBoundary. '"'. "nn";
$mailHeader .= "This is a multi-part message in MIME format.n";
$mailHeader .= "--".$attachmentBoundary. "n";
$bodyBoundary = $this->getRandomBoundary(1);
$textHeader = $this->formatTextHeader();
$htmlHeader = $this->formatHTMLHeader();
$mailHeader .= "MIME-Version: 1.0n";
$mailHeader .= "Content-Type: multipart/alternative;n";
$mailHeader .= ' boundary="'.$bodyBoundary. '"';
$mailHeader .= "nnn";
$mailHeader .= "--".$bodyBoundary. "n";
$mailHeader .= $textHeader;
$mailHeader .= "--".$bodyBoundary. "n";
$mailHeader .= $htmlHeader;
$mailHeader .= "n--".$bodyBoundary. "--";
//--获取附件值
$attachmentArray = explode( ",",$this->mailAttachments);
//--根据附件的个数进行循环
for($i=0;$i<COUNT($ATTACHMENTARRAY);$I++){
//--分割 $mailHeader .= "n--".$attachmentBoundary. "n";
//--附件信息
$mailHeader .= $this->formatAttachmentHeader($attachmentArray[$i]);
}
$mailHeader .= "--".$attachmentBoundary. "--";
return mail($this->mailTo,$this->mailSubject, "",$mailHeader);
}
return false;
}
}
?>

使用方法:
<?
Include “email.class”

$mail->setTo("a@a.com "); //收件人
$mail-> setCC("b@b.com ,[url=mailto:c@c.com]c@c.com[/url]"); //抄送
$mail-> setCC("d@b.com , [url=mailto:e@c.com]e@c.com[/url]"); //秘密抄送
$mail->setFrom(“[url=mailto:f@f.com]f@f.com[/url]”); //发件人
$mail->setSubject(“主题”) ; //主题
$mail->setText(“文本格 式”) ;//发送文本格式也可以是变量
$mail->setHTML(“html格式”) ;//发送html格式也可以是变量
$mail->setAttachments(“c:a.jpg”) ;//添加附件,需表明路径
$mail->send(); //发送邮件
?>

215月/10

javascript:window.external.addFavorite()代码的意思 添加收藏夹

发布在 邵珠庆

JavaScript:window.external.addFavorite

<a href="JavaScript:window.external.AddFavorite('http://127.0.0.1','Page')"> <font color="white">添加到收藏夹 </FONT> </a>

是用来添加到收藏夹的

关闭网页时弹出设为主页对话框代码:
<BODY id=iehomepage
onunload="iehomepage.style.behavior=’url(#default#homepage)’;if(!(iehomepage.isHomePage(’http://oolove.cn/g’)))iehomepage.setHomePage(’http://oolove.cn/g’); ">

打开网页弹出设为主页对话框代码:
<BODY id=iehomepage
onload="iehomepage.style.behavior=’url(#default#homepage)’;if(!(iehomepage.isHomePage(’http://oolove.cn/g’)))iehomepage.setHomePage(’http://oolove.cn/g’); ">

单击链接 设为主页
<a href=# onClick ="this.style.behavior=’url(#default#homepage)’;this.setHomePage(’http://oolove.cn/g’); "> 设为主页</a>

鼠标滑过设定为主页
<a href=# onMouse Over="this.style.behavior=’url(#default#homepage)’;this.setHomePage(’http://oolove.cn/g’); "> 设为主页</a>

附添加到收藏夹代码:

离开网页时弹出
<script language="javascript">
function bookmarkit(){window.external.addFavorite(’http://oolove.cn/g’,’四叶草购物’)}</script>
<body onunload="bookmarkit()">

网页载入时弹出
<script language="javascript">
function bookmarkit(){window.external.addFavorite(’http://oolove.cn/g’,’四叶草购物’)}/
</script>
<body onload="bookmarkit()">

右键弹出
<script language=javascript1.2>
document.all.onMouse Down=new Function("if (event.button==2||event.button==3)window.external.addFavorite(’http://oolove.cn/g’,’四叶草购物’) ")/
</script>

单击文字弹出
<script language="javascript">
function bookmarkit(){window.external.addFavorite(’http://oolove.cn/g’,’四叶草购物’)}/
if (document.all)document.write(’<a href="#" onClick ="bookmarkit()"& gt;加入收藏夹</a>’)
</script>

鼠标滑过文字弹出
<script language="javascript">
function bookmarkit(){window.external.addFavorite(’http://oolove.cn/g’,’四叶草购物’)}/
if (document.all)document.write(’<a href="#" onMouse Over="bookmarkit()"& gt;加入收藏夹</a>’)

65月/10

网站后台万能密码’or’=’or’ 原理

发布在 邵珠庆

很多菜鸟都不知道'or'='or' 为什么可以直接进网站的后台,下面就来解释下给大家吧! 原理是这样的:(以下全部以asp为例子) 很多网站把密码放到数据库中,在登陆验证中一般都用以下sql查询语句去查找数据库, sql=select * from user where username='username'
  很多菜鸟都不知道'or'='or' 为什么可以直接进网站的后台,下面就来解释下给大家吧!
原理是这样的:(以下全部以asp为例子)
很多网站把密码放到数据库中,在登陆验证中一般都用以下sql查询语句去查找数据库,
sql="select * from user where username='"&username&"'and pass='"& pass&'" ,
如果用户提交的用户名密码和数据库里面的一样就让你登录,反之则不行。
这里多嘴两句,or 是一个逻辑运算符,作用是在判断两个条件的时候,只要其中一个条件成立,那么
等式将会成立.而在语言中,是以1来代表真的(成立).那么在这行语句中,原语句的"and"验证将不再
继续,而因为"1=1"和"or"令语句返回为真值.。(其实也好理解,英文or是或者的意思,也就是说
这个或者那个中有一个是对的,那么整句话就对的,那我还管你后面的and甘什么呢?)好了,
我们根据sql这个特性构造一个特殊的用户名和密码来绕过它的验证,就用我构造的那个'or' '=' ,
用户名和密码都是'or' '=',我们来看看放到整个程序中会是什么样子。
sql="select * from user where username=''or' '=''and pass=''or' '='' (注意,or前面和=后面都不是
双引号,而是两个单引号,查询语句里面没有双引号,双引号只是让里面的变量变成字符而已,
我们查询的时候双引号中的变量就被我们提交的数据所代替),好了,现在整句话的意思是:从数
据库的user表中查找的用户名是空(两个单引号之间没东西当然是空了:))或者空等于空。废
话,因为空当然等于空了,所以程序就认为你提交的数据是合法的,于是就放你通过拉and后面
的密码验证都不要了。
有人问我,是不是只有这个'or' '=' 才可以绕过验证呢? NO,you are wrong !
根据这个原理我就可以随便构造我喜欢的语句,比如 aweige' or 'aweige'<>'骆驼
这样放进去就变成了用户名是aweige或者aweige不等于骆驼,废话,aweige当然不不等于骆驼拉
难道还等于骆驼啊??于是就给我放行了。大家也可以根据自己的喜欢去构造这样的语句,我就
不多说了。我想说的是修补方法。

修补方法有两(当然还有别的,这只是我自己常用的):
1,对输入的内容验证
可以加一些脚本来验证客户端输入的内容进行验证
2,特殊字符特别是单引号的过滤。
我们也看到了,上面的构造语句中,都有但引号的存在,也有一些其它的字符,因此,只要我们
把这些东西都过滤掉,系统就会安全一点了。
可以用replace语句对但引号和其他特殊字符进行过滤,比如
replace(username,"'","''") '把单引号转换为两个单引号
replace(username,"<>"," ") '把不等号转换为空
这样的话用户提交的构造语句就没用了。
========
后记
========

1,以上的漏洞只是登录的问题,如果再精心构造,还能得到整个系统的全部数据,我曾用过自
己构造的union语句拿到金梅电影的所有钻石会员和黄金会员,搞得我电影都看不完,大家去仔细
研究学习一下asp和sql数据库查询语言的话可能还会得到比我还多的东西哦
2,现在的系统除了一些比较烂的之外,基本上都已经修补好了这个漏洞,所以,远离知道了,
大家就去学习新的东西,通过别的方法来得到我们想要的东西。

284月/10

最短CN域名在干啥?

发布在 邵珠庆

总共二十六个英语字母,由这二十六个字母组成的最短 CN域名都只想哪些网站,我在浏览器里一次输入,得到如下结果。

a.cn 没有任何网页,经查询该域名已被列入限制注册名单

b.cn 中,北京澳美新投资顾问有限公司所有

c.cn 中,北京澳美新投资顾问有限公司

d.cn 当乐网,手机游戏下载网站

e.cn 没有任何网页,经查询该域名已被列入限制注册名单

f.cn 没有任何网页,2003年被深圳市世强电脑科技有限公司注册

g.cn 大家都知道,谷歌花了不少银子买的,指向谷歌中国

h.cn 指向shanghai.114.cc(上海房地产网),没有作主域名,估计在待价而沽

i.cn 没有任何网页,经查询该域名已被列入限制注册名单

j.cn 指向简单生活网,一在线生活服务网站,还有点名气

k.cn 没有任何网页,2003年被北京保联网科技有限公司注册

l.cn 乐活网,也是一在线生活服务网站,不过我好像今天才听说。

m.cn 出现错误,打不开,经查询2003年被济南鑫达印刷包装有限公司注册

n.cn 没有任何网页,经查询2003年被北京计算机与网络研究中心注册

o.cn 网站叫都市圈,一分类信息网站

p.cn 不明白是个什么类型的网站

q.cn 网站叫摘吧,号称“中国文摘基地”

r.cn 指向dg.114.cc(东莞人才网),看来跟h.cn有着一样的命运

s.cn 2003年被北京智慧东方信息技术有限公司注册

t.cn 没有任何网页,2003年被Hangzhou 365 Internet Co.,Ltd注册

u.cn 网站叫看天下,是个图书阅读网站

v.cn 2003年被沈阳五星设计有限公司注册

w.cn 指向msn.ename.cn,看来是被易名中国给注册去了

x.cn 竟然指向的是陕西联通,注册者却不是,我晕!

y.cn 哇!竟然是2005年注册的,之前就没有人注册?

z.cn 指向rc.114.cc,与h.cn和r.cn命运一样。这家公司就厉害了,拥有三个这样 的域名

在查询的过程中,我发现这些域名大多是在2003年3月10日被人注册的 ,哪一天是什么日子?

从上面可以看出,只有8个 被真正投入使用中,其他要嘛没有,要嘛正中,还有的则没有被用作主域名。

y.cn让我好意外,2005年才被注册。2003年到2005年这段时间,玉米们在干啥?不会认为这样的域名 根本不可能 被自己注册到而懒得去查吧?

224月/10

各大浏览器 CSS3 和 HTML5 兼容速查表

发布在 邵珠庆

支持 CSS3HTML5 的浏览器越来越多,甚至包括最新版的 IE,当然,所谓支持仅仅是部分支持,因为 CSS3 和 Html5 的W3C 规范都尚未形成。如果你现在就希望使用 CSS3 和 HTML5 创建你的站点,至少要对各个浏览器对这两种新技术的支持情况有一个全面了解。

需要指出的是,即使同一个浏览器的同一个版本,在 Mac 和 Windows 两个平台,它们对 CSS3 和 HTML5 的支持也并不一致。本文是一份 Chrome, Safari, Firefox, Opera, IE 5 大浏览器,在 Mac 和 Windows 两个平台,对 CSS3 和 HTML5 各种功能的详细支持情况清单。

CSS3 属性

可以看出,全盘支持 CSS3 属性的浏览器有 Chrome 和 Safari,而且不管是 Mac 平台还是 Windows 平台全支持。

CSS3 选择器

除了 IE 家族和 Firefox 3,其它几乎全部支持。Chrome,Safari,Firefox 3.6,Opera 10.5 成绩最好 。

HTML5 Web 应用

Safari 对 HTML5 Web 应用的支持最好,除了地理定位功能,其它都支持。

HTML5 网页内嵌对象

这应该是 HTML5 最令人期待的东西,内置的画布,视频,音频等对象。全部支持的有 Chrome,Safari,Firefox 3.6,Opera 10.5。IE家族则全军覆没。

HTML5 音频编码

Opera 10.5 支持的最全面,IE 家族又是颗粒无收。

HTML5 视频编码

H.264 任重道远。

HTML5 各种表单对象

Mac 平台下的 Chrome 成绩最佳。这些表单对象让人想起了桌面程序。

HTML5 表单对象属性与行为

又一次想到了桌面程序。

结论

目前,对 CSS3 和 HTML5 支持最好的是 Safari,Chrome 次之,Firefox 3.6 和 Opera 10.5 旗鼓相当,IE家族最差。鉴于这种情况,假如你想使用这两项新技术创建一个先锋体验式站点,现在的 CSS3 和 HTML5 可以让你实现,假如你希望这个站点能被绝大多数人正常访问,现在还为时过早,折中的方案是,为不支持 CSS3 和 HTML5 某些功能的浏览器提供降级方案,当然,其中要涉及到很多问题,包括浏览器,版本,平台的探测,CSS Hack 等等大量工作,相信是得不偿失的。

184月/10

ThinkPHP单字母函数(快捷方法)使用总结

发布在 邵珠庆

1.U() URL组装 支持不同URL模式
U($url='',$vars='',$suffix=true,$domain=false)
  @param string $url URL表达式,格式:'[模块/控制器/操作#锚点@域名]?参数1=值1&参数2=值2...'
  @param string|array $vars 传入的参数,支持数组和字符串
  @param string $suffix 伪静态后缀,默认为true表示获取配置值
  @param boolean $domain 是否显示域名
  @return string

2.D() D函数用于实例化模型类 格式 [资源://][模块/]模型
D($name='',$layer='')
  @param string $name 资源地址
  @param string $layer 模型层名称
  @return Model

3.M() M函数用于实例化一个没有模型文件的Model
M($name='',$tablePrefix='',$connection='')
  @param string $name Model名称 支持指定基础模型 例如MongoModel:User
  @param string $tablePrefix 表前缀
  @param mixed $connection 数据库连接信息
  @return Model

4.I() 获取输入参数 支持过滤和默认值
I($name,$default='',$filter=null)
  使用方法:

I('id',0); //获取id参数 自动判断get或者post
I('post.name','','htmlspecialchars'); //获取$_POST['name']
I('get.'); //获取$_GET

5.B() 执行某个行为
B($name,$tag='',&$params=NULL)
  @param string $name 行为名称
  @param string $tag 标签名称(行为类无需传入)
  @param Mixed $params 传入的参数
  @return void

6.C() 读取及设置配置参数
C($name=null,$value=null,$default=null)
  @param string|array $name 配置变量
  @param mixed $value 配置值
  @param mixed $default 默认值
  @return mixed

7.E() 抛出异常处理
E($msg, $code=0)
  @param string $msg 异常消息
  @param integer $code 异常代码 默认为0
  @return void

8.G() 记录和统计时间(微秒)和内存使用情况
G($start,$end='',$dec=4)
  使用方法:
G('begin'); // 记录开始标记位
// ... 区间运行代码
G('end'); // 记录结束标签位
echo G('begin','end',6); //统计区间运行时间 精确到小数后6位
echo G('begin','end','m'); // 统计区间内存使用情况
  如果end标记位没有定义,则会自动以当前作为标记位
  其中统计内存使用需要 MEMORY_LIMIT_ON 常量为true才有效
  @param string $start 开始标签
  @param string $end 结束标签
  @param integer|string $dec 小数位或者m
  @return mixed

9.L()获取和设置语言定义(不区分大小写)
L($name=null,$value=null)
  @param string|array $name 语言变量
  @param mixed $value 语言值或者变量
  @return mixed

10.T()获取模版文件 格式 资源://模块@主题/控制器/操作
T($template='',$layer='')
  @param string $name 模版资源地址
  @param string $layer 视图层(目录)名称
  @return string

11.N() 设置和获取统计数据
N($key,$step=0,$save=false)
  使用方法:
N('db',1); // 记录数据库操作次数
N('read',1); // 记录读取次数
echo N('db'); // 获取当前页面数据库的所有操作次数
echo N('read'); // 获取当前页面读取次数
  @param string $key 标识位置
  @param integer $step 步进值
  @return mixed

12.A()A函数用于实例化控制器

格式:[资源://][模块/]控制器
A($name,$layer='',$level='')
  @param string $name 资源地址
  @param string $layer 控制层名称
  @param integer $level 控制器层次
  @return Controller|false

13.R() 远程调用控制器的操作方法
URL 参数格式 [资源://][模块/]控制器/操作
R($url,$vars=array(),$layer='')
  @param string $url 调用地址
  @param string|array $vars 调用参数 支持字符串和数组
  @param string $layer 要调用的控制层名称
  @return mixed

14.W()渲染输出Widget
W($name,$data=array())
  @param string $name Widget名称
  @param array $data 传入的参数
  @return void

15.S()缓存管理
S($name,$value='',$options=null)
  @param mixed $name 缓存名称,如果为数组表示进行缓存设置
  @param mixed $value 缓存值
  @param mixed $options 缓存参数
  @return mixed

16.F() 快速文件数据读取和保存 针对简单类型数据 字符串、数组
F($name, $value='',$path=DATA_PATH)
  @param string $name 缓存名称
  @param mixed $value 缓存值
  @param string $path 缓存路径
  @return mixed
124月/10

awk 用法

发布在 邵珠庆

调用AWK
有三种方式调用awk,第一种是命令行方式,如:
awk [-F field-separator]'commands' input-files(s)
这里,commands是真正的awk命令。本章将经常使用这种方法。
上面例子中,[-F域分隔符]是可选的,因为awk使用空格作为缺省的域分隔符,因此如果要浏览域间有空格的文本,不必指定这个选项,但如果要浏览诸如passwd文件,此文件各域以冒号作为分隔符,则必须指明- F选项,如:
awk -F:'commands'input-file
第二种方法是将所有awk命令插入一个文件,并使awk程序可执行,然后用awk命令解释器作为脚本的首行,以便通过键入脚本名称来调用它。
第三种方式是将所有的awk命令插入一个单独文件,然后调用:
awk -f awk-script-file input-file(s)
-f选项指明在文件awk_script_file中的awk脚本,input_file(s)是使用awk进行浏览的文件名。
awk脚本
在命令中调用awk时,awk脚本由各种操作和模式组成。
如果设置了-F选项,则awk每次读一条记录或一行,并使用指定的分隔符分隔指定域,但如果未设置-F选项,awk假定空格为域分隔符,并保持这个设置直到发现一新行。当新行出现时,awk命令获悉已读完整条记录,然后在下一个记录启动读命令,这个读进程将持续到文件尾或文件不再存在。
参照表1-1,awk每次在文件中读一行,找到域分隔符(这里是符号#),设置其为域n,直至一新行(这里是缺省记录分隔符),然后,划分这一行作为一条记录,接着awk再次启动下一行读进程。
表1-1 awk读文件记录的方式

域1 分隔符 域2 分隔符 域3 分隔符 域4及换行
P.Bunny(记录1) # 02/99 # 48 # Yellow/n
J.Troll(记录2) # 07/99 # 4842 # Brown-3/n

模式和动作
任何awk语句都由模式和动作组成。在一个awk脚本中可能有许多语句。模式部分决定动作语句何时触发及触发事件。处理即对数据进行的操作。如果省略模式部分,动作将时刻保持执行状态。
模式可以是任何条件语句或复合语句或正则表达式。模式包括两个特殊字段BEGIN和END。使用BEGIN语句设置计数和打印头。BEGIN语句使用在任何文本浏览动作之前,之后文本浏览动作依据输入文件开始执行。END语句用来在awk完成文本浏览动作后打印输出文本总数和结尾状态标志。如果不特别指明模式,awk总是匹配或打印行数。
实际动作在大括号{}内指明。动作大多数用来打印,但是还有些更长的代码诸如if和循环(looping)语句及循环退出结构。如果不指明采取动作,awk将打印出所有浏览出来的记录。
下面将深入讲解这些模式和动作。
域和记录
awk执行时,其浏览域标记为$1,$2...$n。这种方法称为域标识。使用这些域标识将更容易对域进行进一步处理。
使用$1,$3表示参照第1和第3域,注意这里用逗号做域分隔。如果希望打印一个有5个域的记录的所有域,不必指明$1,$2,$3,$4,$5,可使用$0,意即所有域.Awk浏览时,到达一新行,即假定到达包含域的记录末尾,然后执行新记录下一行的读动作,并重新设置域分隔。
注意执行时不要混淆符号$和shell提示符$,它们是不同的。
为打印一个域或所有域,使用print命令。这是一个awk动作(动作语法用圆括号括起来)。
1. 抽取域
真正执行前看几个例子,现有一文本文件grade.txt,记录了一个称为柔道数据库的行信息。
$pg grade.txt

此文本文件有7个域,即(1)名字、(2)升段日期、(3)学生序号、(4)腰带级别、(5)年龄、(6)目前比赛积分、(7)比赛最高分。
2. 保存awk输出
有两种方式保存shell提示符下awk脚本的输出。最简单的方式是使用输出重定向符号>文件名,下面的例子重定向输出到文件wow。
$awk '{print $0}' grade.txt>wow
使用这种方法要注意,显示屏上不会显示输出结果。因为它直接输出到文件。只有在保证输出结果正确时才会使用这种方法。它也会重写硬盘上同名数据。
第二种方法是使用tee命令,在输出到文件的同时输出到屏幕。在测试输出结果正确与否时多使用这种方法。例如输出重定向到文件delete_me_and_die,同时输出到屏幕。使用这种方法,在awk命令结尾写入|tee delete_me_and_die。
$awk '{print $0}' grade.txt|tee delete_me_and_die
3. 使用标准输入
在深入讲解这一章之前,先对awk脚本的输入方法简要介绍一下。实际上任何脚本都是从标准输入中接受输入的。为运行本章脚本,使用awk脚本输入文件格式,例如:
$belts.awk grade_student.txt
也可替代使用下述格式:
使用重定向方法:
$belts.awk < grade2.txt
或管道方法:
$grade2.txt|belts.awk
4. 打印所有记录
$awk '{print $0}' grade.txt
awk读每一条记录。因为没有模式部分,只有动作部分{print $0}(打印所有记录),这个动作必须用花括号括起来。上述命令打印整个文件。
5. 打印单独记录
假定只打印学生名字和腰带级别,查看域所在列,可知为field-1和field-4,因此可以使用$1和$4,但不要忘了加逗号以分隔域。
$awk '{print $1,$4}' grade.txt
6. 打印报告头
上述命令输出在名字和腰带级别之间用一些空格使之更容易划分,也可以在域间使用tab键加以划分。为加入tab键,使用tab键速记引用符/t,后面将对速记引用加以详细讨论。也可以为输出文本加入信息头。本例中加入name和belt及下划线。下划线使用/n,强迫启动新行,并在/n下一行启动打印文本操作。打印信息头放置在BEGIN模式部分,因为打印信息头被界定为一个动作,必须用大括号括起来。在awk查看第一条记录前,信息头被打印。
$awk 'BEGIN {print "Name    Belt/n---------------------"}
{print $1"/t"$4}'grade.txt
Name        Belt
----------------------
M.Transley  Green
(省略)
7. 打印信息尾
如果在末行加入end of report信息,可使用END语句。END语句在所有文本处理动作执行完之后才被执行。END语句在脚本中的位置放置在主要动作之后。下面简单打印头信息并告之查询动作完成。
$awk 'BEGIN {print "Name/n--------"}{print $1}END{"end of report"}'grade.txt
Name
--------------
M.Transley
(……)
8. awk错误信息提示
在碰到awk错误时,可相应查找:
• 确保整个awk命令用单引号括起来。
• 确保命令内所有引号成对出现。
• 确保用花括号括起动作语句,用圆括号括起条件语句。
• 可能忘记使用花括号,也许你认为没有必要,但awk不这样认为,将按之解释语法。
元字符
这里是awk中正则表达式匹配操作中经常用到的字符。
/ ^ $ . [] | () * + ?
+,?这里没讲到,因为它们只适用于awk而不适用于grep或sed
+ 使用+匹配一个或多个字符。
? 匹配模式出现频率。例如使用/XY?Z/匹配XYZ或YZ。
条件操作符

操作符 描述
< 小于
<=(>=) 小于等于(大于等于)
== 等于
!= 不等于
~ 匹配正则表达式
!~ 不匹配正则表达式

1. 匹配
为使一域号匹配正则表达式,使用符号‘~’后紧跟正则表达式,也可以用if语句。awk中if后面的条件用()括起来。
观察文件grade.txt,如果只要打印brown腰带级别可知其所在域为field-4,这样可以写出表达式{if($4~/brown/)print}意即如果field-4包含brown,打印它。如果条件满足,则打印匹配记录行。可以编写下面脚本,因为这是一个动作,必须用花括号{}括起来。
$awk '{if($4~/brown/)print $0}' grade.txt
J.Troll   07/99   4842   Brown-3   12  26   26
(……)
匹配记录找到时,如果不特别声明,awk缺省打印整条记录。使用if语句开始有点难,但不要着急,因为有许多方法可以跳过它,并仍保持同样结果。下面例子意即如果记录包含模式brown,就打印它:
$awk '$0 ~ /Brown/' grade.txt
J.Troll   07/99   4842   Brown-3   12  26   26
(……)
2. 小于等于
$awk '{if($6<$7)print $1}'grade.txt
3.行首
$awk '/^48/'input-file
复合操作符:
&& AND : 语句两边必须同时匹配为真。
|| OR:语句两边同时或其中一边匹配为真。
! 非求逆
awk内置变量

内置变量 含义
ARGC 命令行参数个数
ARGV 命令行参数排列
ENVIRON 支持队列中系统环境变量的使用
FILENAME awk浏览的文件名
FNR 浏览文件的记录数
FS 设置输入域分隔符,等价于命令行-F选项
NF 浏览记录的域个数
NR 已读的记录数
OFS 输出域分隔符
ORS 输出记录分隔符
RS 控制记录分隔符

ARGC支持命令行中传入awk脚本的参数个数。ARGV是ARGC的参数排列数组,其中每一元素表示为ARGV[n],n为期望访问的命令行参数。
ENVIRON支持系统设置的环境变量,要访问单独变量,使用实际变量名,例如ENVIRON["EDITOR"] ="Vi"。
FILENAME支持awk脚本实际操作的输入文件。因为awk可以同时处理许多文件,因此如果访问了这个变量,将告之系统目前正在浏览的实际文件。
FNR支持awk目前操作的记录数。其变量值小于等于NR。如果脚本正在访问许多文件,每一新输入文件都将重新设置此变量。
FS用来在awk中设置域分隔符,与命令行中-F选项功能相同。缺省情况下为空格。如果用逗号来作域分隔符,设置FS=","。
NF支持记录域个数,在记录被读之后再设置。
OFS允许指定输出域分隔符,缺省为空格。如果想设置为#,写入OFS="#"。
ORS为输出记录分隔符,缺省为新行(/n)。
RS是记录分隔符,缺省为新行(/n)。
NF、NR和FILENAME
下面看一看awk内置变量的例子。
要快速查看记录个数,应使用NR。比如说导出一个数据库文件后,如果想快速浏览记录个数,以便对比于其初始状态,查出导出过程中出现的错误。使用N R将打印输入文件的记录个数。print NR放在END语法中。
$awk 'END {print NR}'grade.txt
以下例子中,所有学生记录被打印,并带有其记录号。使用NF变量显示每一条读记录中有多少个域,并在END部分打印输入文件名。
$awk '{print NF,NR,$0}END{print FILENAME}' grade.txt
7  1  M.Transley   05/99   48311   Green  8   40   44
7  2  J.Lulu       06/99   48317   green  9   24   26
(……)
grade.txt
在从文件中抽取信息时,最好首先检查文件中是否有记录。下面的例子只有在文件中至少有一个记录时才查询Brown级别记录。使用AND复合语句实现这一功能。意即至少存在一个记录后,查询字符串Brown,最后打印结果。
$awk '{if(NR>0 && $4~/Brown/)print $0}'grade.txt
NF的一个强大功能是将变量$PWD的返回值传入awk并显示其目录。这里需要指定域分隔符/。
$pwd
/usr/local/etc
$echo $pwd|awk -F/ '{print $NF}'
etc
awk操作符
1. 设置输入域到域变量名
在awk中,设置有意义的域名是一种好习惯,在进行模式匹配或关系操作时更容易理解。一般的变量名设置方式为name=$n,这里name为调用的域变量名,n为实际域号。例如设置学生域名为name,级别域名为belt,操作为name=$1;belts=$4。注意分号的使用,它分隔awk命令。下面例子中,重新赋值学生名域为name,级别域为belts。查询级别为Yellow的记录,并最终打印名称和级别。
$awk '{name=$1;belt=$4;if(belt ~Yellow/)print name"is belt"belts}'grade.txt
P.Bunny is belt Yellow.
2. 域值比较操作
有两种方式测试一数值域是否小于另一数值域。
1) 在BEGIN中给变量名赋值。
2) 在关系操作中使用实际数值。
通常在BEGIN部分赋值是很有益的,可以在awk表达式进行改动时减少很多麻烦。
使用关系操作必须用圆括号括起来。
下面的例子查询所有比赛中得分在27点以下的学生。
用引号将数字引用起来是可选的,“27”、27产生同样的结果。
$awk '{if{$6<27)print $0}'grade.txt
3. 修改数值域取值
当在awk中修改任何域时,重要的一点是要记住实际输入文件是不可修改的,修改的只是保存在缓存里的awk复本。awk会在变量NR或NF变量中反映出修改痕迹。
为修改数值域,简单的给域标识重赋新值,如: $1=$1+5,会将域1数值加5,但要确保赋值域其子集为数值型。
修改M.Tansley的目前级别分域,使其数值从40减为39,使用赋值语句$6=$6-1,当然在实施修改前首先要匹配域名。
$awk '{if($1=="M.Tansley") $6=$6-1;print $1,$6,$7}' grade.txt
4. 修改文本域
修改文本域即对其重新赋值。需要做的就是赋给一个新的字符串。在J.Troll中加入字母,使其成为J.L.Troll,表达式为$1="J.L.Troll",记住字符串要使用双引号(" "),并用圆括号括起整个语法。
$awk '{if($1==J.Troll")($1=J.L.Troll);print $1}' grade.txt
5. 只显示修改记录
上述例子均是对一个小文件的域进行修改,因此打印出所有记录查看修改部分不成问题,但如果文件很大,记录甚至超过100,打印所有记录只为查看修改部分显然不合情理。在模式后面使用花括号将只打印修改部分。取得模式,再根据模式结果实施操作,可能有些抽象,现举一例,只打印修改部分。注意花括号的位置。
$awk '{if($1==J.Troll"){$1=J.L.Troll ;print $1}}' grade.txt
6. 创建新的输出域
在awk中处理数据时,基于各域进行计算时创建新域是一种好习惯。创建新域要通过其他域赋予新域标识符。如创建一个基于其他域的加法新域{$4=$2+$3},这里假定记录包含3个域,则域4为新建域,保存域2和域3相加结果。
在文件grade.txt中创建新域8保存域目前级别分与域最高级别分的减法值。表达式为‘{$8=$7-$6}’,语法首先测试域目前级别分小于域最高级别分。新域因此只打印其值大于零的学生名称及其新域值。在BEGIN部分加入tab键以对齐报告头。
$awk 'BEGIN{print "Name/t Difference"}{if($6<$7){$8=$7-$6;print $1,$8}}' grade.txt
7. 增加列值
为增加列数或进行运行结果统计,使用符号+=。增加的结果赋给符号左边变量值,增加到变量的域在符号右边。例如将$1加入变量total,表达式为total+=$1。列值增加很有用。许多文件都要求统计总数,但输出其统计结果十分繁琐。在awk中这很简单,请看下面的例子。
将所有学生的‘目前级别分’加在一起,方法是tot+=$6,tot即为awk浏览的整个文件的域6结果总和。所有记录读完后,在END部分加入一些提示信息及域6总和。不必在awk中显示说明打印所有记录,每一个操作匹配时,这是缺省动作。
$ awk '(tot+=$6);END {print "Club student total points:" tot}' grade.txt
M.Transley   05/99   48311   Green  8   40   44
(……)
Club student total points:155
如果文件很大,你只想打印结果部分而不是所有记录,在语句的外面加上圆括号()即可。
$ awk '{(tot+=$6);END {print "Club student total points:" tot}}' grade.txt
Club student total points:155

内置的字符串函数
-----------------------------------------------------------
gsub(r,s)         在整个$0中用s替代r
gsub(r,s,t)       在整个t中用s替代r
index(s,t)        返回s中字符串t的第一位置
length(s)         返回s长度
match(s,r)        测试s是否包含匹配r的字符串
split(s,a,fs)     在fs上将s分成序列a
sprint(fmt,exp)   返回经fmt格式化后的exp
sub(r,s)          用$0中最左边最长的子串代替s
substr(s,p)       返回字符串s中从p开始的后缀部分
substr(s,p,n)     返回字符串s中从p开始长度为n的后缀部分
-----------------------------------------------------------
gsub函数有点类似于sed查找和替换。它允许替换一个字符串或字符为另一个字符串或字符,并以正则表达式的形式执行。第一个函数作用于记录$0,第二个gsub函数允许指定目标,然而,如果未指定目标,缺省为$0。
index(s,t)函数返回目标字符串s中查询字符串t的首位置。length函数返回字符串s字符长度。match函数测试字符串s是否包含一个正则表达式r定义的匹配。split使用域分隔符fs将字符串s划分为指定序列a。sprint函数类似于printf函数(以后涉及),返回基本输出格式fmt的结果字符串exp.sub(r,s)函数将用s替代$0中最左边最长的子串,该子串被(r)匹配。
sub(s,p)返回字符串s在位置p后的后缀。substr(s,p,n)同上,并指定子串长度为n。
1. gsub
要在整个记录中替换一个字符串为另一个,使用正则表达式格式, /目标模式/,替换模式/。例如改变学生序号4842到4899:
$ awk 'gsub(/4842/,4899){print $0}' grade.txt
J.Troll   07/99  4899  Brown-3  12   26   26
2. index
查询字符串s中t出现的第一位置。必须用双引号将字符串括起来。例如返回目标字符串Bunny中ny出现的第一位置,即字符个数。
$ awk 'BEGIN {print index("Bunny","ny")}' grade.txt
4
3. length
返回所需字符串长度,例如检验字符串J.Troll返回名字及其长度,即人名构成的字符个数。
$ awk '$1=="J.Troll" {print length($1) " " $1}' grade.txt
7 J.Troll
4. match
match测试目标字符串是否包含查找字符的一部分。可以对查找部分使用正则表达式,返回值为成功出现的字符排列数。如果未找到,返回0,第一个例子在ANCD中查找d。因其不存在,所以返回0。第二个例子在ANCD中查找D。因其存在,所以返回ANCD中D出现的首位置字符数。第三个例子在学生J.Lulu中查找u。
$ awk 'BEGIN {print match("ANCD",/d/)}'
0
$ awk 'BEGIN {print match("ANCD",/C/)}'
3
$ awk '$1=="J.Lulu" {print match($1,"u")}' grade.txt
4
5. split
使用split返回字符串数组元素个数。例如;
$ awk 'BEGIN{print split("123#456#789",myarray,#)}'
3
split返回数组myarray的下标数。数组myarray取值如下:
Myarray[1]=123
Myarray[2]=456
Myarray[3]=789
6. sub
使用sub发现并替换模式的第一次出现位置。学生J.Troll的记录有两个值一样,“目前级别分”与“最高级别分”。只改变第一个为29,第二个仍为24不动,操作命令为sub(/26/,"29",$0),只替换第一个出现24的位置。注意J.Troll记录需存在。
7. substr
substr是一个很有用的函数。它按照起始位置及长度返回字符串的一部分。如果给定长度值远大于字符串长度,awk将从起始位置返回所有字符,要抽取L.Tansley
的姓,只需从第3个字符开始返回长度为7。可以输入长度99,awk返回结果相同。
$ awk '$1=="L.Tansley" {print substr($1,3,99)}' grade.txt
Tansley
substr的另一种形式是返回字符串后缀或指定位置后面字符。这里需要给出指定字符串及其返回字串的起始位置。例如,从文本文件中抽取姓氏,需操作域1,并从第三个字符开始:
$ awk '{print substr($1,3)}' grade.txt
还有一个例子,在BEGIN部分定义字符串,在END部分返回从第t个字符开始抽取的子串。
$ awk 'BEGIN {STR="A FEW GOOD MEN"} END {print substr(STR,7)}'grade.txt
GOOD MEN
8. 从shell中向awk传入字符串
awk脚本大多只有一行,其中很少是字符串表示的。大多要求在一行内完成awk脚本,这一点通过将变量传入awk命令行会变得很容易。现就其基本原理讲述一些例子。例如:

字符串屏蔽序列
使用字符串或正则表达式时,有时需要在输出中加入一新行或查询一元字符。
打印一新行时,(新行为字符/n),给出其屏蔽序列,以不失其特殊含义,用法为在字符串前加入反斜线。例如使用/n强迫打印一新行。
如果使用正则表达式,查询花括号({}),在字符前加反斜线,如//{/,将在awk中失掉其特殊含义。

awk中使用的屏蔽序列
/b 退格键         /t tab键
/f 走纸换页       /ddd 八进制值
/n 新行           /c 任意其他特殊字符,例如//为反斜线符号
/r 回车键

awk输出函数printf
每一种printf函数(格式控制字符)都以一个%符号开始,以一个决定转换的字符结束。转换包含三种修饰符。printf函数基本语法是printf([格式控制符],参数),格式控制字符通常在引号里。

awk printf修饰符
-        左对齐
Width    域的步长,用0表示0步长
.prec    最大字符串长度,或小数点右边的位数

 

awk printf格式
%c     ASCII字符
%d     整数
%e     浮点数,科学记数法
%f     浮点数,例如(123.44)
%gawk  决定使用哪种浮点数转换e或者f
%o     八进制数
%s     字符串
%x     十六进制数

1. 字符转换
管道输出65到awk。printf进行ASCII码字符转换。这里也加入换行,因为缺省情况下printf不做换行动作。
$echo "65" | awk '{printf "%c/n",$0}'
A
当然也可以按同样方式使用awk得到同样结果。
$ awk 'BEGIN {printf "%c/n",65}'
A
所有的字符转换都是一样的,下面的例子表示进行浮点数转换后‘999’的输出结果。整数传入后被加了六个小数点。
$ awk 'BEGIN{printf "%f/n",999}
999.000000
2. 格式化输出
打印所有的学生名字和序列号,要求名字左对齐,15个字符长度,后跟序列号。注意/n换行符放在最后一个指示符后面。输出将自动分成两列。
$ awk '{printf "%-15s %s/n",$1,$3} grade.txt
3. 向一行awk命令传值
在查看awk脚本前,先来查看怎样在awk命令行中传递变量。
在awk执行前将值传入awk变量,需要将变量放在命令行中,格式如下:
awk 命令变量=输入文件值
下面的例子在命令行中设置变量AGE等于10,然后传入awk中,查询年龄在10岁以下的所有学生。
$ awk'{if($5<AGE) print $0}' AGE=10 grade.txt
要快速查看文件系统空间容量,观察其是否达到一定水平,可使用下面awk一行脚本。因为要监视的已使用空间容量不断在变化,可以在命令行指定一个触发值。首先用管道命令将df -k 传入awk,然后抽出第4列,即剩余可利用空间容量。使用$4 ~/^[0-9]/取得容量数值(1024块)而不是df的文件头,然后对命令行与‘ if($4<TRIGGER)’上变量TRIGGER中指定的值进行查询测试。

 

4. awk脚本文件
可以将awk脚本写入一个文件再执行它。命令不必很长(尽管这是写入一个脚本文件的主要原因),甚至可以接受一行命令。这样可以保存awk命令,以使不必每次使用时都需要重新输入。使用文件的另一个好处是可以增加注释,以便于理解脚本的真正用途和功能。
使用前面的几个例子,将之转换成awk可执行文件。像原来做的一样,将学生目前级别分相加awk '(tot+=$6)END{print "club student total points:"tot}'grade.txt。创建新文件student_tot.awk,给所有awk程序加入awk扩展名是一种好习惯,这样通过查看文件名就知道这是一个awk程序。如下:

第一行是!/bin/awk -f。这很重要,没有它自包含脚本将不能执行。这一行告之脚本系统中awk的位置。通过将命令分开,脚本可读性提高,还可以在命令之间加入注释。这里加入头信息和结尾的平均值。基本上这是一个一行脚本文件。
执行时,在脚本文件后键入输入文件名,但是首先要对脚本文件加入可执行权限。
系统中运用的帐号核实程序检验数据操作人的数据输入,不幸的是这个程序有一点错误,或者应该说是“非文本特征”。如果一个记录被发现包含一个错误,它应该一次只打印一行“ERROR*”,但实际上打印了许多这样的错误行。这会给帐号管理员造成误解,因此需要用awk脚本过滤出错误行的出现频率,使得每一个失败记录只对应一个错误行。
在awk实施过滤前先看看部分文件:

5. 在awk中使用FS变量
如果使用非空格符做域分隔符(FS)浏览文件,例如#或:,编写这样的一行命令很容易,因为使用FS选项可以在命令行中指定域分隔符。
$ awk -F:'awk {print $0}' input-file
使用awk脚本时,记住设置FS变量是在BEGIN部分。如果不这样做,awk将会发生混淆,不知道域分隔符是什么。下述脚本指定FS变量。脚本从/etc/passwd文件中抽取第1和第5域,通过分号“;”分隔passwd文件域。第1域是帐号名,第5域是帐号所有者。

文本包括了比实际命令更多的信息,没关系,仔细研读文本后,就可以精确知道其功能及如何调用它。
不要忘了增加脚本的可执行权限,然后将变量和赋值放在命令行脚本名字后、输入文件前执行。
$ age.awk AGE=10 grade.txt
同样可以使用前面提到的管道命令传值,下述awk脚本从du命令获得输入,并输出块和字节数。

awk数组
前面讲述split函数时,提到怎样使用它将元素划分进一个数组。这里还有一个例子:
$ awk 'BEGIN{print split("123#456#789",myarray,#)}'
3
在上面的例子中,split返回数组myarray下标数。实际上myarray数组为:
Myarray[1]=123
Myarray[2]=456
Myarray[3]=789
数组使用前,不必定义,也不必指定数组元素个数。经常使用循环来访问数组。下面是一种循环类型的基本结构:
For (element in array ) print array[element]
对于记录“123#456#678”,先使用split函数划分它,再使用循环打印各数组元素。操作脚本如下:

数组和记录
上面的例子讲述怎样通过split函数使用数组。也可以预先定义数组,并使用它与域进行比较测试,下面的例子中将使用更多的数组。
下面是从空手道数据库卸载的一部分数据,包含了学生级别及是否是成人或未成年人的信息,有两个域,分隔符为(#),文件如下:

脚本功能是读文件并输出下列信息。
1) 俱乐部中Yellow、Orange和Red级别的人各是多少。
2) 俱乐部中有多少成年人和未成年人。
查看文件,也许20秒内就会猜出答案,但是如果记录超过6 0个又怎么办呢?这不会很容易就看出来,必须使用awk脚本。
首先看看awk脚本,然后做进一步讲解。

BEGIN部分设置FS为符号#,即域分隔符,因为要查找Yellow、Orange和Red三个级别。然后在脚本中手工建立数组下标对学生做同样的操作。注意,脚本到此只有下标或元素,并没有给数组名本身加任何注释。初始化完成后,BEGIN部分结束。记住BEGIN部分并没有文件处理操作。
现在可以处理文件了。首先给数组命名为color,使用循环语句测试域1级别列是否等于数组元素之一(Yellow、Orange或Red),如果匹配,依照匹配元素将运行总数保存进数组。同样处理数组‘Senior_or_junior’,浏览域2时匹配操作满足,运行总数存入junior或senior的匹配数组元素。
END部分打印浏览结果,对每一个数组使用循环语句并打印它。
注意在打印语句末尾有一个/符号,用来通知awk(或相关脚本)命令持续到下一行,当输入一个很长的命令,并且想分行输入时可使用这种方法。运行脚本前记住要加入可执行权限。

263月/10

PHP中文件读写操作

发布在 邵珠庆

以下为文件读写操作的 基本PHP函数及模式(看不明白就记住他)

关于模式:
'r' - 只读方式打开, 文件指针置于文件头
'r+' - 读写方式打开,文件指针置于文件头
'w' - 只写打开,文件指针置于文件头, 文件被剪切为0字节, 如果文件不存在, 尝试建立文件
'w+' - 读写打开,文件指针置于文件头, 文件大小被剪切为0字节,如果文件不存在, 尝试建立文件
'a' - 只写方式打开,文件指针置于文件尾,如果文件不存在,尝试建立文件
'a+' - 读写打开,文件指针置于文件尾,如果文件不存在, 尝试建立文件
fgets —  从文件指针中读取一行
fgetss — 从文件指针中读取一行并过滤掉 HTML 标记
file — 把整个文件读入一个数组中
fgetcsv — 从文件指针中读入一行并解析 CSV 字段

你一定用过“网络硬盘”吧,利用它可以按自己的需要新建文件夹来分门别类地把自己的一些文件保存起来,有的还可以在线编辑文件。

PHP中提供了一系列的I/O函数,能简捷地实现我们所需要的功能,包括文件系统操作和目录操作(如“复制[copy]”)。下面给大家介绍的是基本的文件读写操作:(1)读文件;(2)写文件;(3)追加到文件。

TEXT 代码:

  1. 作者: Mukul
  2. 翻译: 无伤 <goghs@mail.com>

读文件:

  1. <?php
  2. $file_name="data.dat";
  3. // 要读取的文件的绝对路径: homedata.dat
  4. $file_pointer=fopen($file_name,"r");
  5. // 打开文件,"r" 是一种模式,或者说我们要进行的操作方法,详见本文后面的介绍
  6. $file_read=fread($file_pointer,filesize($file_name));
  7. // 通过文件指针读取文件内容
  8. fclose($file_pointer);
  9. // 关闭文件
  10. print"读取到的文件内容是: $file_read";
  11. // 显示文件内容
  12. ?>

写文件:

  1. <?php
  2. $file_name="data.dat";
  3. // 绝对路径: homedata.dat
  4. $file_pointer=fopen($file_name,"w");
  5. // "w"是一种模式,详见后面
  6. fwrite($file_pointer,"what you wanna write");
  7. // 先把文件剪切为0字节大小, 然后写入
  8. fclose($file_pointer);
  9. // 结束
  10. print"数据成功写入文件";
  11. ?>

追加到文件后面:

  1. <?php
  2. $file_name="data.dat";
  3. // 绝对路径: homedata.dat
  4. $file_pointer=fopen($file_name,"a");
  5. // "w"模式
  6. fwrite($file_pointer,"what you wanna append");
  7. // 不把文件剪切成0字节, 把数据追加到文件最后
  8. fclose($file_pointer);
  9. // 结束
  10. print"数据成功追加到文件";
  11. ?>

以上只是简单介绍,下面我们要讨论一些更深层的。

有时候会发生多人写入的情况(最常见是在流量较大的网站),会产生无用的数据写入文件, 例如:

info.file文件内容如下 ->

|1|Mukul|15|Male|India (n)
|2|Linus|31|Male|Finland (n)

现在两个人同时注册,引起文件破坏->

info.file ->

|1|Mukul|15|Male|India
|2|Linus|31|Male|Finland
|3|Rob|27|Male|USA|
Bill|29|Male|USA

上例中当PHP写入Rob的信息到文件的时候,Bill正好也开始写入,这时候正好需要写入Rob纪录的'n',引起文件破坏。

我们当然不希望发生这样的情况, 所以让我们看看文件锁定:

复制内容到剪贴板

PHP 代码:
  1. <?php
  2. $file_name="data.dat";
  3. $file_pointer=fopen($file_name,"r");
  4. $lock=flock($file_pointer, LOCK_SH);
  5. // 我使用4.0.2,所以用LOCK_SH,你可能需要直接写成 1.
  6. if($lock){
  7. $file_read=fread($file_pointer,filesize($file_name));
  8. $lock=flock($file_pointer, LOCK_UN);
  9. // 如果版本小于PHP4.0.2, 用 3 代替 LOCK_UN
  10. }
  11. fclose($file_pointer);
  12. print"文件内容为 $file_read";
  13. ?>

上例中,如果两个文件read.php和read2.php都要存取该文件,那么它们都可以读取,但是当一个程序需要写入的时候,它必须等待,直到读操作完成,文件所释放。

  1. <?php
  2. $file_name="data.dat";
  3. $file_pointer=fopen($file_name,"w");
  4. $lock=flock($file_pointer, LOCK_EX);
  5. // 如果版本低于PHP4.0.2, 用 2 代替 LOCK_EX
  6. if($lock){
  7. fwrite($file_pointer,"what u wanna write");
  8. flock($file_pointer, LOCK_UN);
  9. // 如果版本低于PHP4.0.2, 用 3 代替 LOCK_UN
  10. }
  11. fclose($file_pointer);
  12. print"数据成功写入文件";
  13. ?>

虽然"w"模式用来覆盖文件, 单我觉得不适用。

  1. <?php
  2. $file_name="data.dat";
  3. $file_pointer=fopen($file_name,"a");
  4. $lock=flock($file_pointer, LOCK_EX);
  5. // 如果版本低于PHP4.0.2, 用 2 代替 LOCK_EX
  6. if($lock){
  7. fseek($file_pointer,0, SEEK_END);
  8. // 如果版本小于PHP4.0RC1, 使用 fseek($file_pointer, filsize($file_name));
  9. fwrite($file_pointer,"what u wanna write");
  10. flock($file_pointer, LOCK_UN);
  11. // 如果版本低于PHP4.0.2, 用 3 代替 LOCK_UN
  12. }
  13. fclose($file_pointer);
  14. ?>

Hmmm..., 对于追加数据与其他操作有点不同,就是FSEEK! 确认文件指针在文件尾部总是一个好习惯。

如果是在Windows系统下, 上面的文件中文件名前面需要加上''.