<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SNEEZRY</title>
	<atom:link href="http://sneezry.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://sneezry.com</link>
	<description>DEVELOPER&#039;S BLOG</description>
	<lastBuildDate>Mon, 30 Jan 2012 06:30:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>自我审查——无奈的举措</title>
		<link>http://sneezry.com/2012/01/%e8%87%aa%e6%88%91%e5%ae%a1%e6%9f%a5%e2%80%94%e2%80%94%e6%97%a0%e5%a5%88%e7%9a%84%e4%b8%be%e6%8e%aa/</link>
		<comments>http://sneezry.com/2012/01/%e8%87%aa%e6%88%91%e5%ae%a1%e6%9f%a5%e2%80%94%e2%80%94%e6%97%a0%e5%a5%88%e7%9a%84%e4%b8%be%e6%8e%aa/#comments</comments>
		<pubDate>Sun, 29 Jan 2012 20:35:59 +0000</pubDate>
		<dc:creator>sneezry</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[插件]]></category>

		<guid isPermaLink="false">http://sneezry.com/?p=725</guid>
		<description><![CDATA[好久未更新博客了，很是对不起大家。考研总算告一段落，前些天在忙另外一个项目，结果把CreQQ和博客都耽误了，我担心要是再不更新博客，恐怕这一亩三分地都被大家忘没了，于是今天凌晨果断加急发了这篇。 前一阵子在搞项目，于是免不了的要Google，虽然都是些技术问题，但不免还是时常触碰到天朝的G点，每到这个时候我都几乎要抓狂，因为在一段时间里就无法访问Google了，不得不说真这是一件*蛋的事！出于无奈，只好在客户端这边进行自我审查，于是我写了这款叫做Self Censorship（自我审查）的插件来协助判断Google所列出的结果是否已被和谐，如果已被和谐则提示用户不要点击。 此插件会随用户使用Google搜索时自动运行（SSL协议除外，因为此协议下不存在上述问题）。灰色代表正在进行检测，如果长时间显示为灰色，则表示此网站很可能被DNS污染，也有可能是服务器问题；绿色代表正常；橙色代表网页可能出现故障而不能显示，但其没有被屏蔽；红色代表此页面已被屏蔽，访问很可能会导致Google在一段时间内无法访问。 P.S 今晨此文发布匆忙，首版插件存在无法访问可能被屏蔽的链接的问题，新版插件已经修复，并已更新至Web App Store。]]></description>
			<content:encoded><![CDATA[<p>好久未更新博客了，很是对不起大家。考研总算告一段落，前些天在忙另外一个项目，结果把CreQQ和博客都耽误了，我担心要是再不更新博客，恐怕这一亩三分地都被大家忘没了，于是今天凌晨果断加急发了这篇。</p>
<p>前一阵子在搞项目，于是免不了的要Google，虽然都是些技术问题，但不免还是时常触碰到天朝的G点，每到这个时候我都几乎要抓狂，因为在一段时间里就无法访问Google了，不得不说真这是一件*蛋的事！出于无奈，只好在客户端这边进行自我审查，于是我写了这款叫做<a href="https://chrome.google.com/webstore/detail/lpgcnffkignjacipnkomllpppjpnojni">Self Censorship（自我审查）</a>的插件来协助判断Google所列出的结果是否已被和谐，如果已被和谐则提示用户不要点击。</p>
<p>此插件会随用户使用Google搜索时自动运行（SSL协议除外，因为此协议下不存在上述问题）。灰色代表正在进行检测，如果长时间显示为灰色，则表示此网站很可能被DNS污染，也有可能是服务器问题；绿色代表正常；橙色代表网页可能出现故障而不能显示，但其没有被屏蔽；红色代表此页面已被屏蔽，访问很可能会导致Google在一段时间内无法访问。</p>
<p>P.S 今晨此文发布匆忙，首版插件存在无法访问可能被屏蔽的链接的问题，新版插件已经修复，并已更新至Web App Store。</p>
<p><img class="alignnone size-full wp-image-726" title="Self Censorship" src="http://sneezry.com/wp-content/uploads/sneezry.com/2012/01/sc.png" alt="" width="561" height="655" /></p>
]]></content:encoded>
			<wfw:commentRss>http://sneezry.com/2012/01/%e8%87%aa%e6%88%91%e5%ae%a1%e6%9f%a5%e2%80%94%e2%80%94%e6%97%a0%e5%a5%88%e7%9a%84%e4%b8%be%e6%8e%aa/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>CreQQ代码详细解析</title>
		<link>http://sneezry.com/2011/11/creqq%e4%bb%a3%e7%a0%81%e8%af%a6%e7%bb%86%e8%a7%a3%e6%9e%90/</link>
		<comments>http://sneezry.com/2011/11/creqq%e4%bb%a3%e7%a0%81%e8%af%a6%e7%bb%86%e8%a7%a3%e6%9e%90/#comments</comments>
		<pubDate>Mon, 28 Nov 2011 10:37:40 +0000</pubDate>
		<dc:creator>sneezry</dc:creator>
				<category><![CDATA[技术]]></category>

		<guid isPermaLink="false">http://sneezry.com/?p=707</guid>
		<description><![CDATA[我想一定会有很多像我一样的人，想写出一款CreQQ类似的程序，无论是出于个人爱好还是技术研究的目的。在我准备写CreQQ这款程序的时候我也翻遍了整个互联网（当然有点夸张），都没有找到比较优秀的资源，所以，在我写出了这款基本还能用的程序之后，决定将我所努力得到的东西分享给大家。 写此类插件最难的莫过于协议，腾讯的协议一直很封闭，虽然有人已经通过抓包的方法摸清了Web QQ的协议，但愿意拿出来和大家共享的却不多，能把自己写好的程序拿出来并帮助大家进行分析的更是没有，这也更加激励我把这篇日志写完，当然我最终的目的就是希望那些和曾经的我一样在Google上苦苦寻找答案的人省些力气，不要因为找不到资料而泄气。 那么好了，言归正传，我们现在就开始窥探下CreQQ的秘密吧！请注意，CreQQ是用JavaScript语言编写的，对于JavaScript不是很熟悉的同学看起代码来可能会有些困难，不过我会用尽量详细的语言帮助大家进行分析的。 CreQQ的源码大家可以通过https://clients2.google.com/service/update2/crx?response=redirect&#38;x=id%3Dehgdacjejmbklleccjegbbaklhhoedlh%26uc下载（请不要使用Chrome浏览器，否则您无法得到文件，而会被直接安装）。您会得到一个后缀名为.crx的文件，将crx改为zip，之后解压缩即可得到CreQQ的源码。 其中background.html是我们今天要讲解的问题，其他的文件我们可以不去看。 涉及到WebQQ协议的部分，第一个执行的函数是check()函数。 function check(){ localStorage.webqqdetails = &#34;正在获取验证码……&#34;; chkbk(); chrome.browserAction.setBadgeBackgroundColor({&#34;color&#34;:[30,144,255,255]}); chrome.browserAction.setBadgeText({&#34;text&#34;:&#34;...&#34;}); islogin = 1; u = localStorage.webqqu; pw = localStorage.webqqp; if(u &#38;&#38; pw){ var url = &#34;http://ptlogin2.qq.com/check?appid=1003903&#38;uin=&#34;+u+&#34;&#38;r=&#34;+Math.random(); var el = document.createElement(&#34;script&#34;); el.setAttribute('src',url); document.body.appendChild(el); } else{ u = localStorage.webqqu; pw = localStorage.webqqp; setTimeout(check, 1000); } } .csharpcode, .csharpcode pre { font-size: small; [...]]]></description>
			<content:encoded><![CDATA[<p>我想一定会有很多像我一样的人，想写出一款CreQQ类似的程序，无论是出于个人爱好还是技术研究的目的。在我准备写CreQQ这款程序的时候我也翻遍了整个互联网（当然有点夸张），都没有找到比较优秀的资源，所以，在我写出了这款基本还能用的程序之后，决定将我所努力得到的东西分享给大家。</p>
<p>写此类插件最难的莫过于协议，腾讯的协议一直很封闭，虽然有人已经通过抓包的方法摸清了Web QQ的协议，但愿意拿出来和大家共享的却不多，能把自己写好的程序拿出来并帮助大家进行分析的更是没有，这也更加激励我把这篇日志写完，当然我最终的目的就是希望那些和曾经的我一样在Google上苦苦寻找答案的人省些力气，不要因为找不到资料而泄气。</p>
<p>那么好了，言归正传，我们现在就开始窥探下CreQQ的秘密吧！请注意，CreQQ是用JavaScript语言编写的，对于JavaScript不是很熟悉的同学看起代码来可能会有些困难，不过我会用尽量详细的语言帮助大家进行分析的。</p>
<p>CreQQ的源码大家可以通过<a title="https://clients2.google.com/service/update2/crx?response=redirect&amp;x=id%3Dehgdacjejmbklleccjegbbaklhhoedlh%26uc" href="https://clients2.google.com/service/update2/crx?response=redirect&amp;x=id%3Dehgdacjejmbklleccjegbbaklhhoedlh%26uc">https://clients2.google.com/service/update2/crx?response=redirect&amp;x=id%3Dehgdacjejmbklleccjegbbaklhhoedlh%26uc</a>下载（请不要使用Chrome浏览器，否则您无法得到文件，而会被直接安装）。您会得到一个后缀名为.crx的文件，将crx改为zip，之后解压缩即可得到CreQQ的源码。</p>
<p>其中background.html是我们今天要讲解的问题，其他的文件我们可以不去看。</p>
<p>涉及到WebQQ协议的部分，第一个执行的函数是check()函数。</p>
<pre class="csharpcode"><span class="kwrd">function</span> check(){
    localStorage.webqqdetails = <span class="str">&quot;正在获取验证码……&quot;</span>;
    chkbk();
    chrome.browserAction.setBadgeBackgroundColor({<span class="str">&quot;color&quot;</span>:[30,144,255,255]});
    chrome.browserAction.setBadgeText({<span class="str">&quot;text&quot;</span>:<span class="str">&quot;...&quot;</span>});
    islogin = 1;
    u = localStorage.webqqu;
    pw = localStorage.webqqp;
    <span class="kwrd">if</span>(u &amp;&amp; pw){
        <span class="kwrd">var</span> url = <span class="str">&quot;http://ptlogin2.qq.com/check?appid=1003903&amp;uin=&quot;</span>+u+<span class="str">&quot;&amp;r=&quot;</span>+Math.random();
        <span class="kwrd">var</span> el = document.createElement(<span class="str">&quot;script&quot;</span>);
        el.setAttribute(<span class="str">'src'</span>,url);
        document.body.appendChild(el);
    }
    <span class="kwrd">else</span>{
        u = localStorage.webqqu;
        pw = localStorage.webqqp;
        setTimeout(check, 1000);
    }
}</pre>
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>上面就是check函数的全部源码。此函数的核心功能就是得到u和pw这两个变量后，动态创建一个src为“http://ptlogin2.qq.com/check?appid=1003903&amp;uin=<strong>u</strong>&amp;r=随机数”这样的一个script标签。通过引用前述的url后，腾讯服务器会返回诸如 ptui_checkVC(&#8217;0&#8242;,&#8217;!6SG&#8217;); 的响应，其中第一个参数可能是0也可能是1，如果是0表示不用验证，第二个参数，即!6SG就是验证码，如果第一个参数是1，代表需要进行验证，并且第二个参数是验证码相关信息，这个判断过程我们是通过ptui_checkVC()函数处理的。</p>
<pre class="csharpcode"><span class="kwrd">function</span> ptui_checkVC(c, vc){
    localStorage.webqqdetails = <span class="str">&quot;正在获取验证状态……&quot;</span>;
    <span class="kwrd">if</span>(<span class="str">&quot;0&quot;</span> == c){
        vi = 0;
        v = vc;
        l();
    }
    <span class="kwrd">else</span>{
        vi = 1;
        chrome.browserAction.setBadgeText({<span class="str">&quot;text&quot;</span>:<span class="str">&quot;v&quot;</span>});
        localStorage.webqqi = <span class="str">&quot;http://captcha.qq.com/getimage?aid=1002101&amp;r=&quot;</span>+Math.random()+<span class="str">&quot;&amp;uin=&quot;</span>+u+<span class="str">&quot;&amp;vc_type=&quot;</span>+vc;
        getcaps();
    }
}</pre>
<p>上面即为ptui_checkVC函数的全部源码。当上部调用的url返回的第一个参数为0时，我们进入下一步，调用l()函数，否则显示图片“http://captcha.qq.com/getimage?aid=1002101&amp;r=随机数&amp;uin=u&amp;vc_type=验证码相关信息”。并将用户输入的验证码备用。</p>
<pre class="csharpcode"><span class="kwrd">function</span> l(){
    localStorage.webqqdetails = <span class="str">&quot;正在登录到腾讯服务器……&quot;</span>;
    chrome.browserAction.setBadgeText({<span class="str">&quot;text&quot;</span>:<span class="str">&quot;...&quot;</span>});
    <span class="kwrd">if</span>(vi){
        v = localStorage.webqqs;
        localStorage.webqqs = <span class="str">&quot;&quot;</span>;
    }
    <span class="kwrd">var</span> p = md5(pw + v.toUpperCase());
    <span class="kwrd">if</span>(Number(localStorage.webqqsettings.split(<span class="str">&quot;;&quot;</span>)[0])){
        chrome.browserAction.setIcon({path:(Number(localStorage.webqqsettings.split(<span class="str">&quot;;&quot;</span>)[7])?<span class="str">&quot;gmail&quot;</span>:<span class="str">&quot;qq&quot;</span>) + <span class="str">&quot;_hd.png&quot;</span>});
    }
    <span class="kwrd">else</span>{
        chrome.browserAction.setIcon({path:(Number(localStorage.webqqsettings.split(<span class="str">&quot;;&quot;</span>)[7])?<span class="str">&quot;gmail&quot;</span>:<span class="str">&quot;qq&quot;</span>) + <span class="str">&quot;_on.png&quot;</span>});
    }
    <span class="kwrd">var</span> url = <span class="str">&quot;http://ptlogin2.qq.com/login?&quot;</span>+(Number(localStorage.webqqsettings.split(<span class="str">&quot;;&quot;</span>)[0])?<span class="str">&quot;&quot;</span>:<span class="str">&quot;h=1&amp;&quot;</span>)+<span class="str">&quot;u=&quot;</span>+u+<span class="str">&quot;&amp;p=&quot;</span>+p+<span class="str">&quot;&amp;verifycode=&quot;</span>+v+<span class="str">&quot;&amp;webqq_type=1&amp;remember_uin=1&amp;aid=1002101&amp;u1=http%3A%2F%2Fw.qq.com%2Fmain.shtml%3F816&amp;h=1&amp;ptredirect=1&amp;ptlang=2052&amp;from_ui=1&amp;pttype=1&amp;dumy=&amp;fp=loginerroralert&amp;action=5-37-424199&amp;mibao_css=&quot;</span>;
    <span class="kwrd">var</span> el = document.createElement(<span class="str">&quot;script&quot;</span>);
    el.setAttribute(<span class="str">'src'</span>,url);
    document.body.appendChild(el);
}</pre>
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>上面的就是l()函数的全部源码。核心作用是调用<font color="#222222">“</font>http://ptlogin2.qq.com/login?u=<strong>u</strong>&amp;p=<strong>p</strong>&amp;verifycode=<strong>v</strong>&amp;webqq_type=1&amp;remember_uin=1&amp;aid=1002101&amp;u1=http%3A%2F%2Fw.qq.com%2Fmain.shtml%3F816&amp;h=1&amp;ptredirect=1&amp;ptlang=2052&amp;from_ui=1&amp;pttype=1&amp;dumy=&amp;fp=loginerroralert&amp;action=5-37-424199&amp;mibao_css=”。其中u是用户名，p是用户密码明码经过md5加密后的密码pw与验证码全大写后进行拼接得到的字符串再次进行md5加密后得到的。v是验证码。如果是在线登录，需要在上面的url后添加&amp;h=1，如果没有这个参数将是隐身登录。</p>
<p>如果腾讯服务器接受登录，将返回诸如 ptuiCB(&#8217;0&#8242;,&#8217;0&#8242;,&#8217;http://w.qq.com/main.shtml?816&#8242;,&#8217;1&#8242;,&#8217;登录成功！&#8217;); 的响应，表示登录成功，否则会在第五个参数提示错误信息。</p>
<p>下面我们就将开始拉取数据了。首先我们开始获取cookies，我们分别需要获取到ptwebqq、skey和uin这三个cookies。虽然在用户登录时已经输入了帐号，但是如果用户输入的是邮箱地址，我们需要通过uin这个cookies获取用户对应的QQ号码。并将uin作为u的值。</p>
<p>获取完cookies后我们就要开始获取web_session。向 http://web-proxya.qq.com/conn_s POST数据，数据为“ u;22;0;00000000;skey;ptwebqq;0; ”，服务器返回一长串以分号相隔的数据，而五个数据即为web_session，将其保存好，后面会用到。</p>
<p>然后我们开始获取分组信息。向 http://web-proxya.qq.com/conn_s POST数据，数据为“u;3c;0;web_session;1;”。服务器返回诸如“545251277;3c;0;09;0;My Friends;1;middle school;2;high school;3;SNAIL Society;4;Same School;5;net &amp; nyt;6;university;7;秘书部;8;Ppl can C me;”的响应，第一个数据是用户QQ帐号，第四个数据是用户QQ帐号好友的分组数目，从第五个开始，是序号和组名。需要注意的是，如果用户只有一个“我的好友”分组，第四个数字将是0。</p>
<p>之后我们开始获取好友信息。向 http://web-proxya.qq.com/conn_s POST数据，数据为“u;58;0;web_session;s;”，其中u为用户QQ号码，s为从哪个好友开始获取，因为一次获取不全，需要多次获取。CreQQ此处相应的函数为getfriends()函数，其完整源码如下所示。</p>
<pre class="csharpcode"><span class="kwrd">function</span> getfriends(s,l,m){
    localStorage.webqqdetails = <span class="str">&quot;正在获取好友信息……&quot;</span>;
    <span class="kwrd">var</span> xhr = <span class="kwrd">new</span> XMLHttpRequest();
    content = u+<span class="str">&quot;;58;0;&quot;</span>+web_session+<span class="str">&quot;;&quot;</span>+s+<span class="str">&quot;;&quot;</span>;
    xhr.open(<span class="str">&quot;POST&quot;</span>, <span class="str">&quot;http://web-proxya.qq.com/conn_s&quot;</span>, <span class="kwrd">true</span>);
    xhr.onreadystatechange = <span class="kwrd">function</span>() {
      <span class="kwrd">if</span> (xhr.readyState == 4) {
        <span class="kwrd">var</span> gtmp = xhr.responseText.split(<span class="str">&quot;;&quot;</span>);
        <span class="kwrd">var</span> j=l;
        <span class="kwrd">var</span> k=m;
        <span class="kwrd">for</span>(i=4; i&lt;gtmp.length-1; i+=4){
            <span class="kwrd">if</span>(<span class="str">&quot;0&quot;</span> == gtmp[i+1]){
                friends[j]=gtmp[i];
                fgroup[j] = (Number(gtmp[i+2])&amp;60)&gt;&gt;2;
                j++;
            }
            <span class="kwrd">else</span>{
                qun[k]=[];
                qun[k].id=gtmp[i];
                qun[k].qn=<span class="str">&quot;&quot;</span>;
                qun[k].nm=<span class="str">&quot;&quot;</span>;
                k++;
            }
        }
        localStorage.webqqlog += <span class="str">&quot;3] &quot;</span>+xhr.responseText+<span class="str">&quot;&lt;br /&gt;&quot;</span>;
        <span class="kwrd">if</span>(0==Number(gtmp[3]))
            step = 3;
        <span class="kwrd">else</span>
            getfriends(Number(gtmp[3]),j,k);
      }
    }
    xhr.send(content);
}</pre>
<p>服务器返回诸如“545251277;58;0;739650251;1686331;0;4;20;4366143;0;0;20;5081492;0;20;20;6029847;0;33;20;……”的响应，其中第四个数据为下一次从哪个好友开始获取，从第五个数据开始，每四个数据为一组，每组数据中，第一个如果是QQ好友就为好友QQ号码，如果是群就为群id（注意不是群号）；第二个数据，为0代表是好友，为1代表是群；第三个数据是好友所在分组序号，不过这个序号不是真正的分组序号，需要与60按位与，之后右移两位，即原始数据若为n，计算后的数据应该是(n&amp;60)&gt;&gt;2。</p>
<p>之后我们就可以获取在线好友了，向 http://web-proxya.qq.com/conn_s POST数据，数据为“u;26;0;web_session;0;0;”，服务器返回诸如“545251277;81;1;521050918;10;545251277;81;2;545044875;10;……”的响应，每五个数据为一组，需要注意的是，不是每个数据都一定是在线好友信息，我们需要对每组数据的第二个数据进行判断，只有是81时才代表此数据是好友在线信息。其中第四个数据就是在线好友的QQ号码。</p>
<p>此功能CreQQ使用getonline()函数实现，此函数完整代码如下。</p>
<pre class="csharpcode"><span class="kwrd">function</span> getonline(){
    localStorage.webqqdetails = <span class="str">&quot;正在获取在线好友信息……&quot;</span>;
    <span class="kwrd">var</span> xhr = <span class="kwrd">new</span> XMLHttpRequest();
    content = u+<span class="str">&quot;;26;0;&quot;</span>+web_session+<span class="str">&quot;;0;0;&quot;</span>;
    xhr.open(<span class="str">&quot;POST&quot;</span>, <span class="str">&quot;http://web-proxya.qq.com/conn_s&quot;</span>, <span class="kwrd">true</span>);
    xhr.onreadystatechange = <span class="kwrd">function</span>() {
      <span class="kwrd">if</span> (xhr.readyState == 4) {
        <span class="kwrd">var</span> gtmp = xhr.responseText.split(<span class="str">&quot;;&quot;</span>);
        <span class="kwrd">var</span> j=0;
        <span class="kwrd">var</span> i;
        <span class="kwrd">for</span>(i=0; i&lt;gtmp.length-1; i+=5){
            <span class="kwrd">if</span>(gtmp[1] == <span class="str">&quot;81&quot;</span>){
                online[j] = gtmp[i+3];
                j++;
            }
        }
        localStorage.webqqlog += <span class="str">&quot;4] &quot;</span>+xhr.responseText+<span class="str">&quot;&lt;br /&gt;&quot;</span>;
        step = 4;
      }
    }
    xhr.send(content);
}</pre>
<p>接下来我们开始获取好友昵称。继续向 http://web-proxya.qq.com/conn_s POST数据，数据为“u;26;0;web_session;0;0;”，请注意，这里POST的数据没有错误，确实和获取在线好友时POST的数据完全一样。和获取QQ好友时一样，服务器一次可能无法将所有信息传递完，此时需要进行多次请求。服务器返回诸如“545251277;26;0;50;1686331;297;21;0;逆袭(*□д`*;1;4366143;381;25;0;▓小·魚;0;5081492;663;2;0;地狱战狂;0;6029847;0;22;0;长空√铁翼;0;……”的响应，其中第4个数据代表下次从第几个好友开始请求，如果为0则表示获取完毕。从第五个数据开始，每6个数据为一组，每组中第一个数据为好友QQ号码，第五个数据为好友昵称。</p>
<p>这里需要注意的是，腾讯服务器会将每个数据都发送两边，可能是考虑到保证信息传递成功率吧。CreQQ完成此功能的函数是getfriendsinfo()，其完整源码如下所示。</p>
<pre class="csharpcode"><span class="kwrd">function</span> getfriendsinfo(s,l){
    localStorage.webqqdetails = <span class="str">&quot;正在获取好友昵称……&quot;</span>;
    <span class="kwrd">var</span> xhr = <span class="kwrd">new</span> XMLHttpRequest();
    content = u+<span class="str">&quot;;26;0;&quot;</span>+web_session+<span class="str">&quot;;&quot;</span>+s+<span class="str">&quot;;0;&quot;</span>;
    xhr.open(<span class="str">&quot;POST&quot;</span>, <span class="str">&quot;http://web-proxya.qq.com/conn_s&quot;</span>, <span class="kwrd">true</span>);
    xhr.onreadystatechange = <span class="kwrd">function</span>() {
      <span class="kwrd">if</span> (xhr.readyState == 4) {
        <span class="kwrd">var</span> gtmp = xhr.responseText.split(<span class="str">&quot;;&quot;</span>);
        <span class="kwrd">var</span> j=l;
        <span class="kwrd">var</span> i;
        <span class="kwrd">for</span>(i=4; i&lt;gtmp.length-1; i+=6){
            nickqq[j] = gtmp[i];
            nickname[j] = gtmp[i+4];
            j++;
        }
        localStorage.webqqlog += <span class="str">&quot;5] &quot;</span>+xhr.responseText+<span class="str">&quot;&lt;br /&gt;&quot;</span>;
        <span class="kwrd">if</span>(0==Number(gtmp[3]))
            step = 5;
        <span class="kwrd">else</span>
            getfriendsinfo(Number(gtmp[3]),j);
      }
    }
    xhr.send(content);
}</pre>
<p>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>在获取完好友昵称后，我们需要获取用户对好友标注的注释，向 http://web-proxya.qq.com/conn_s POST数据，数据为“u;3e;0;web_session;4;s;”其中s为下一次从哪里开始获取，当然还是因为服务器不能一次将所有信息返回。服务器返回如下响应“545251277;3e;0;4;1;5081492;0;XD同学;26990152;0;魔方;80554933;0;陈伯洋;81263051;0;索老师;117163304;0;雒唯;……”其中第五个数据表示下一次从哪里开始获取，如果为0则表示获取完毕。从第6个数据开始，每3个为一组，第一个数据为好友QQ号码，第三个为好友昵称。</p>
<p>CreQQ通过getmark()函数完成上述过程，其完整代码如下。</p>
<pre class="csharpcode"><span class="kwrd">function</span> getmark(s,l){
    localStorage.webqqdetails = <span class="str">&quot;正在获取好友备注……&quot;</span>;
    <span class="kwrd">var</span> xhr = <span class="kwrd">new</span> XMLHttpRequest();
    content = u+<span class="str">&quot;;3e;0;&quot;</span>+web_session+<span class="str">&quot;;4;&quot;</span>+s+<span class="str">&quot;;&quot;</span>;
    xhr.open(<span class="str">&quot;POST&quot;</span>, <span class="str">&quot;http://web-proxya.qq.com/conn_s&quot;</span>, <span class="kwrd">true</span>);
    xhr.onreadystatechange = <span class="kwrd">function</span>() {
      <span class="kwrd">if</span> (xhr.readyState == 4) {
        <span class="kwrd">var</span> gtmp = xhr.responseText.split(<span class="str">&quot;;&quot;</span>);
        <span class="kwrd">if</span>(<span class="str">&quot;3e&quot;</span>==gtmp[1]){
               <span class="kwrd">var</span> j=l;
               <span class="kwrd">var</span> i;
               <span class="kwrd">for</span>(i=5; i&lt;gtmp.length-1; i+=3){
                markname[j] = gtmp[i+2];
                markqq[j] = gtmp[i];
                j++;
            }
            localStorage.webqqlog += <span class="str">&quot;6] &quot;</span>+xhr.responseText+<span class="str">&quot;&lt;br /&gt;&quot;</span>;
            <span class="kwrd">if</span>(0==Number(gtmp[4])){
                step = 6;
            }
            <span class="kwrd">else</span>{
                getmark(s+1,j);
            }
        }
        <span class="kwrd">else</span>{
            getmark(0,0);
        }
      }
    }
    xhr.send(content);
}</pre>
<p>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>接下来我们开始获取群信息。向 http://web-proxya.qq.com/conn_s POST数据，数据为“u;30;0;web_session;72;q;0;”，其中q为群id，这个信息我们在获取好友信息时已经获取到，服务器返回诸如“545251277;30;0;72;2144613258;64613258;1;0;545251277;Snail活动计划;1月27日中午12点新千里烤肉不见不散（百度被pass了~）。聚会带好学生证，看电影凭学生证有优惠。;Sorry, this group is disallowed to be joined.;0;1851747632;87491030;20;0;0;117163304;20;0;1;124415910;20;0;0;174053188;20;0;0;273214505;20;0;0;290017418;20;0;0;304480723;20;0;0;331737201;20;0;0;378539454;20;0;0;408359572;20;0;0;493390039;20;0;0;545251277;20;0;0;740074342;20;0;1;741389790;20;0;1;805957574;20;0;0;1033471702;20;0;0;1364088792;20;0;0;1851747632;20;0;0;”的响应，其中第六个数据为群号，第10个数据为群名，第9个数据为创建者QQ号，第11个数据为群公告，第12个数据为群介绍，从第15个数据开始，每4个为一组，第一个为成员QQ号码。需要注意的是，服务器返回的响应有时和我们请求的数据不符，即我们请求的是id为A的群信息，而服务器返回的确实B的信息，因为这样，我们需要对信息进行验证。</p>
<p>CreQQ使用getquninfo()和quninfo()两个函数完成上述过程，完整代码如下。</p>
<pre class="csharpcode"><span class="kwrd">function</span> getquninfo(){
    localStorage.webqqdetails = <span class="str">&quot;正在获取群信息……&quot;</span>;
    <span class="kwrd">var</span> k;
    <span class="kwrd">for</span>(k=0;k&lt;qun.length;k++){
        quninfo(qun[k].id,k);
    }
    step = 7;
}

<span class="kwrd">function</span> quninfo(q,k){
    <span class="kwrd">if</span>(qun[k].qn){
        <span class="kwrd">return</span>;
    }
    <span class="kwrd">var</span> xhr = <span class="kwrd">new</span> XMLHttpRequest();
    content = u+<span class="str">&quot;;30;0;&quot;</span>+web_session+<span class="str">&quot;;72;&quot;</span>+q+<span class="str">&quot;;0;&quot;</span>;
    xhr.open(<span class="str">&quot;POST&quot;</span>, <span class="str">&quot;http://web-proxya.qq.com/conn_s&quot;</span>, <span class="kwrd">true</span>);
    xhr.onreadystatechange = <span class="kwrd">function</span>() {
      <span class="kwrd">if</span> (xhr.readyState == 4) {
        <span class="kwrd">var</span> gtmp = xhr.responseText.split(<span class="str">&quot;;&quot;</span>);
        <span class="kwrd">if</span>(gtmp[1]==30 &amp;&amp; gtmp[4]==q){
            qun[k].qn = gtmp[5];
              qun[k].nm = gtmp[9];
              localStorage.webqqlog += <span class="str">&quot;7] &quot;</span>+k+<span class="str">&quot; - &quot;</span>+qun[k].qn+<span class="str">&quot; - &quot;</span>+qun[k].nm+<span class="str">&quot;&lt;br /&gt;&quot;</span>;
              localStorage.webqqqun += qun[k].id+<span class="str">&quot;;&quot;</span>+encodeURIComponent(qun[k].qn)+<span class="str">&quot;;&quot;</span>+qun[k].nm+<span class="str">&quot;;;&quot;</span>;
          }
          <span class="kwrd">else</span>{
              <span class="kwrd">var</span> i;
              <span class="kwrd">for</span>(i=0;i&lt;qun.length;i++){
                  <span class="kwrd">if</span>(qun[i].id==gtmp[4] &amp;&amp; !qun[i].qn){
                      qun[i].qn = gtmp[5];
                      qun[i].nm = gtmp[9];
                      localStorage.webqqlog += <span class="str">&quot;7] &quot;</span>+i+<span class="str">&quot; - &quot;</span>+qun[i].qn+<span class="str">&quot; - &quot;</span>+qun[i].nm+<span class="str">&quot;&lt;br /&gt;&quot;</span>;
                      localStorage.webqqqun += qun[i].id+<span class="str">&quot;;&quot;</span>+encodeURIComponent(qun[i].qn)+<span class="str">&quot;;&quot;</span>+qun[i].nm+<span class="str">&quot;;;&quot;</span>;
                  }
              }
              <span class="kwrd">if</span>(!qun[k].qn){
                  quninfo(q,k);
              }
          }
      }
    }
    xhr.send(content);
}</pre>
<p>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>至此，全部数据我们拉取完毕，接下来CreQQ对数据进行了格式化，即将数据转换为JSON格式，CreQQ转换的格式为：</p>
<pre class="csharpcode">[{<span class="str">&quot;groupid&quot;</span>:groupid,<span class="str">&quot;groupname&quot;</span>:groupname,<span class="str">&quot;friends&quot;</span>:[{<span class="str">&quot;name&quot;</span>:name,<span class="str">&quot;qq&quot;</span>:qq,<span class="str">&quot;online&quot;</span>:<span class="str">&quot;1/0&quot;</span>},……]},……]</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>将数据格式化完毕后，我们开始向腾讯服务器发送“心跳包”，一方面及时得到最新消息和上下线状态，一方面告诉服务器用户在线，不要断开连接。</p>
<p>“心跳包”的发送方法为向 http://web-proxya.qq.com/conn_s POST数据，数据为“u;00;msgid;web_session;”，其中msgid为指令序号，从第一个指令开始为1，依次增加。服务器返回数据格式较多，所有我们分开讨论。如果返回的数据第二个数据为01，表示用户掉线；如果第二个数据为81，表示用户上下线状态，其中第5个数据是10表示上线，否则表示下线，第4个数据是相关好友QQ号码。如果第二个数据为17，且第4个数据不是10000，且第6个数据不是30，那么其为新消息，如果第4个数据是10000，且第6个数据是30表示用户异地登录，被迫下线。如果服务器返回数据为新消息，则如果第6个数据为09，表示好友消息，否则表示群消息。其中第3个数据为消息验证信息A，第5个数据为消息验证信息B，第8个数据为信息内容，第4个为发送信息的好友QQ号码，如果是群则是群id，如果是好友消息，第9个数据是消息发送时间，如果是群消息，第14个数据为消息发送时间。如果是好友消息，第10个数据是消息验证信息C，如果是群消息，第15个数据是消息验证信息C，消息验证信息我们在反馈服务器信息时要用到。</p>
<p>当我们受到消息后需要告知服务器接收成功，即我们需要发送反馈信息。反馈信息的发送方法为向 http://web-proxya.qq.com/conn_s POST数据，数据为“u;17;a;web_session;b;u;c;e;d;”，其中a为消息验证信息A，b为发送信息的QQ号或群id，c为验证信息B，d为验证信息C，如果是好友消息，e为1，如果是群消息，e为3。</p>
<p>至此“心跳包”结束，CreQQ对此处的编写使用了大量篇幅，分别使用了pulld()函数发送“心跳包”、setst()函数更改好友在线状态、callbackm()函数发送信息接收反馈信息。这三个函数的完整代码如下。</p>
<pre class="csharpcode">function pulld(){
    <span class="kwrd">if</span>(localStorage.webqqb){
        localStorage.webqqb = <span class="str">&quot;&quot;</span>;
        localStorage.webqqbr = <span class="str">&quot;true&quot;</span>;
        logout();
        <span class="kwrd">return</span>;
    }
    <span class="kwrd">else</span>{
        var xhr = <span class="kwrd">new</span> XMLHttpRequest();
        content = u+<span class="str">&quot;;00;&quot;</span>+msgid+<span class="str">&quot;;&quot;</span>+web_session+<span class="str">&quot;;&quot;</span>;
        msgid++;
        xhr.open(<span class="str">&quot;POST&quot;</span>, <span class="str">&quot;http://web-proxya.qq.com/conn_s&quot;</span>, <span class="kwrd">true</span>);
        xhr.onreadystatechange = function() {
          <span class="kwrd">if</span> (xhr.readyState == 4) {
              <span class="kwrd">if</span>(xhr.responseText){
                var gtmpp = xhr.responseText.split(u+<span class="str">&quot;;&quot;</span>);
                var i;
                <span class="kwrd">for</span>(i=1;i&lt;gtmpp.length;i++){
                    var gtmp = gtmpp[i].split(<span class="str">&quot;;&quot;</span>);
                    <span class="kwrd">if</span>(gtmp[0]==<span class="str">&quot;01&quot;</span>){
                        chrome.browserAction.setBadgeBackgroundColor({<span class="str">&quot;color&quot;</span>:[128,128,128,255]});
                            chrome.browserAction.setBadgeText({<span class="str">&quot;text&quot;</span>:<span class="str">&quot;Off&quot;</span>});
                            chrome.browserAction.setIcon({path:(Number(localStorage.webqqsettings.split(<span class="str">&quot;;&quot;</span>)[7])?<span class="str">&quot;gmail&quot;</span>:<span class="str">&quot;qq&quot;</span>) + <span class="str">&quot;_off.png&quot;</span>});
                            chrome.browserAction.setTitle({title:<span class="str">&quot;CreQQ&quot;</span>});
                            <span class="rem">//alert(&quot;由于网络原因，您已离线，请稍后重新登录。&quot;);</span>
                            localStorage.webqqrelog = <span class="str">&quot;true&quot;</span>;
                            localStorage.webqqbr = <span class="str">&quot;true&quot;</span>;
                            window.location.reload();
                        <span class="kwrd">return</span>;
                    }
                    <span class="kwrd">else</span> <span class="kwrd">if</span>(gtmp[0]==<span class="str">&quot;17&quot;</span>){
                        <span class="kwrd">if</span>(<span class="str">&quot;10000&quot;</span>==gtmp[2] &amp;&amp; <span class="str">&quot;30&quot;</span>==gtmp[4]){
                            chrome.browserAction.setBadgeBackgroundColor({<span class="str">&quot;color&quot;</span>:[128,128,128,255]});
                                chrome.browserAction.setBadgeText({<span class="str">&quot;text&quot;</span>:<span class="str">&quot;Off&quot;</span>});
                                chrome.browserAction.setIcon({path:(Number(localStorage.webqqsettings.split(<span class="str">&quot;;&quot;</span>)[7])?<span class="str">&quot;gmail&quot;</span>:<span class="str">&quot;qq&quot;</span>) + <span class="str">&quot;_off.png&quot;</span>});
                                chrome.browserAction.setTitle({title:<span class="str">&quot;CreQQ&quot;</span>});
                            alert(<span class="str">&quot;您的帐号在另一地点登录，您被迫下线。\n\n如果这不是您本人的操作，那么您的密码很可能已经泄漏。建议您修改密码。&quot;</span>);
                            localStorage.webqqbr = <span class="str">&quot;true&quot;</span>;
                            window.location.reload();
                            <span class="kwrd">return</span>;
                        }
                        var rep = 0;
                        var msg = gtmp[6];
                        var qq = gtmp[2];
                        var qr = (gtmp[4]==<span class="str">&quot;09&quot;</span>?1:3);
                        var qe = (gtmp[4]==<span class="str">&quot;09&quot;</span>?gtmp[8]:gtmp[13]);
                        callbackm(gtmp[1],gtmp[2],gtmp[3],qe,qr);

                        var g = localStorage.webqqg.split(<span class="str">&quot;;&quot;</span>);
                        var j;
                        <span class="kwrd">for</span>(j=0; j&lt;g.length-1; j++){
                            <span class="kwrd">if</span>(g[j] == gtmp[1]){
                                rep = 1;
                                <span class="kwrd">break</span>;
                            }
                        }
                        <span class="kwrd">if</span>(!rep){
                            <span class="kwrd">if</span>(gtmp[4]==<span class="str">&quot;09&quot;</span>){
                                <span class="kwrd">if</span>(!Number(localStorage.webqqsettings.split(<span class="str">&quot;;&quot;</span>)[5])){
                                    document.getElementById(<span class="str">'mr'</span>).play();
                                }
                                var tim = gtmp[7];
                                var a = qq+<span class="str">&quot;;&quot;</span>+encodeURIComponent(msg)+<span class="str">&quot;;&quot;</span>+tim+<span class="str">&quot;;;&quot;</span>;
                                var h = qq+<span class="str">&quot;;0;&quot;</span>+encodeURIComponent(msg)+<span class="str">&quot;;&quot;</span>+tim+<span class="str">&quot;;;&quot;</span>;
                                localStorage.webqqc += a;
                                localStorage.webqqh += h;

                                <span class="kwrd">if</span>(localStorage.webqqsettings.split(<span class="str">&quot;;&quot;</span>)[2] &amp;&amp; !Number(localStorage.webqqsettings.split(<span class="str">&quot;;&quot;</span>)[0])){
                                    var t = <span class="kwrd">new</span> Date();
                                    var msgt = localStorage.webqqsettings.split(<span class="str">&quot;;&quot;</span>)[2].split(<span class="str">&quot;%25r&quot;</span>);
                                    var msgtt = msgt[0];
                                    var k;
                                    <span class="kwrd">for</span>(k=1; k&lt;msgt.length; k++){
                                        msgtt += msg + msgt[k];
                                    }
                                    tim = Math.floor(t.getTime()/1000);
                                    h = qq+<span class="str">&quot;;1;&quot;</span>+msgtt+<span class="str">&quot;;&quot;</span>+tim+<span class="str">&quot;;;&quot;</span>;
                                        localStorage.webqqh += h;
                                        ssmsg(qq,msgtt);
                                }
                            }
                            <span class="kwrd">else</span>{
                                showqunm(<span class="str">&quot;q&quot;</span>+qq,gtmp[9],msg,gtmp[12]);
                                <span class="rem">/*</span>
<span class="rem">                                var tim = gtmp[12];</span>
<span class="rem">                                var a = &quot;{\&quot;qq\&quot;:\&quot;q&quot;+qq+&quot;\&quot;,\&quot;msg\&quot;:\&quot;&quot;+gtmp[9]+&quot;: &quot;+encodeURIComponent(msg)+&quot;\&quot;,\&quot;tim\&quot;:\&quot;&quot;+tim+&quot;\&quot;};&quot;;</span>
<span class="rem">                                var h = &quot;{\&quot;qq\&quot;:\&quot;q&quot;+qq+&quot;\&quot;,\&quot;u\&quot;:\&quot;0\&quot;,\&quot;msg\&quot;:\&quot;&quot;+gtmp[9]+&quot;: &quot;+encodeURIComponent(msg)+&quot;\&quot;,\&quot;tim\&quot;:\&quot;&quot;+tim+&quot;\&quot;};&quot;;</span>
<span class="rem">                                */</span>
                            }
                            localStorage.webqqg += gtmp[1] + <span class="str">&quot;;&quot;</span>;
                            freshbadge();
                        }
                    }
                    <span class="kwrd">else</span> <span class="kwrd">if</span>(gtmp[0]==<span class="str">&quot;81&quot;</span>){
                        <span class="kwrd">if</span>(gtmp[3]==<span class="str">&quot;10&quot;</span>){
                            setst(gtmp[2],1);
                        }
                        <span class="kwrd">else</span>{
                            setst(gtmp[2],0);
                        }
                    }
                }
            }
            setTimeout(pulld, 2000);
          }
        }
        xhr.send(content);
    }
}

function callbackm(a,b,c,d,e){
    var xhr = <span class="kwrd">new</span> XMLHttpRequest();
    content = u+<span class="str">&quot;;17;&quot;</span>+a+<span class="str">&quot;;&quot;</span>+web_session+<span class="str">&quot;;&quot;</span>+b+<span class="str">&quot;;&quot;</span>+u+<span class="str">&quot;;&quot;</span>+c+<span class="str">&quot;;&quot;</span>+e+<span class="str">&quot;;&quot;</span>+d+<span class="str">&quot;;&quot;</span>;
    msgid++;
    xhr.open(<span class="str">&quot;POST&quot;</span>, <span class="str">&quot;http://web-proxya.qq.com/conn_s&quot;</span>, <span class="kwrd">true</span>);
    <span class="rem">/*</span>
<span class="rem">    xhr.onreadystatechange = function() {</span>
<span class="rem">      if (xhr.readyState == 4) {</span>
<span class="rem">          alert(1);</span>
<span class="rem">      }</span>
<span class="rem">    }</span>
<span class="rem">    */</span>
    xhr.send(content);
}</pre>
<p>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>上述代码中的pull()函数调用了showqunm()函数，此函数的作用是获取群消息的发送者昵称。这部分函数比较简单，我就不做详细分析了，大家看一下代码就能看懂。此函数的完整代码如下。</p>
<pre class="csharpcode"><span class="kwrd">function</span> showqunm(qq,sq,msg,tim){
    <span class="kwrd">var</span> i;
    <span class="kwrd">var</span> sqp = sqa.split(<span class="str">&quot;;;&quot;</span>);
    <span class="kwrd">for</span>(i=0; i&lt;sqp.length-1; i++){
        <span class="kwrd">var</span> sqpp = sqp[i].split(<span class="str">&quot;;&quot;</span>);
        <span class="kwrd">if</span>(sqpp[0]==sq){
            <span class="kwrd">if</span>(Number(localStorage.webqqsettings.split(<span class="str">&quot;;&quot;</span>)[1])){
                <span class="kwrd">if</span>(!Number(localStorage.webqqsettings.split(<span class="str">&quot;;&quot;</span>)[5])){
                document.getElementById(<span class="str">'mr'</span>).play();
            }
                <span class="kwrd">var</span> a = qq+<span class="str">&quot;;&quot;</span>+sqpp[1]+<span class="str">&quot;: &quot;</span>+encodeURIComponent(msg)+<span class="str">&quot;;&quot;</span>+tim+<span class="str">&quot;;;&quot;</span>;
                localStorage.webqqc += a;
            }
            <span class="kwrd">var</span> h = qq+<span class="str">&quot;;0;&quot;</span>+sqpp[1]+<span class="str">&quot;: &quot;</span>+encodeURIComponent(msg)+<span class="str">&quot;;&quot;</span>+tim+<span class="str">&quot;;;&quot;</span>;
            localStorage.webqqh += h;
            <span class="kwrd">return</span>;
        }
    }
    <span class="kwrd">var</span> xhr = <span class="kwrd">new</span> XMLHttpRequest();
    content = u+<span class="str">&quot;;0126;&quot;</span>+msgid+<span class="str">&quot;;&quot;</span>+web_session+<span class="str">&quot;;0;1;&quot;</span>+sq+<span class="str">&quot;;&quot;</span>;
    msgid++;
    xhr.open(<span class="str">&quot;POST&quot;</span>, <span class="str">&quot;http://web-proxya.qq.com/conn_s&quot;</span>, <span class="kwrd">true</span>);
    xhr.onreadystatechange = <span class="kwrd">function</span>() {
      <span class="kwrd">if</span> (xhr.readyState == 4) {
          <span class="kwrd">var</span> gtmp = xhr.responseText.split(<span class="str">&quot;;&quot;</span>);
          <span class="kwrd">if</span>(gtmp[1]==<span class="str">&quot;0126&quot;</span> &amp;&amp; gtmp[4]==sq){
              sqa += sq+<span class="str">&quot;;&quot;</span>+gtmp[6]+<span class="str">&quot;;;&quot;</span>;
              <span class="kwrd">if</span>(Number(localStorage.webqqsettings.split(<span class="str">&quot;;&quot;</span>)[1])){
                    <span class="kwrd">var</span> a = qq+<span class="str">&quot;;&quot;</span>+gtmp[6]+<span class="str">&quot;: &quot;</span>+encodeURIComponent(msg)+<span class="str">&quot;;&quot;</span>+tim+<span class="str">&quot;;;&quot;</span>;
                    localStorage.webqqc += a;
                }
                <span class="kwrd">var</span> h = <span class="str">&quot;q&quot;</span>+qq+<span class="str">&quot;;0;&quot;</span>+gtmp[6]+<span class="str">&quot;: &quot;</span>+encodeURIComponent(msg)+<span class="str">&quot;;&quot;</span>+tim+<span class="str">&quot;;;&quot;</span>;
                localStorage.webqqh += h;
            }
            <span class="kwrd">else</span>
            {
                setTimeout(<span class="kwrd">function</span>(){showqunm(qq,sq,msg,tim)},500);
            }
      }
    }
    xhr.send(content);
}</pre>
<p>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>对于发送消息，指令分为两种：一种是向好友发消息，指令为“u;30;msgid;web_session;0a;qq;msg;”；第二种是向群发消息，指令为“u;16;msgid;web_session;qq;0b;606;msg;”，其中qq为群id。同样是将此指令POST到 http://web-proxya.qq.com/conn_s 中去。指令很简单，相信大家也都知道各参数的含义，需要注意的是msg发送前需要进行url编码，即utf8编码。</p>
<p>CreQQ使用ssmsg()函数发送消息，其源码如下。</p>
<pre class="csharpcode"><span class="kwrd">function</span> ssmsg(qq,msg){
    <span class="kwrd">if</span>(<span class="str">&quot;100&quot;</span> == qq){
        creqqfeedback(msg);
        <span class="kwrd">return</span>;
    }
    <span class="kwrd">if</span>(<span class="str">&quot;101&quot;</span> == qq){
        pubweibo(msg);
        <span class="kwrd">return</span>;
    }
    <span class="kwrd">if</span>(<span class="str">&quot;102&quot;</span> == qq){
        pubrenren(msg);
        <span class="kwrd">return</span>;
    }
    <span class="kwrd">var</span> xhr = <span class="kwrd">new</span> XMLHttpRequest();
    <span class="kwrd">if</span>(<span class="str">&quot;q&quot;</span> == qq.substr(0,1)){
        qq = qq.substr(1);
        content = u+<span class="str">&quot;;30;&quot;</span>+msgid+<span class="str">&quot;;&quot;</span>+web_session+<span class="str">&quot;;0a;&quot;</span>+qq+<span class="str">&quot;;&quot;</span>+msg+<span class="str">&quot;;&quot;</span>;
    }
    <span class="kwrd">else</span>{
        content = u+<span class="str">&quot;;16;&quot;</span>+msgid+<span class="str">&quot;;&quot;</span>+web_session+<span class="str">&quot;;&quot;</span>+qq+<span class="str">&quot;;0b;606;&quot;</span>+msg+<span class="str">&quot;;&quot;</span>;
    }
    xhr.open(<span class="str">&quot;POST&quot;</span>, <span class="str">&quot;http://web-proxya.qq.com/conn_s&quot;</span>, <span class="kwrd">true</span>);
    <span class="rem">/*</span>
<span class="rem">    xhr.onreadystatechange = function() {</span>
<span class="rem">      if (xhr.readyState == 4) {</span>
<span class="rem">          freshbadge();</span>
<span class="rem">      }</span>
<span class="rem">    }</span>
<span class="rem">    */</span>
    xhr.send(content);
}</pre>
<p>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>关于CreQQ中的main()函数，我们在之前讲的这些过程都是由main()函数来调用的，因为在JavaScript中通过XMLHttpRequest请求数据时，不会阻塞下面的代码运行，即我们不能通过return的方法将请求得到的服务器响应通过函数值返回，这样我们就不得不让每一部的相关函数运行结束后将状态告知main()函数，之后main()函数再进行下一步的操作。这种解决思路对于学电子的同学应该不会陌生，因为这就是硬件设计语言Verilog中的状态机，我也是从我们的课本中找到了这个思路。main()函数的源码如下，它是通过step和lstep这两个全局变量判断运行状态的。</p>
<pre class="csharpcode"><span class="kwrd">function</span> main(){
    <span class="kwrd">if</span>(step == lstep){
        <span class="kwrd">return</span>;
    }
    <span class="kwrd">else</span>{
        <span class="kwrd">switch</span>(step){
            <span class="kwrd">case</span> -1:{
                getcookie();
                lstep = -1;
                <span class="kwrd">break</span>;
            }
            <span class="kwrd">case</span> 0:{
                getwebsession();
                lstep = 0;
                <span class="kwrd">break</span>;
            }
            <span class="kwrd">case</span> 1:{
                getgroup();
                lstep = 1;
                <span class="kwrd">break</span>;
            }
            <span class="kwrd">case</span> 2:{
                getfriends(0,0,0);
                lstep = 2;
                <span class="kwrd">break</span>;
            }
            <span class="kwrd">case</span> 3:{
                getonline();
                lstep = 3;
                <span class="kwrd">break</span>;
            }
            <span class="kwrd">case</span> 4:{
                getfriendsinfo(0,0);
                lstep = 4;
                <span class="kwrd">break</span>;
            }
            <span class="kwrd">case</span> 5:{
                getmark(0,0);
                lstep = 5;
                <span class="kwrd">break</span>;
            }
            <span class="kwrd">case</span> 6:{
                getquninfo();
                lstep = 6;
                <span class="kwrd">break</span>;
            }
            <span class="kwrd">case</span> 7:{
                getlistinfo();
                lstep = 7;
                clearInterval(ml);
                freshbadge();
                pulld();
                <span class="rem">//setInterval(getsmsg, 5000);</span>
                <span class="kwrd">if</span>(Number(localStorage.webqqsettings.split(<span class="str">&quot;;&quot;</span>)[0])){
                    chrome.browserAction.setTitle({title:u+<span class="str">&quot;(隐身)&quot;</span>});
                }
                <span class="kwrd">else</span>{
                    chrome.browserAction.setTitle({title:u+<span class="str">&quot;(在线)&quot;</span>});
                }
                localStorage.webqqbr = <span class="str">&quot;&quot;</span>;
                <span class="kwrd">break</span>;
            }
        }
    }
}</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>零零散散说了这么多，希望大家能原谅我这么差的表达能力。如果大家想继续深入了解Web QQ的协议（迷你版），可以通过<a href="http://www.google.com.hk/url?sa=t&amp;rct=j&amp;q=webqq%E5%8D%8F%E8%AE%AE&amp;source=web&amp;cd=1&amp;ved=0CCkQFjAA&amp;url=http%3A%2F%2Fblog.csdn.net%2Fyjh4866%2Farticle%2Fdetails%2F5820699&amp;ei=_cnTTonoLs6eiAf-k9zeDg&amp;usg=AFQjCNG9TFgaG4pEh7oiMdZEiuFlq9Or4Q&amp;sig2=w3KN5IyTBgel13Eg36fwMA">这个地址</a>进行学习，我开始也是从这个博客学习的，不过由于这个讲的是老版本的协议，所有个别地方会有些出入，不过讲得要比我好得多。最后要向大家推荐下Windows Live Writer，真的很好用，哈哈。没有详细讲解源码的程序不能算是真正的开源程序，大家说是不是啊 <img src='http://sneezry.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://sneezry.com/2011/11/creqq%e4%bb%a3%e7%a0%81%e8%af%a6%e7%bb%86%e8%a7%a3%e6%9e%90/feed/</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
		<item>
		<title>CreQQ退出Chrome浏览器插件大赛评选</title>
		<link>http://sneezry.com/2011/11/creqq%e9%80%80%e5%87%bachrome%e6%b5%8f%e8%a7%88%e5%99%a8%e6%8f%92%e4%bb%b6%e5%a4%a7%e8%b5%9b%e8%af%84%e9%80%89/</link>
		<comments>http://sneezry.com/2011/11/creqq%e9%80%80%e5%87%bachrome%e6%b5%8f%e8%a7%88%e5%99%a8%e6%8f%92%e4%bb%b6%e5%a4%a7%e8%b5%9b%e8%af%84%e9%80%89/#comments</comments>
		<pubDate>Mon, 21 Nov 2011 16:35:11 +0000</pubDate>
		<dc:creator>sneezry</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[点滴]]></category>

		<guid isPermaLink="false">http://sneezry.com/?p=690</guid>
		<description><![CDATA[很遗憾做出这个决定，但或许这个决定又是最明智的，如果不能给你一个公平的平台，那么还不如不去参与。我不想对CSDN有什么个人评价，只是将我所看到的告诉大家，让大家去评论吧。CreQQ上线10天左右，下载量达到360，投票数达到33，无论是下载量还是投票数都排名第一，很让我欣慰。虽然不是太多，但由于这个活动没有被宣传得太火，能拿到这个成绩我已经很满足了。我从未奢望过最后会拿什么第一，甚至没奢望过会得奖，我只是希望能得到用户最真诚的评判。CSDN平台的投票漏洞我早就发现了，但是我从未用这个漏洞去刷票，甚至CSDN的系统允许同一ID在不同日期投两次票，我都一再告诉同学和朋友不要刷票，投一次足够了。看就在这个时候，某个应用刚刚发布半天下载量和投票数都超过了CreQQ，我不是说没有比CreQQ更好的插件，我也不是说不可能会有插件在短时间内超过CreQQ的成绩，但是如果那个插件做的好，我心服口服。从结构上看，contentscript.js、background.html都是空的，也就是说是作者拿到一个结构完善的空架子，自己填进去的，这实在不像是一位熟练的插件开发者。当然这不能说明什么问题，如果有好的创意能够弥补这方面的不足，问题是，那个应用登录居然采用的是明码登录，而不是使用业内常用的oauth授权，而且只能阅读有限条目，拉到底端后无法读取更多条目，不能发送……这样的插件怎么能够在短时间内受到如此多用户的青睐？！当翻阅其源码时我惊呆了，其后端应用托管于chrome.blog.csdn.net中，我从不知csdn.net向广大用户开放了ftp权限，毫无疑问——CSDN内部人员。既然这么玩了那就没什么意思了，CreQQ果断退出评选，当然如果就这么认输了也不是我的性格，内部不是刷票嘛，我也会刷，那个漏洞我可是还没用过呢！刷过后必然要留图纪念下，同时也希望Google以后搞什么大赛就自己搞，别找个协办的把一锅汤都给搅腥了！]]></description>
			<content:encoded><![CDATA[<p>很遗憾做出这个决定，但或许这个决定又是最明智的，如果不能给你一个公平的平台，那么还不如不去参与。我不想对CSDN有什么个人评价，只是将我所看到的告诉大家，让大家去评论吧。CreQQ上线10天左右，下载量达到360，投票数达到33，无论是下载量还是投票数都排名第一，很让我欣慰。虽然不是太多，但由于这个活动没有被宣传得太火，能拿到这个成绩我已经很满足了。我从未奢望过最后会拿什么第一，甚至没奢望过会得奖，我只是希望能得到用户最真诚的评判。CSDN平台的投票漏洞我早就发现了，但是我从未用这个漏洞去刷票，甚至CSDN的系统允许同一ID在不同日期投两次票，我都一再告诉同学和朋友不要刷票，投一次足够了。看就在这个时候，某个应用刚刚发布半天下载量和投票数都超过了CreQQ，我不是说没有比CreQQ更好的插件，我也不是说不可能会有插件在短时间内超过CreQQ的成绩，但是如果那个插件做的好，我心服口服。从结构上看，contentscript.js、background.html都是空的，也就是说是作者拿到一个结构完善的空架子，自己填进去的，这实在不像是一位熟练的插件开发者。当然这不能说明什么问题，如果有好的创意能够弥补这方面的不足，问题是，那个应用登录居然采用的是明码登录，而不是使用业内常用的oauth授权，而且只能阅读有限条目，拉到底端后无法读取更多条目，不能发送……这样的插件怎么能够在短时间内受到如此多用户的青睐？！当翻阅其源码时我惊呆了，其后端应用托管于chrome.blog.csdn.net中，我从不知csdn.net向广大用户开放了ftp权限，毫无疑问——CSDN内部人员。既然这么玩了那就没什么意思了，CreQQ果断退出评选，当然如果就这么认输了也不是我的性格，内部不是刷票嘛，我也会刷，那个漏洞我可是还没用过呢！刷过后必然要留图纪念下，同时也希望Google以后搞什么大赛就自己搞，别找个协办的把一锅汤都给搅腥了！</p>
<p><a href="http://sneezry.com/wp-content/uploads/sneezry.com/2011/11/google-chorme浏览器插件开发大赛-作品详情.png"><img class="alignnone size-full wp-image-691" title="google chorme浏览器插件开发大赛 作品详情" src="http://sneezry.com/wp-content/uploads/sneezry.com/2011/11/google-chorme浏览器插件开发大赛-作品详情.png" alt="" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://sneezry.com/2011/11/creqq%e9%80%80%e5%87%bachrome%e6%b5%8f%e8%a7%88%e5%99%a8%e6%8f%92%e4%bb%b6%e5%a4%a7%e8%b5%9b%e8%af%84%e9%80%89/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>更加完美的CreQQ</title>
		<link>http://sneezry.com/2011/11/%e6%9b%b4%e5%8a%a0%e5%ae%8c%e7%be%8e%e7%9a%84creqq/</link>
		<comments>http://sneezry.com/2011/11/%e6%9b%b4%e5%8a%a0%e5%ae%8c%e7%be%8e%e7%9a%84creqq/#comments</comments>
		<pubDate>Mon, 07 Nov 2011 16:17:33 +0000</pubDate>
		<dc:creator>sneezry</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[CreQQ]]></category>
		<category><![CDATA[qq]]></category>
		<category><![CDATA[插件]]></category>

		<guid isPermaLink="false">http://sneezry.com/?p=674</guid>
		<description><![CDATA[很少为一个插件发两篇博文——或者说从未吧……说实话，CreQQ真的是我少数几个能拿得出手的插件，不过有点可惜的是它的用户量还不到1000，可能和早期版本不完善有关吧。为了使CreQQ的使用体验更加完美，我对CreQQ再一次进行了较大的升级，所以有必要向大家汇报一下。 首先是外观上，CreQQ终于可以使用黑色主题了，这得益于支持文字颜色的设定，之前的版本文字是黑色的不可更改，导致无法使用黑色主题。让我们看一看黑色的CreQQ是什么样的。 大家也许发现上图中之显示了在线好友，没错，根据用户建议，新版CreQQ增加了只显示在线好友的选项。 或许你还在抱怨CreQQ无法同时和多人聊天的缺陷，之前之所以没有这么设计，是考虑到不进行弹窗的设计，后来从手机QQ中得到了灵感，并且将之最多同时和五人聊天的限制提升为十四人。 CreQQ选项中新增了文字颜色设定与好友显示设定，这在之前已经介绍过，同时CreQQ又新增了多款主题，要不要看看Hello Kitty呢 最新版CreQQ已经发布至CreQQ开发版中，目前CreQQ稳定版依然停留在1.8.5未进行升级，在随后测试三天后，将于11月10日与大家正式见面，想马上进行体验的同学可以现在开发版，不过请注意开发版可能会出现不稳定的情况，同时开发版的升级频率也要大于稳定版，这可能会给您带来麻烦。 CreQQ需要倾听您的建议，请将您的建议发送至 lizhe#lizhe.org，我会争取在24小时内回复每一封来信。再次感谢大家对CreQQ的支持！]]></description>
			<content:encoded><![CDATA[<p>很少为一个插件发两篇博文——或者说从未吧……说实话，CreQQ真的是我少数几个能拿得出手的插件，不过有点可惜的是它的用户量还不到1000，可能和早期版本不完善有关吧。为了使CreQQ的使用体验更加完美，我对CreQQ再一次进行了较大的升级，所以有必要向大家汇报一下。 首先是外观上，CreQQ终于可以使用黑色主题了，这得益于支持文字颜色的设定，之前的版本文字是黑色的不可更改，导致无法使用黑色主题。让我们看一看黑色的CreQQ是什么样的。</p>
<p><img class="alignnone size-full wp-image-675" title="CreQQ" src="http://sneezry.com/wp-content/uploads/sneezry.com/2011/11/wq1890.png" alt="" width="300" height="550" /></p>
<p><img class="alignnone size-full wp-image-676" title="CreQQ" src="http://sneezry.com/wp-content/uploads/sneezry.com/2011/11/wq1891.png" alt="" width="300" height="550" /></p>
<p>大家也许发现上图中之显示了在线好友，没错，根据用户建议，新版CreQQ增加了只显示在线好友的选项。 或许你还在抱怨CreQQ无法同时和多人聊天的缺陷，之前之所以没有这么设计，是考虑到不进行弹窗的设计，后来从手机QQ中得到了灵感，并且将之最多同时和五人聊天的限制提升为十四人。</p>
<p><img class="alignnone size-full wp-image-677" title="CreQQ" src="http://sneezry.com/wp-content/uploads/sneezry.com/2011/11/wq1892.png" alt="" width="300" height="550" /></p>
<p>CreQQ选项中新增了文字颜色设定与好友显示设定，这在之前已经介绍过，同时CreQQ又新增了多款主题，要不要看看Hello Kitty呢 <img src='http://sneezry.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><img class="alignnone size-full wp-image-678" title="CreQQ" src="http://sneezry.com/wp-content/uploads/sneezry.com/2011/11/wq1893.png" alt="" width="608" height="475" /></p>
<p>最新版CreQQ已经发布至CreQQ开发版中，目前CreQQ稳定版依然停留在1.8.5未进行升级，在随后测试三天后，将于11月10日与大家正式见面，想马上进行体验的同学可以现在开发版，不过请注意开发版可能会出现不稳定的情况，同时开发版的升级频率也要大于稳定版，这可能会给您带来麻烦。 CreQQ需要倾听您的建议，请将您的建议发送至 lizhe#lizhe.org，我会争取在24小时内回复每一封来信。再次感谢大家对CreQQ的支持！</p>
]]></content:encoded>
			<wfw:commentRss>http://sneezry.com/2011/11/%e6%9b%b4%e5%8a%a0%e5%ae%8c%e7%be%8e%e7%9a%84creqq/feed/</wfw:commentRss>
		<slash:comments>51</slash:comments>
		</item>
		<item>
		<title>将书签写进Google搜索结果</title>
		<link>http://sneezry.com/2011/10/%e5%b0%86%e4%b9%a6%e7%ad%be%e5%86%99%e8%bf%9bgoogle%e6%90%9c%e7%b4%a2%e7%bb%93%e6%9e%9c/</link>
		<comments>http://sneezry.com/2011/10/%e5%b0%86%e4%b9%a6%e7%ad%be%e5%86%99%e8%bf%9bgoogle%e6%90%9c%e7%b4%a2%e7%bb%93%e6%9e%9c/#comments</comments>
		<pubDate>Thu, 27 Oct 2011 16:32:06 +0000</pubDate>
		<dc:creator>sneezry</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[插件]]></category>

		<guid isPermaLink="false">http://sneezry.com/?p=661</guid>
		<description><![CDATA[还记得曾经Google允许用户屏蔽部分搜索结果时大家都感到非常兴奋，现在就连搜索结果都可以让用户自己说了算了。可是我倒是觉得Google做得还不够，哈哈，为神马你只允许用户删除结果而不允许用户添加结果呢？ 如果我们把书签整合到Google中会是怎样的呢？比如我想在线读《洛丽塔》（18-的小童鞋请自觉不要去搜索，嗯嗯），我在网上找到了一个不错的在线阅读洛丽塔的网站，我想把它加进书签中，但是我有习惯用谷歌搜索内容，于是我就可以通过一个小插件完成我的想法： 如果大家对这个插件感兴趣，那么不妨看看下面对其使用方法的介绍。 首先在浏览任意网页时点击功能工具栏中的插件图标： 点击后当前网页的标题、URL地址会被自动填写，然后要做的就是填写关键字，如果此处我们填写“开发博客”： 点击保存按钮后，我们通过Google搜索“开发博客”试试： ============================================================= 注意：请通过地址栏进行搜索，通过Google主页进行搜索书签不会被显示。 安装插件]]></description>
			<content:encoded><![CDATA[<p>还记得曾经Google允许用户屏蔽部分搜索结果时大家都感到非常兴奋，现在就连搜索结果都可以让用户自己说了算了。可是我倒是觉得Google做得还不够，哈哈，为神马你只允许用户删除结果而不允许用户添加结果呢？</p>
<p>如果我们把书签整合到Google中会是怎样的呢？比如我想在线读《洛丽塔》（18-的小童鞋请自觉不要去搜索，嗯嗯），我在网上找到了一个不错的在线阅读洛丽塔的网站，我想把它加进书签中，但是我有习惯用谷歌搜索内容，于是我就可以通过一个小插件完成我的想法：</p>
<p><img class="alignnone size-full wp-image-662" title="洛丽塔" src="http://sneezry.com/wp-content/uploads/sneezry.com/2011/10/gm1.png" alt="" /></p>
<p>如果大家对这个插件感兴趣，那么不妨看看下面对其使用方法的介绍。</p>
<p>首先在浏览任意网页时点击功能工具栏中的插件图标：</p>
<p><img class="alignnone size-full wp-image-663" title="工具栏" src="http://sneezry.com/wp-content/uploads/sneezry.com/2011/10/gm2.png" alt="" width="382" height="123" /></p>
<p>点击后当前网页的标题、URL地址会被自动填写，然后要做的就是填写关键字，如果此处我们填写“开发博客”：</p>
<p><img class="alignnone size-full wp-image-664" title="书签管理" src="http://sneezry.com/wp-content/uploads/sneezry.com/2011/10/gm3.png" alt="" /></p>
<p>点击保存按钮后，我们通过Google搜索“开发博客”试试：</p>
<p><img class="alignnone size-full wp-image-665" title="开发博客" src="http://sneezry.com/wp-content/uploads/sneezry.com/2011/10/gm4.png" alt="" /></p>
<p>=============================================================</p>
<p><span style="color: #ff0000;">注意：请通过地址栏进行搜索，通过Google主页进行搜索书签不会被显示。</span></p>
<p><a href="https://chrome.google.com/webstore/detail/inmlcpjfafkfaknkplnhoimjfldpmkde"><img class="alignnone size-large wp-image-669" title="点击安装GMark" src="http://sneezry.com/wp-content/uploads/sneezry.com/2011/10/sc-1024x640.png" alt="点击安装GMark" /></a></p>
<p><a href="https://chrome.google.com/webstore/detail/inmlcpjfafkfaknkplnhoimjfldpmkde">安装插件</a></p>
]]></content:encoded>
			<wfw:commentRss>http://sneezry.com/2011/10/%e5%b0%86%e4%b9%a6%e7%ad%be%e5%86%99%e8%bf%9bgoogle%e6%90%9c%e7%b4%a2%e7%bb%93%e6%9e%9c/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
	</channel>
</rss>

