Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4564947
  • 博文数量: 1214
  • 博客积分: 13195
  • 博客等级: 上将
  • 技术积分: 9105
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-19 14:41
个人简介

C++,python,热爱算法和机器学习

文章分类

全部博文(1214)

文章存档

2021年(13)

2020年(49)

2019年(14)

2018年(27)

2017年(69)

2016年(100)

2015年(106)

2014年(240)

2013年(5)

2012年(193)

2011年(155)

2010年(93)

2009年(62)

2008年(51)

2007年(37)

分类: 大数据

2014-05-28 15:50:31

文章来源:

摘要 MIME是目前互联网邮件普遍采用的格式标准,本文通过对MIME邮件格式规范的分析和说明,给出了从邮件中提取其所含各种信息的基本方法。

关键词 MIME、邮件、格式、信息提取

MIME,英文全称为“Multipurpose Internet Mail Extensions”,即多用途互联网邮件扩展,是目前互联网电子邮件普遍遵循的邮件技术规范。在MIME出现之前,互联网电子邮件主要遵循由RFC 822所制定的标准,电子邮件一般只用来传递基本的ASCII码文本信息,MIME在 RFC 822的基础上对电子邮件规范做了大量的扩展,引入了新的格式规范和编码方式,在MIME的支持下,图像、声音、动画等二进制文件都可方便的通过电子邮件来进行传递,极大地丰富了电子邮件的功能。目前互联网上使用的基本都是遵循MIME规范的电子邮件。

电子邮件的分析和读取一般都通过专用的邮件软件来实现,比如Outlook、Foxmail,但这种第三方软件无法和开发者自己的系统整合,通过对MIME邮件格式的分析,我们可以在自己的应用程序中实现对MIME邮件所含信息的读取。

1 MIME邮件格式分析

MIME技术规范的完整内容由RFC 2045-2049定义,包括了信息格式、媒体类型、编码方式等各方面的内容,这里我们只介绍其中的一些关键的格式和规范,通过了解这些格式规范,我们就可以实现以编程的方式从MIME邮件中提取基本的邮件信息。

1.1 域

MIME邮件的基本信息、格式信息、编码方式等重要内容都记录在邮件内的各种域中,域的基本格式:{域名}:{内容},域由域名后面跟“:”再加上域的信息内容构成,一条域在邮件中占一行或者多行,域的首行左侧不能有空白字符,比如空格或者制表符,占用多行的域其后续行则必须以空白字符开头。域的信息内容中还可以包含属性,属性之间以“;”分隔,属性的格式如下:{属性名称}=”{属性值}”。 表1是一封示例邮件的内容,其中行1-5、行8都是单行的域,行6-7则是一个多行的域,并带有一个名为charset的属性,属性值为us-ascii。

表1 示例电子邮件

行1 From: ”suntao” 
行2 To: 
行3 Subject: hello world
行4 Date: Mon, 9 Oct 2006 16:51:34 +0800
行5 MIME-Version: 1.0
行6 Content-Type: text/plain;
行7             charset="us-ascii"
行8 Date: Mon, 9 Oct 2006 16:48:25 +0800
行9
行10 Hello world
行11

邮件规范中定义了大量域,分别用来存储同邮件相关的各种信息,比如发件人的名字和邮件地址信息存储在From域中,收件人的邮件地址信息存储在To域中,开发人员可通过查询RFC文档得到完整的邮件域定义列表。

1.2 Content-Type域

Content-Type域定义了邮件中所含各种内容的类型以及相关属性。邮件所含的文本、超文本、附件等信息都按照对应Content-Type域所指定的媒体类型、存储位置、编码方式等信息存储在邮件中。Content-Type域基本格式:Content-Type:{主类型}/{子类型}。

示例邮件中的行6-7就是一个Content-Type域,主类型为text,子类型为plain,字符集属性为us-ascii。

表2:MIME邮件中常见的主类型

主类型 常见属性 参数含义
text charset 文本信息所使用的字符集
image name 图像的名称
application name 应用程序的名称
multipart boundary 邮件分段边界标识

1.3 multipart类型

MIME邮件中各种不同类型的内容是分段存储的,各个段的排列方式、位置信息都通过Content-Type域的multipart类型来定义。multipart类型主要有三种子类型:mixed、alternative、related。

1.3.1 multipart类型基本格式

● multipart/mixed类型

如果一封邮件中含有附件,那邮件的Content-Type域中必须定义multipart/mixed类型,邮件通过multipart/mixed类型中定义的boundary标识将附件内容同邮件其它内容分成不同的段。基本格式如下:

Content-Type: multipart/mixed;
boundary="{分段标识}"

● multipart/alternative类型

MIME邮件可以传送超文本内容,但出于兼容性的考虑,一般在发送超文本格式内容的同时会同时发送一个纯文本内容的副本,如果邮件中同时存在纯文本和超文本内容,则邮件需要在Content-Type域中定义multipart/alternative类型,邮件通过其boundary中的分段标识将纯文本、超文本和邮件的其它内容分成不同的段。基本格式如下:

Content-Type: multipart/alternative;
boundary="{分段标识}"

● multipart/related类型

MIME邮件中除了可以携带各种附件外,还可以将其它内容以内嵌资源的方式存储在邮件中。比如我们在发送html格式的邮件内容时,可能使用图像作为html的背景,html文本会被存储在alternative段中,而作为背景的图像则会存储在multipart/related类型定义的段中。基本格式如下:

Content-Type: multipart/related;
type="multipart/alternative";
boundary="{分段标识}"

1.3.2 multipart类型的boundary属性

multipart的子类型中都定义了各自的boundary属性,邮件使用这些boundary中定义的字符串作为标识,将邮件内容分成不同的段,段体内的每个子段以“–”+boundary行开始,父段则以“–”+boundary+“–”行结束,不同段之间用空行分隔。

1.3.3 multipart类型的层次关系

表3:multipart子类型之间的层次关系

MIME邮件通过多个Content-Type域的multipart类型将内容分成不同的段,这些段在邮件中不是线形顺序排列的,而是存在一个互相包含的层次关系,multipart子类型之间的层次关系结构如表3。

1.4 Content-Transfer-Encoding域

MIME邮件可以传送图像、声音、视频以及附件,这些非ASCII码的数据都是通过一定的编码规则进行转换后附着在邮件中进行传递的。编码方式存储在邮件的Content-Transfer-Encoding域中,一封邮件中可能有多个Content-Transfer-Encoding域,分别对应邮件不同部分内容的编码方式。目前MIME邮件中的数据编码普遍采用Base64编码或Quoted-printable编码来实现。

1.4.1 Base64编码

Base64编码的目的是将输入的数据全部转换成由64个指定ASCII字符组成的字符序列, 这64个字符由{'A'-'Z', 'a'-'z', '0'-'9', '+', '/'}构成。编码时将需要转换的数据每次取出6bit,然后将其转换成十进制数字,这个数字的范围最小为0,最大为63,然后查询{'A'-'Z', 'a'-'z', '0'-'9', '+', '/'}构成的字典表,输出对应位置的ASCII码字符,这样每3个字节的数据内容会被转换成4个字典中的ASCII码字符,当转换到数据末尾不足3个字节时,则用“=”来填充。

1.4.2 Quoted-printable编码

Quoted-printable编码的目的也是将输入的信息转换成可打印的ASCII码字符,但它是根据信息的内容来决定是否进行编码,如果读入的字节处于33-60、62-126范围内的,这些都是可直接打印的ASCII字符,则直接输出,如果不是,则将该字节分为两个4bit,每个用一个16进制数字来表示,然后在前面加“=”,这样每个需要编码的字节会被转换成三个字符来表示。

2 MIME邮件信息提取

从上面的分析可以看出,MIME邮件传递的实际是一个经过特殊编码并以约定格式排列的字符序列,我们只需要提取存储在邮件各种域中的格式、位置和编码信息,按照根据这些信息从字符序列中提取出对应的字符内容并对其进行反向解码,就可以得到我们需要的有关内容。

下面给出.Net环境下,利用C#结合正则表达式从邮件中提取相关信息的基本思路和部分代码。

2.1 收件人/发件人/邮件主题的提取

收件人、发件人、邮件主题是一封邮件的基本组成信息,分别存邮件的From域、To域、Subject域中。开发中只需要通过正则表达式来匹配这些指定的域,然后从匹配结果中取出相关信息即可。

示例代码:提取邮件主题

string emailContent = "……";//emailContent中存储的是邮件内容
pat = @"^Subject:\s*(?.*)\s*\r\n";
myMatches = Regex.Matches(emailContent,pat,RegexOptions.Multiline);
foreach(Match nextMatch in myMatches)
{
          GroupCollection myGroup = nextMatch.Groups;
          string title = myGroup["title"].ToString();//title变量存储From域的内容
          ……
}</pre>
	<p style="margin-top:0px;margin-bottom:1em;">
		需要注意的是上面的代码提取的是跟随在Subject:后面的字符串,如果邮件的主题内容是中文或者其它需要编码的地区文字,则还需要对其进行解码。比如,如果邮件的Subject域中的信息是“你好”,那么提取出来的字符串会是这种形式:=?gb2312?B?xOO6ww==?=,第一个?同第二个?之间的gb2312代表标题内容所使用的字符集,第二个?和第三个?之间的B代表这部分内容采用的是base64编码方式,如果采用Quoted-printabel编码方式则显示Q,第三个?和第四个?之间则是“你好”经过base64编码后的字符串。
	</p>
</div>
<h3 class="sectionedit10" style="padding:0.5em 0px 0px;margin:0px 0px 1em 40px;color:#333333;font-size:21px;font-weight:normal;border-bottom-style:none;border-color:#CCCCCC;clear:left;font-family:Verdana, 'Lucida Grande', Lucida, Helvetica, Arial, sans-serif;line-height:19.5px;text-align:justify;white-space:normal;background-color:#FFFFFF;">
	2.2 multipart分段信息的提取
</h3>
<div class="level3" style="padding:0px;margin:0px 0px 0px 43px;color:#333333;font-family:Verdana, 'Lucida Grande', Lucida, Helvetica, Arial, sans-serif;font-size:13px;line-height:19.5px;text-align:justify;white-space:normal;background-color:#FFFFFF;">
	<p style="margin-top:0px;margin-bottom:1em;">
		邮件通过multipart类型将内容分隔成不同的段,各段之间的边界标识由对应multipart类型的boundary属性定义。要从邮件中提取出需要的内容,首先需要提取出邮件中的分段信息。下面的代码从一封邮件中提取出所有的multipart类型的名称和boundary属性。
	</p>
	<p style="margin-top:0px;margin-bottom:1em;">
		示例代码:提取multipart信息
	</p>
<pre class="code" style="padding:0.5em;margin-bottom:1em;border-style:dashed;border-color:#CCCCCC;width:auto !important;background-color:#F7F9FA;">string emailContent = “……”;//emailContent中存储的是邮件内容
string pat = @"\bContent-Type:\s*(?<type>\w+/\w+);\s+(type=\S(?<subtype>\S+)\S)?\s+boundary=""(?<flag>\S+)""";
MatchCollection myMatches = Regex.Matches(emailContent,pat);
foreach(Match nextMatch in myMatches)
{
          GroupCollection myGroup = nextMatch.Groups;
          string type = myGroup["type"].ToString();//type变量存储multipart类型的名称
          string flag = myGroup["flag"].ToString();//flag变量存储multipart类型的boundary属性
          ……
}</pre>
</div>
<h3 class="sectionedit11" style="padding:0.5em 0px 0px;margin:0px 0px 1em 40px;color:#333333;font-size:21px;font-weight:normal;border-bottom-style:none;border-color:#CCCCCC;clear:left;font-family:Verdana, 'Lucida Grande', Lucida, Helvetica, Arial, sans-serif;line-height:19.5px;text-align:justify;white-space:normal;background-color:#FFFFFF;">
	2.3 邮件附件的提取
</h3>
<div class="level3" style="padding:0px;margin:0px 0px 0px 43px;color:#333333;font-family:Verdana, 'Lucida Grande', Lucida, Helvetica, Arial, sans-serif;font-size:13px;line-height:19.5px;text-align:justify;white-space:normal;background-color:#FFFFFF;">
	<p style="margin-top:0px;margin-bottom:1em;">
		邮件中的附件信息由对应的Content-Type域、Content-Transfer-Encoding域、Content-Disposition域和multipart/mixed类型定义,前三个域定义附件的类型、名称和编码方式,multipart/mixed则定义附件同邮件其它内容的分段标识。基本格式如下:
	</p>
<pre class="code" style="padding:0.5em;margin-bottom:1em;border-style:dashed;border-color:#CCCCCC;width:auto !important;background-color:#F7F9FA;">--boundary分段标识
Content-Type: application/msword;
name="readme.doc"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename=" readme.doc "
……
文件内容的Base64编码
……
--boundary分段标识</pre>
	<p style="margin-top:0px;margin-bottom:1em;">
		示例代码:提取邮件附件
	</p>
<pre class="code" style="padding:0.5em;margin-bottom:1em;border-style:dashed;border-color:#CCCCCC;width:auto !important;background-color:#F7F9FA;">//boundaryMixed代表已经提取出的multipart/mixed类型的boundary标识
//DecodeBase64为自定义的base64解码函数
//DecodeQuotedPrintable为自定义的quoted-printable解码函数
string emailContent = “……”;//emailContent中存储的是邮件内容
string pat = @"\r\nContent-Type:\s*(?<filetype>\S*);\s*name=""(?<name>\S*)""\s*Content-Transfer-Encoding:\s*(?<encoding>\S*)\s*Content-Disposition:\s*attachment;\s*filename=""(?<filename>\S+)""\s+(?<content>[\S|\r\n]+)" + "--" + boundaryMixed;
MatchCollection myMatches = Regex.Matches(emailContent,pat,RegexOptions.Singleline);    
foreach(Match nextMatch in myMatches)
{
          //提取附件的类型、编码方式、文件名、内容信息
          GroupCollection myGroup = nextMatch.Groups;
          string fileType = myGroup["filetype"].ToString();
          string encoding = myGroup["encoding"].ToString();
          string fileName = myGroup["filename"].ToString();
          string content = myGroup["content"].ToString().Trim();
          byte[] attachFile;
          //根据附件的编码方式对提取出的附件内容进行解码
          if(encoding == “base64”)
          {
                    attachFile = DecodeBase64 (content);
}
if(encoding == “quoted-printable”)
{
                    attachFile = DecodeQuotedPrintable (content);
}
//将解码后的内容写入磁盘
          FileStream fs = new FileStream("c:\\" + fileName,
FileMode.CreateNew);
          BinaryWriter bw = new BinaryWriter(fs);
          bw.Write(attachFile);
          bw.Close();
          fs.Close();
}</pre>
	<p style="margin-top:0px;margin-bottom:1em;">
		上面的程序从邮件原文中提取出附件信息,并根据附件采用的编码类型进行解码,然后将解码后的内容按照原文件名存储到C盘根目录。同样,如果附件的文件名是中文或者其它需要编码的文字,则首先需要对文件名进行解码。
	</p>
</div>
<h2 class="sectionedit12" style="padding:0.5em 0px 0px;margin:0px 0px 1em 20px;color:#333333;font-size:22px;font-weight:normal;border-bottom-width:1px;border-bottom-style:solid;border-color:#CCCCCC;clear:left;font-family:Verdana, 'Lucida Grande', Lucida, Helvetica, Arial, sans-serif;line-height:19.5px;text-align:justify;white-space:normal;background-color:#FFFFFF;">
	3 总结
</h2>
<div class="level2" style="padding:0px;margin:0px 0px 0px 23px;color:#333333;font-family:Verdana, 'Lucida Grande', Lucida, Helvetica, Arial, sans-serif;font-size:13px;line-height:19.5px;text-align:justify;white-space:normal;background-color:#FFFFFF;">
	<p style="margin-top:0px;margin-bottom:1em;">
		本文对MIME邮件的基本格式做了分析和阐述,介绍了MIME中几个重要的规范和定义,并给出了利用正则表达式从邮件内容中提取相关信息的基本思路和方法。在开发中需要注意的是,邮件中所含的内容决定了邮件的具体格式,multipart类型以及对应的分段标识只有在有相关内容的时候才会在邮件中出现,在开发时需要具体分析。MIME的详细技术规范可以查询RFC的相关文档。
	</p>
</div>                                   </div>
            <!-- <div class="Blog_con3_1">管理员在2009年8月13日编辑了该文章文章。</div> -->
            <div class="Blog_con2_1 Blog_con3_2">
              <div>
			  <!--<img src="/image/default/tu_8.png">-->
			  <!-- JiaThis Button BEGIN -->
				<div class="bdsharebuttonbox"><A class=bds_more href="#" data-cmd="more"></A><A class=bds_qzone title=分享到QQ空间 href="#" data-cmd="qzone"></A><A class=bds_tsina title=分享到新浪微博 href="#" data-cmd="tsina"></A><A class=bds_tqq title=分享到腾讯微博 href="#" data-cmd="tqq"></A><A class=bds_renren title=分享到人人网 href="#" data-cmd="renren"></A><A class=bds_weixin title=分享到微信 href="#" data-cmd="weixin"></A></div>
<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
				<!-- JiaThis Button END -->
			  </div>
              阅读(3891) | 评论(0) | 转发(0) |
			                <div class="HT_line3"></div>
            </div>
            
            <div class="Blog_con3_3">
              <div><span id='digg_num'>0</span><a href="javascript:void(0)" id='digg' bid='4277145' url='/blog/digg.html' ></a></div>
              <p>上一篇:<a href="/uid-9162199-id-4277138.html">走进cassandra之七:最终一致性</a></p>
              <p>下一篇:<a href="/uid-9162199-id-4330727.html">机器学习中的算法(2)-支持向量机(SVM)基础</a></p>    
            </div>
            
          </div>
          		  <!--
          <div class="Blog_con3_4 Blog_con3_5">
            <div class="Blog_tit2 Blog_tit7">热门推荐</div>
            <ul>
			              <li><a href="" title="" target='blank' ></a></li>
			            </ul>
          </div>
		  -->
        </div>
      </div>
      <div class="Blog_right1_7" id='replyList'>
		<div class="Blog_tit3">给主人留下些什么吧!~~</div>
				<!--暂无内容-->
				<!-- 评论分页-->
		<div class="Blog_right1_6 Blog_right1_12">
        		</div>
		<!-- 评论分页-->
        <div class="Blog_right1_10" style="display:none">
          <div class="Blog_tit3">评论热议</div>
		  		 <!--未登录 -->
        <div class="Blog_right1_8">
          <div class="nologin_con1"> 请登录后评论。
            <p><a href="http://account.chinaunix.net/login"  onclick="link(this)">登录</a> <a href="http://account.chinaunix.net/register?url=http%3a%2f%2fblog.chinaunix.net">注册</a></p>
          </div>
        </div>
       
		
        </div>
        <div style="text-align:center;margin-top:10px;">
            <script type="text/javascript" smua="d=p&s=b&u=u3118759&w=960&h=90" src="//www.nkscdn.com/smu0/o.js"></script>
        </div>
      </div>
    </div>
  </div>
  <input type='hidden' id='report_url' value='/blog/ViewReport.html' />

<script type="text/javascript">
  	//测试字符串的长度 一个汉字算2个字节
	function mb_strlen(str)
	{
		var len=str.length;
		var totalCount=0;
		for(var i=0;i<len;i++)
		{
			var c = str.charCodeAt(i);
			if ((c >= 0x0001 && c <= 0x007e) || (0xff60<=c && c<=0xff9f)) {
				totalCount++;
			}else{
				totalCount+=2;
			}
		}
		return totalCount;
	}
	/*
	var Util = {};
	Util.calWbText = function (text, max){
		if(max === undefined)
			max = 500;
		var cLen=0;
		var matcher = text.match(/[^\x00-\xff]/g),
			wlen  = (matcher && matcher.length) || 0;
		//匹配url链接正则 http://***
		var pattern = /http:\/\/([\w-]+\.)+[\w-]+(\/*[\w-\.\/\?%&=][^\s^\u4e00-\u9fa5]*)?/gi;
		//匹配的数据存入数组
		var arrPt = new Array();
		var i = 0;
		while((result = pattern.exec(text)) != null){
			arrPt[i] = result[0];
			i++;
		}
		//替换掉原文本中的链接
		for(var j = 0;j<arrPt.length;j++){
			text = text.replace(arrPt[j],"");
		}
		//减掉链接所占的长度
		return Math.floor((max*2 - text.length - wlen)/2 - 12*i);
	};
	*/
	var allowComment = '0';
	
	//举报弹出层
	function showJuBao(url, cid){
		
			$.cover(false);
			asyncbox.open({
				id  : 'report_thickbox',
				url : url,
				title : '举报违规',
				width : 378,
				height : 240,
				scroll : 'no',
				data : {
					'cid'	 : cid,
					'idtype' : 2 ,
                                        'blogurl' : window.location.href
				},
				callback : function(action){
					if(action == 'close'){
						$.cover(false);
					}
				}
			});
	}

	$(function(){

		//创建管理员删除的弹出层
		$('#admin_article_del').click(function(){
			$.cover(false);
			asyncbox.open({
				id : 'class_thickbox',
				html : '<div class="HT_layer3_1"><ul><li class="HT_li1">操作原因:<select class="HT_sel7" id="del_type" name="del_type"><option value="广告文章">广告文章</option><option value="违规内容">违规内容</option><option value="标题不明">标题不明</option><option value="文不对题">文不对题</option></select></li><li class="HT_li1" ><input class="HT_btn4" id="admin_delete"  type="button" /></li></ul></div>',
				title : '选择类型',
				width : 300,
				height : 150,
				scroll : 'no',
				callback : function(action){
					if(action == 'close'){
						$.cover(false);
					}
				}
			});
		});
		$('#admin_delete').live('click' , function(){
			///blog/logicdel/id/3480184/url/%252Fblog%252Findex.html.html
			var type = $('#del_type').val();
			var url = '/blog/logicdel/id/4277145/url/%252Fuid%252F9162199.html.html';
			window.location.href= url + '?type=' + type;
		});


		//顶  js中暂未添加&过滤 
		$('#digg').live('click' , function(){

			if(isOnLine == '' )
			{
				//showErrorMsg('登录之后才能进行此操作' , '消息提示');
				showErrorMsg('操作失败,您需要先登录!', '消息提示', 'http://account.chinaunix.net/login');
				return false;
			}

			var bid = $('#digg').attr('bid');
			var url = $('#digg').attr('url');

			var digg_str = $.cookie('digg_id');
			if(digg_str != null)
			{
				var arr= new Array(); //定义一数组

				arr = digg_str.split(","); //字符分割     
				for( i=0 ; i < arr.length ; i++ )   
				{   
					if(bid == arr[i])
					{
						showErrorMsg('已经赞过该文章', '消息提示'); 
						return false;
					}
				} 
			}
			$.ajax({
				type:"POST",
				url:url,	
				data: {
					'bid' : bid 
				},
				dataType: 'json',
				success:function(msg){
					if(msg.error == 0)
					{
						var num = parseInt($('#digg_num').html(),10);
						num += 1;
						$('#digg_num').html(num);
						$('#digg').die();

						if(digg_str == null)
						{
							$.cookie('digg_id', bid, {expires: 30 , path: '/'});
						}
						else
						{
							$.cookie('digg_id', digg_str + ',' + bid, {expires: 30 , path: '/'});
						}
						showSucceedMsg('谢谢' , '消息提示');
					}
					else if(msg.error == 1)
					{
						//showErrorMsg(msg.error_content , '消息提示'); 
						showErrorMsg('操作失败,您需要先登录!', '消息提示', 'http://account.chinaunix.net/login');
					}
					else if(msg.error == 2)
					{
						showErrorMsg(msg.error_content , '消息提示'); 
					}
				}
			});
		});
		//举报弹出层
		/*$('.box_report').live('click' , function(){
			if(isOnLine == '' )
			{
				//showErrorMsg('登录之后才能进行此操作' , '消息提示');
				showErrorMsg('操作失败,您需要先登录!', '消息提示', 'http://account.chinaunix.net/login');
				return false;
			}
			var url = $('#report_url').val();
			var cid = $(this).attr('cid');
			$.cover(false);
			asyncbox.open({
				id  : 'report_thickbox',
				url : url,
				title : '举报违规',
				width : 378,
				height : 240,
				scroll : 'no',
				data : {
					'cid'	 : cid,
					'idtype' : 2 
				},
				callback : function(action){
					if(action == 'close'){
						$.cover(false);
					}
				}
			});
		});*/


		//评论相关代码
		
		//点击回复显示评论框
		$('.Blog_a10').live('click' , function(){
			if(isOnLine == '' )
			{
				//showErrorMsg('登录之后才能进行此操作' , '消息提示');
				showErrorMsg('操作失败,您需要先登录!', '消息提示', 'http://account.chinaunix.net/login');
				return false;
			}

			if(allowComment == 1)
			{
				showErrorMsg('该博文不允许评论' , '消息提示'); 
				return false;
			}
			var tid = $(this).attr('toid');//留言作者id
			var bid = $(this).attr('bid');//blogid
			var cid = $(this).attr('cid');//留言id
			var tname = $(this).attr('tname');
                         			var tpl  = '<div class="Blog_right1_9">';
				tpl +=	 '<div class="div2">';
				tpl +=     '<textarea name="" cols="" rows="" class="Blog_ar1_1" id="rmsg">文明上网,理性发言...</textarea>';
				tpl +=	 '</div>';
				tpl +=   '<div class="div3">';
				tpl +=		'<div class="div3_2"><a href="javascript:void(0);" class="Blog_a11" id="quota_sbumit" url="/Comment/PostComment.html" tid="'+tid+'" bid="'+bid+'" cid="'+cid+'" tname="'+tname+'" ></a><a href="javascript:void(0)" id="qx_comment" class="Blog_a12"></a></div>';
				tpl +=		'<div class="div3_1"><a href="javascript:void(0);" id="mface"><span></span>表情</a></div>';
				tpl +=		'<div class="clear"></div>';
				tpl +=	 '</div>';
				tpl +=  '</div>';
                                 			$('.z_move_comment').html('');
			$(this).parents('.Blog_right1_8').find('.z_move_comment').html(tpl).show();
		});
		//引用的评论提交
		$('#quota_sbumit').live('click' , function(){

			if(isOnLine == '' )
			{
				//showErrorMsg('登录之后才能进行此操作' , '消息提示');
				showErrorMsg('操作失败,您需要先登录!', '消息提示', 'http://account.chinaunix.net/login');
				return false;
			}

			var bid   = $(this).attr('bid');
			var tid   = $(this).attr('tid');//被引用人的id
			var qid   = $(this).attr('cid');//引用的id
			var url = $(this).attr('url');
			var text = $('#rmsg').val();
			var tname = $(this).attr('tname');
			if(text == '' || text=='文明上网,理性发言...')
			{
				showErrorMsg('评论内容不能为空!' , '消息提示'); 
				return false;
			}
			else
			{
				if(mb_strlen(text) > 1000){
					showErrorMsg('评论内容不能超过500个汉字' , '消息提示'); 
					return false;
				}
			}
		    $.ajax({
		        type: "post",
			    url: url ,
			    data: {'bid': bid , 'to' : tid , 'qid' : qid , 'text': text , 'tname' : tname },
				dataType: 'json',
			    success: function(data){
				    if(data.code == 1){
						var tpl =  '<div class="Blog_right1_8">';
							tpl+=     '<div class="Blog_right_img1"><a href="' +data.info.url+ '" >' + data.info.header + '</a></div>';
							tpl+=     '<div class="Blog_right_font1">';
							tpl+=         '<p class="Blog_p5"><span><a href="' +data.info.url+ '" >' + data.info.username + '</a></span>' + data.info.dateline + '</p>';
							tpl+=         '<p class="Blog_p7"><a href="' + data.info.quota.url + '">' + data.info.quota.username + '</a>:'+ data.info.quota.content + '</p>';
							tpl+=         '<p class="Blog_p8">' + data.info.content + '</p><span class="span_text1"><a href="javascript:void(0);" class="Blog_a10" toid=' + data.info.fuid + ' bid=' + data.info.bid + ' cid=' + data.info.cid + '  tname = ' + data.info.username + ' >回复</a> |  <a class="comment_del_mark" style="cursor:pointer" url="' + data.info.delurl + '" >删除</a> |  <a href="javascript:showJuBao(\'/blog/ViewReport.html\','+data.info.cid+')" class="box_report" cid="' + data.info.cid + '" >举报</a></span></div>';
							tpl+=         '<div class="z_move_comment" style="display:none"></div>';
							tpl+=	      '<div class="Blog_line1"></div></div>';
							$('#replyList .Blog_right1_8:first').before(tpl);
							$('.z_move_comment').html('').hide();
				    }
					else if(data.code == -1){
						//showErrorMsg(data.info , '消息提示'); 
						showErrorMsg('操作失败,您需要先登录!', '消息提示', 'http://account.chinaunix.net/login');
			        }
                },
			    error: function(){//请求出错处理
                        
                }
			});
		});
		//底部发表评论
		$('#submitmsg').click(function(){
			if(allowComment == 1)
			{
				showErrorMsg('该博文不允许评论' , '消息提示'); 
				return false;
			}
			var bid   = $(this).attr('bid');
			var toid  = $(this).attr('toid');
			var text = $('#reply').val();
			var url = $(this).attr('url');
			if(text == '' || text=='文明上网,理性发言...')
			{
				showErrorMsg('评论内容不能为空!' , '消息提示'); 
				return false;
			}
			else
			{
				if(mb_strlen(text) > 1000){
					showErrorMsg('评论内容不能超过500个汉字' , '消息提示'); 
					return false;
				}
			}
		    $.ajax({
		        type: "post",
			    url: url ,
			    data: {'bid': bid , 'to' : toid ,'text': text},
				dataType: 'json',
			    success: function(data){
				    if(data.code == 1)
					{
						var tpl   = '<div class="Blog_right1_8">';
							tpl  +=   '<div class="Blog_right_img1"><a href="' +data.info.url+ '" >' + data.info.header + '</a></div>';
							tpl  +=	  '<div class="Blog_right_font1">';
							tpl  +=       '<p class="Blog_p5"><span><a href="' +data.info.url+ '" >' + data.info.username + '</a></span>' + data.info.dateline + '</p>';
							tpl  +=       '<p class="Blog_p6">' + data.info.content + '</p>';
							tpl  +=		  '<div class="div1"><a href="javascript:void(0);" class="Blog_a10"  toid=' + data.info.fuid + ' bid=' + data.info.bid + ' cid=' + data.info.cid + '>回复</a> |  <a class="comment_del_mark" style="cursor:pointer" url="' + data.info.delurl + '">删除</a> |  <a href="javascript:showJuBao(\'/blog/ViewReport.html\','+data.info.cid+')" class="box_report" cid="' + data.info.cid + '">举报</a></div>';
							tpl  +=		  '<div class="z_move_comment" style="display:none"></div>';
							tpl  +=    '</div><div class="Blog_line1"></div></div>';
							$('.Blog_tit3:first').after(tpl);
							$('#reply').val('文明上网,理性发言...');
					}
					else if(data.code == -1)
					{
						showErrorMsg(data.info , '消息提示'); 
			        }
                },
			    error: function(){//请求出错处理
                        
                }
		    });
			
		});
		//底部评论重置
		$('#reset_comment').click(function(){
			$('#reply').val('文明上网,理性发言...');
		});
		//取消回复
		$('#qx_comment').live('click' , function(){
			$('.z_move_comment').html('').hide();
		});


		$('#rmsg, #reply').live({
		    focus:function(){
			    if($(this).val() == '文明上网,理性发言...'){
			        $(this).val('');
			    }
			},
			blur:function(){
		        if($(this).val() == ''){
			        $(this).val('文明上网,理性发言...');
			    }
			}
		});
		//删除留言确认
		$('.comment_del_mark').live('click' , function(){
			var url = $(this).attr('url');
			asyncbox.confirm('删除留言','确认', function(action){
				if(action == 'ok')
				{
					location.href = url;
				}
			});
		});
		//删除时间确认
		$('.del_article_id').click(function(){
			var delurl = $(this).attr('delurl');
			asyncbox.confirm('删除文章','确认', function(action){
				if(action == 'ok')
				{
					location.href = delurl;
				}
			});
		});
		/*
		//字数限制
		$('#rmsg, #reply').live('keyup', function(){
			var id = $(this).attr('id');
			var left = Util.calWbText($(this).val(), 500);
			var eid = '#errmsg';
			
			if(id == 'reply') eid =  '#rerrmsg';
			if (left >= 0)
		        $(eid).html('您还可以输入<span>' + left + '</span>字');
		    else
		        $(eid).html('<font color="red">您已超出<span>' + Math.abs(left) + '</span>字 </font>');
		});
		*/
		//加载表情
	    $('#face').qqFace({id : 'facebox1', assign : 'reply', path : '/image/qqface/'});
	    $('#mface').qqFace({id : 'facebox', assign : 'rmsg', path:'/image/qqface/'});
	    
		/*
		$('#class_one_id').change(function(){
			alert(123213);
			var id = parseInt($(this).val() , 10);
			if(id == 0) return false;
			$('.hidden_son_class span').each(function( index , dom ){
				if( dom.attr('cid')  == id )
				{
				}
			});
		});
		*/
		//转载文章
		var turn_url = "/blog/viewClassPart.html";
		$('#repost_bar').click(function(){
			if(isOnLine == '' )
			{
				//showErrorMsg('登录之后才能进行此操作' , '消息提示');
				showErrorMsg('操作失败,您需要先登录!', '消息提示', 'http://account.chinaunix.net/login');
				return false;
			}
			var id = $(this).attr('bid');
			asyncbox.open({
				id  : 'turn_class_thickbox',
				url : turn_url,
				title : '转载文章',
				width : 330,
				height : 131,
				scroll : 'no',
				data : {
					'id'	 : id
				},
				callback : function(action){
					if(action == 'close'){
						$.cover(false);
					}
				}
			});
		});
		/*
	    //转发文章
	    $('#repost_bar').live('click' , function(){
			if(isOnLine == '' )
			{
				//showErrorMsg('登录之后才能进行此操作' , '消息提示');
				showErrorMsg('操作失败,您需要先登录!', '消息提示', 'http://account.chinaunix.net/login');
				return false;
			}
	    	var bid  = $(this).attr('bid');
	    	var url  = $(this).attr('url');
	    	asyncbox.confirm('转载文章','确认', function(action){
	    	  if(action == 'ok'){
	    	    $.ajax({
				type:"POST",
				url:url,	
				data: {
					'bid' : bid 
				},
				dataType: 'json',
				success:function(msg){
				  if(msg.error == 0){
				    showSucceedMsg('转发成功!', '消息提示');
				  }else if(msg.error == 1){
				    //location.href = '/index.php?r=site/login';
					showErrorMsg('操作失败,您需要先登录!', '消息提示', 'http://account.chinaunix.net/login');
				  }else{
				    showErrorMsg(msg.error_content, '消息提示');
			      }
				}
			  });
	    	  }
	    	});

		});
		*/

	});
</script>
<!--该部分应该放在输出代码块的后面才起作用 -->
<script type="text/javascript">

SyntaxHighlighter.autoloader(
	'applescript			/highlight/scripts/shBrushAppleScript.js',
	'actionscript3 as3		/highlight/scripts/shBrushAS3.js',
	'bash shell				/highlight/scripts/shBrushBash.js',
	'coldfusion cf			/highlight/scripts/shBrushColdFusion.js',
	'cpp c					/highlight/scripts/shBrushCpp.js',
	'c# c-sharp csharp		/highlight/scripts/shBrushCSharp.js',
	'css					/highlight/scripts/shBrushCss.js',
	'delphi pascal			/highlight/scripts/shBrushDelphi.js',
	'diff patch pas			/highlight/scripts/shBrushDiff.js',
	'erl erlang				/highlight/scripts/shBrushErlang.js',
	'groovy					/highlight/scripts/shBrushGroovy.js',
	'java					/highlight/scripts/shBrushJava.js',
	'jfx javafx				/highlight/scripts/shBrushJavaFX.js',
	'js jscript javascript	/highlight/scripts/shBrushJScript.js',
	'perl pl				/highlight/scripts/shBrushPerl.js',
	'php					/highlight/scripts/shBrushPhp.js',
	'text plain				/highlight/scripts/shBrushPlain.js',
	'py python				/highlight/scripts/shBrushPython.js',
	'ruby rails ror rb		/highlight/scripts/shBrushRuby.js',
	'scala					/highlight/scripts/shBrushScala.js',
	'sql					/highlight/scripts/shBrushSql.js',
	'vb vbnet				/highlight/scripts/shBrushVb.js',
	'xml xhtml xslt html	/highlight/scripts/shBrushXml.js'
);
SyntaxHighlighter.all();


function code_hide(id){
	var code = document.getElementById(id).style.display;
	if(code == 'none'){
		document.getElementById(id).style.display = 'block';
	}else{
		document.getElementById(id).style.display = 'none';
	}
}
</script>
<!--回顶部js2011.12.30-->
<script language="javascript">
 lastScrollY=0;
 function heartBeat(){
 var diffY;
 if (document.documentElement && document.documentElement.scrollTop)
     diffY = document.documentElement.scrollTop;
 else if (document.body)
     diffY = document.body.scrollTop
 else
     {/*Netscape stuff*/}
 percent=.1*(diffY-lastScrollY);
 if(percent>0)percent=Math.ceil(percent);
 else percent=Math.floor(percent);
 document.getElementById("full").style.top=parseInt(document.getElementById("full").style.top)+percent+"px";
 lastScrollY=lastScrollY+percent;
 if(lastScrollY<200)
 {
 document.getElementById("full").style.display="none";
 }
 else
 {
 document.getElementById("full").style.display="block";
 }
 }
 var gkuan=document.body.clientWidth;
 var ks=(gkuan-960)/2-30;
 suspendcode="<div id=\"full\" style='right:-30px;POSITION:absolute;TOP:500px;z-index:100;width:26px; height:86px;cursor:pointer;'><a href=\"javascript:void(0)\" onclick=\"window.scrollTo(0,0);\"><img src=\"\/image\/top.png\" /></a></div>"
 document.write(suspendcode);
 window.setInterval("heartBeat()",1);
 </script>
  <!-- footer -->
  <div class="Blog_footer" style='clear:both'>
    <div><a href="http://www.chinaunix.net/about/index.shtml" target="_blank" rel="nofollow">关于我们</a> | <a href="http://www.it168.com/bottomfile/it168.shtml" target="_blank" rel="nofollow">关于IT168</a> | <a href="http://www.chinaunix.net/about/connect.html" target="_blank" rel="nofollow">联系方式</a> | <a href="http://www.chinaunix.net/about/service.html" target="_blank" rel="nofollow">广告合作</a> | <a href="http://www.it168.com//bottomfile/flgw/fl.htm" target="_blank" rel="nofollow">法律声明</a> | <a href="http://account.chinaunix.net/register?url=http%3a%2f%2fblog.chinaunix.net" target="_blank" rel="nofollow">免费注册</a>
      <p>Copyright  2001-2010 ChinaUnix.net All Rights Reserved 北京皓辰网域网络信息技术有限公司. 版权所有 </p>
      <div>感谢所有关心和支持过ChinaUnix的朋友们
        <p><a href="http://beian.miit.gov.cn/">16024965号-6 </a></p>
      </div>
    </div>
  </div>
</div>
<script language="javascript">

//全局错误提示弹出框
function showErrorMsg(content, title, url){
	var url = url || '';
	var title = title || '消息提示';
	var html = '';
	html += '<div class="HT_layer3_1 HT_layer3_2"><ul><li><p><span class="login_span1"></span>' + content + '</p></li>';
	if(url == '' || url.length == 0){
		html += '<li class="HT_li1"><input type="button" class="HT_btn2"  onclick=\'close_windows("error_msg")\'></li>';
	} else {
		html += '<li class="HT_li1"><input type="button" class="login_btn1" onclick="location.href=\'' + url + '\'"></li>';
	}
	html += '</ul></div>';
	$.cover(true);
	   asyncbox.open({
		 id: 'error_msg',
		 title : title,
		 html : html,
		 'callback' : function(action){
			 if(action == 'close'){
				 $.cover(false);
			 }
		 }
	});
}

//全局正确提示
function showSucceedMsg(content, title , url ){
	var url = url || '';
	var title = title || '消息提示';
	var html = '';
	html += '<div class="HT_layer3_1 HT_layer3_2"><ul><li><p><span class="login_span2"></span>' + content + '</p></li>';
	if(url == '' || url.length == 0){
		html += '<li class="HT_li1"><input type="button" class="HT_btn2"  onclick=\'close_windows("error_msg")\'></li>';
	} else {
		html += '<li class="HT_li1"><input type="button" class="HT_btn2" onclick="location.href=\'' + url + '\'"></li>';
	}
	html += '</ul></div>';
	$.cover(true);
	asyncbox.open({
		 id: 'error_msg',
		 title : title,
		 html : html,
		 'callback' : function(action){
			 if(action == 'close'){
				 $.cover(false);
			 }
		 }
	});
}

//关闭指定id的窗口
function close_windows(id){
	$.cover(false);
	$.close(id);
}


//公告
var tID;
var tn;                        // 高度
var nStopTime = 5000;        // 不同行间滚动时间隔的时间,值越小,移动越快
var nSpeed = 50;            // 滚动时,向上移动一像素间隔的时间,值越小,移动越快
var isMove = true;
var nHeight = 25;
var nS = 0;
var nNewsCount = 3;

/**
 * n 用于表示是否为第一次运行
 **/
function moveT(n)
{
    clearTimeout(tID)
    var noticev2 = document.getElementById("noticev2")
    nS = nSpeed;

    // 只在第一次调用时运行,初始化环境(有没有参数)
    if (n)
    {
        // 设置行高
        noticev2.style.lineHeight = nHeight + "px";
        // 初始化显示位置
        tn = 0;
        // 刚进入时在第一行停止时间
        nS = nStopTime;
    }

    // 判断鼠标是否指向层
    if (isMove)
    {
        // 向上移动一像素
        tn--;
        // 如果移动到最下面一行了,则移到顶行
        if (Math.abs(tn) == nNewsCount * nHeight)
        {
            tn = 0;
        }
        // 设置位置
        noticev2.style.marginTop = tn + "px";
        // 完整显示一行时,停止一段时间
        if (tn % nHeight == 0)
        {
            nS = nStopTime;
        }
    }

    tID = setTimeout("moveT()", nS);
}
moveT(1);    // 此处可以传入任何参数
</script>
<script type="text/javascript">
//  var _gaq = _gaq || [];
//  _gaq.push(['_setAccount', 'UA-20237423-2']);
//  _gaq.push(['_setDomainName', '.chinaunix.net']);
//  _gaq.push(['_trackPageview']);
//
//  (function() {
//    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
//    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
//    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
//  })();

</script>
<script type="text/javascript">
var _bdhmProtocol = (("https:" == document.location.protocol) ? " https://" : " http://");
document.write(unescape("%3Cscript src='" + _bdhmProtocol + "hm.baidu.com/h.js%3F0ee5e8cdc4d43389b3d1bfd76e83216b' type='text/javascript'%3E%3C/script%3E"));

function link(t){
     var href= $(t).attr('href');
     href+="?url="+encodeURIComponent(location.href);
     $(t).attr('href',href);
    //setCookie("returnOutUrl", location.href, 60, "/");
}
</script>
<script type="text/javascript" src="/js/jquery.qqFace.js"></script>
</body>
</html>