DotText源码阅读(7) --Pingback/TrackBack

DotText源码阅读(7) --Pingback/TrackBack
博客这种服务的区别于论坛和所谓文集网站,很大程度上我认为是由于pingback/trackback的存在,使得博客这种自媒体有可以延展加入SNS的要素。所以分析博客程序,我们需要了解这种协议以及协议的实施细节。
在dottext的源代码中,在发表作品中,我们可以看到有pingback协议的支持,同时在web services的实现中,有trackback协议的实现。至于什么是piongback/trackback协议,google下应当可以找到,也不用我费口舌。
通过              <HttpHandlerpattern="/(?:admin)"type="Dottext.Web.UI.Handlers.BlogExistingPageHandler, Dottext.Web"handlerType="Factory"/>
的映射,使得我们访问每一个blog的admin目录时候,都会UrlRewrite到dottexweb\admin目录下的相对应aspx文件(参考前面部分),其中在发表post的时候,我们看到是这样一个调用关系:
private void UpdatePost()
         {   
              if(Page.IsValid)
              {
                   string successMessage = Constants.RES_SUCCESSNEW;
                   try
                   {
                       Entry entry = new Entry(EntryType);
                        entry.Title = txbTitle.Text;
                        entry.Body = Globals.StripRTB(ftbBody.Text,Request.Url.Host);
                      
                        entry.BlogID = Config.CurrentBlog(Context).BlogID;
                      
                       if (PostID > 0)
                       {//是更新操作
                            successMessage = Constants.RES_SUCCESSEDIT;
                            entry.DateUpdated = DateTime.Now;//BlogTime.CurrentBloggerTime;
                            entry.EntryID = PostID;
                           
                            Entries.Update(entry);
                           
                       }
                       else
                       {//新建操作
                            entry.DateCreated = DateTime.Now;//BlogTime.CurrentBloggerTime;
                            PostID = Entries.Create(entry);       
                       }
                   }
                   catch(Exception ex)
                   {           }
                   finally
                   {            }
              }
     }
     Entries.Create(entry);是这样的:
         public static int Create(Entry entry, int[] CategoryIDs)
         {
              HandlerManager.PreCommit(entry,ProcessAction.Insert);            
              int result = DTOProvider.Instance().Create(entry,CategoryIDs);             
              if(result > 0)
              {
                   HandlerManager.PostCommit(entry,ProcessAction.Insert);                
              }
              return result;
     }
     最终的数据存储试调用DTOProvider也就是DataDTOProvider 最终是落到 SqlDataProvider 来实现数据存储操作。但是我们注意到 HandlerManager.PostCommit(entry,ProcessAction.Insert);     这个操作。仔细看看:
     HandlerManager 是一个关于Entry操作类的包装类(wapper class),PreCommit是这样定义的:
          Process(ProcessState.PreCommit,e,pa);
     而Process是这样读取web.config的
     public static void Process(ProcessState ps, Entry e, ProcessAction pa)
         {     //Do we have factories? 在疑惑是否该用工厂模式呢
              EntryHandler[] hanlers = Config.Settings.EntryHandlers;     //这是反序列化哦,这里的Config是Dottext.Framework.Configuration.Config
              if(e != null && hanlers != null)
              {     //walk the entries 遍历全部处理例程
                   for(int i = 0; i<hanlers.Length; i++)
                   {
                        EntryHandler handler = hanlers[i];
                        if(ShouldProcess(ps,handler,e.PostType,pa))
                       {
                            IEntryFactoryHandler ihandler = handler.IEntryFactoryHandlerInstance;                           
                            //Call the IEntryFactoryHandler configure method. This gives async items a chance to "ready" themselves
                            //before leaving the main thread and entering the managed queue.
                            ihandler.Configure();
                            if(handler.IsAsync)
                            {//Add factory to managed queue.
                                 EntryHanlderQueue.Enqueue(ihandler,e);
                            }
                            else
                            {
                                 ihandler.Process(e);
                            }
                       }
                      
                   }
              }
         }
ShouldProcess 是判断是预提交还是已经提交post,决定是否应该进行handler的实例化,如果是已经提交的Post,我们需要进行handler.IEntryFactoryHandlerInstance;      IentryFactoryHandlerInstance最终是通过
ihandler = (IEntryFactoryHandler)Activator.CreateInstance(Type.GetType(this.ItemType));
来实例化数组元素的().
经过实例化后,就可以执行了。此时根据 handler.IsAsync 的属性,决定是允许 EntryHanlderQueue.Enqueue(ihandler,e); 加入队列,还是马上处理
ihandler.Process(e);.
对于可以异步执行的静态函数 Enque 处理:
public static void Enqueue(IEntryFactoryHandler factory, Entry e)
         {
              EntryHanlderQueue ehq = new EntryHanlderQueue(factory,e);
              ManagedThreadPool.QueueUserWorkItem(new WaitCallback(ehq.Enqueue));
     }
构造一个实例,然后加入线程队列进行任务排队。线程管理暂不讨论。我们看看这几个EntryHandler.
TrackBack Handler是如何处理的呢?
public void Process(Dottext.Framework.Components.Entry e)
         {
              //Get a list of links from the current post
              StringCollection links = TrackHelpers.GetLinks(e.Body);
              if(links != null && links.Count > 0)
              {
                   //Instantiate our proxy
                   TrackBackNotificationProxy proxy = new TrackBackNotificationProxy();
                  
                   //Walk the links
                   for(int i = 0; i<links.Count; i++)
                   {
                       string link = links[i];
                       //get the page text
                       string pageText = BlogRequest.GetPageText(link,e.Link);
                        if(pageText != null)
                       {
                            try
                            {
                                 string desc = null;
                                 if(e.HasDescription)
                                 {
                                     desc = e.Description;
                                 }
                                 else
                                 {
                                      desc=string.Format("TrackBack From:{0}",e.Link);
                                      
                                 }   
desc = regexStripHTML.Replace(e.Body,string.Empty);
                                      if(desc.Length > 100)
                                     {
                                          int place = 100;
                                          int len = desc.Length-1;
                                          while(!Char.IsWhiteSpace(desc[place]) && i < len)
                                          {
                                               place++;
                                          }
                                          desc = string.Format("{0}...",desc.Substring(0,place));
                                     }
                                 }
                                 //attempt a trackback.
                            proxy.TrackBackPing(pageText,link,e.Title,e.Link,e.Author,desc);                           
                            }
                            catch(Exception ex)
                            {                                 Logger.LogManager.CreateExceptionLog(ex,string.Format("Trackback Failure: {0}",link));
                            }
                       }
                   }
              }
     }
 TrackHelpers.GetLinks 会分析Entry.Body字符串,获得post的全部href连结,也就是对外引用部分,这个TrackBack利用proxy.TrackBackPing(pageText,link,e.Title,e.Link,e.Author,desc); 将本文的对外引用通告刚刚获得的连接地址。
TrackBackPing :
    string pageText = BlogRequest.GetPageText(link,e.Link);会利用BlogRequest的http协议能力下载被引用地址的source code,然后 link为另外blog的地址,而e.Link为reffer,这是为了告知对方那个页面引用了link。经过安全解码后,获得了link的源代码,然后TrackBackPing会进行分析,找寻string sPattern = @"<rdf:\w+\s[^>]*?>(</rdf:rdf>)?";匹配的部分,分析出其中的引用通告地址。下一步就是利用SendPing(string trackBackItem, string parameters),向目标地址处post一个application/x-www-form-urlencoded"的数据。此即完成了一次trackBack.
  其他几个EntryHandler也是分同步和异步的,大家可以照此阅读。
    
    题外话:那些没有礼貌的实现pingback/Trackback的所谓blog,就不要妄自称自己为博客服务商(BSP)吧。

CNBlogsDottext10Beta2版本中,TRACKBACK功能被屏蔽掉了,原因可能是因为很多人安装成功后,在提交包含引用链接的POSTS时,出现错误:

 将截断字符串或二进制数据

其实这是因为发送TRACKBACK的关键方法:SendPing(string trackBackItem, string parameters)里,发送字节流时按照ASCII码的长度来发送,当PARAMETERS中包含中文时,就会出错,解决方法是转换成UTF-8发送,下面是我修改过后的代码:

  private void SendPing(string trackBackItem, string parameters)
  {

   HttpWebRequest request = BlogRequest.CreateRequest(trackBackItem);
   request.Method = "POST";

   request.ContentType = "application/x-www-form-urlencoded";
   request.KeepAlive = false;

   byte [] buff = Encoding.GetEncoding("UTF-8").GetBytes(parameters);     

   request.ContentLength = buff.Length;

   Stream reqStream = null;
   try
   {
    reqStream = request.GetRequestStream();

    reqStream.Write(buff, 0, buff.Length);
   }
   catch(Exception e)
   {
    Logger.LogManager.CreateExceptionLog(e,"SendPing Exception");
   }
   finally
   {
    reqStream.Close();
   }

首先我们来看一下是怎么发送TRACKBACK的:入口是Dottext.Framework.EntryHandling.Process

检查文章内容中是否已经包含了远程网页的链接,只有包含才能继续 从远程链接的网页下载HTML代码,如果没得到,说明不是合法链接,要返回 在得到的HTML代码中检查是否已经包含了本文的链接,有说明已经PING过了,要返回 在得到的HTML代码中根据TRACKBACK标准取到要TRACKBACK链接(链接包含在RDF为键值的被注释的XHTML代码中),从而完成了由网页链接到TRACKBACK链接的转化 发送(PING)TRACKBACK。

再来看一下接收TRACKBACK的流程,入口是:Dottext.Framework.Tracking.TrackBackHandler.ProcessRequest

根据PING过来的TRACKBACK链接得到本地文章的ID号,得不到则不是合法链接,要返回 REQUEST方法是否是POST,不是要返回,这是TRACKBACK标准规定的。 根据ID号从库中检索数据,生成ENTRY对象 根据传过来的URL下载远程网页的HTML代码,如果没得到或得到的HTML中没有包含本地文章的链接,说明不是合法链接,要返回 从得到的HTML代码中分析出对方的页面标题,如果没有,要返回 生成一个新的ENTRY对象,并对其各个属性赋值,然后入库

由此我们看到DOTTEXT发送TRACKBACK时效率是比较低的。原因是需要去下载远程的HTML,这将是一个非常耗时的工作,更不用说还要从很可能十分庞大的HTML代码中提取出TRACKBACK链接。

再者就是接收TRACKBACK时,并没有建立屏蔽机制。从而无法避免垃极广告的侵袭,也就是我们所说的SPAM COMMENT。

我想要解决这些问题,需要改变发送TRACKBACK的发送机制。

不再根据TRACKBACK标准去自动获取TRACKBACK,这样不仅效率极低,而且很多网站并不支持这个标准(比如 www.blogchinese.com 就直接提供引用通告,而不是隐藏在网页中,哈哈)的话,就无法TRACKBACK成功了。我们就认为用户输入的就是合法的TRACKBACK链接。直接进行发送。 为了能让用户得到合法的TRACKBACK地址,在每一篇文章内容之后,都显示此文的TRACKBACK链接。 再提供一个页面,输入网页链接,就能显示出此网页的TRACKBACK链接,以继续支持那些符合标准的网站

在接收TRACKBACK时,我们相应做以下改动:

将对方URL拿到库里去验证,看对方是否已经PING过了,因为是在本地进行,速度会非常快。 在库中建立BLACKIP表,对来方的IP进行校验,这样就拥有了封对方IP的功能。

以上只是我的设想,因为时间的原因,还没有动手去实现,如果大家有更好的建议,可以一起来探讨。

posted on 2007-07-13 15:29 方正 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/linckle/archive/2007/07/13/817321.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/264760.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

windows上安装mysql5.7.24

平时自己做测试的时候&#xff0c;自己安装一个mysql还是很有必要的&#xff0c;网上教程很多&#xff0c;但是自己操作过程中还是遇到了一些问题&#xff0c;这里记录一下安装过程。 一、下载mysql https://downloads.mysql.com/archives/community/ 我使用的是5.7.24的解压版…

《java设计模式》之责任链模式

在阎宏博士的《JAVA与模式》一书中开头是这样描述责任链&#xff08;Chain of Responsibility&#xff09;模式的&#xff1a; 责任链模式是一种对象的行为模式。在责任链模式里&#xff0c;很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递&#…

理解杀毒软件技术的意义 脱壳、虚拟、启发式介绍

如果生命是一种执着的力量&#xff0c;那么总有一种力量&#xff0c;比生命更加执着&#xff0c;就是死亡&#xff01;当你去深刻思考“死亡”这两个字的含义&#xff0c;用心去感受生命的来临与离去&#xff0c;更或许有的人&#xff0c;需要在他弥留之际&#xff0c;才能真正…

gb酱油和gbt酱油哪个好_都是酱油,生抽好还是味极鲜好?老板:两者差别很大,别买错了...

导读&#xff1a;都是酱油&#xff0c;生抽好还是味极鲜好&#xff1f;老板&#xff1a;两者差别很大&#xff0c;别买错了一道美食的完成不只是依赖掌厨的高超技艺&#xff0c;还与炒制的锅具、所用的调料等有关。其中最重要的就是调料&#xff0c;有了调料的辅助&#xff0c;…

C#连接基于Java开发IM——Openfire

Openfire简介 Openfire 是开源的、基于可拓展通讯和表示协议(XMPP)、采用Java编程语言开发的实时协作服务器。Openfire的效率很高&#xff0c;单台服务器可支持上万并发用户。   Server和Client端的通信都用xml文档的形式进行通信。 但是Openfire是Java语言写的&#xff0c;对…

数字万用表的使用

参考&#xff1a;连3岁小孩子都能看懂的万用表使用方法 地址&#xff1a;https://www.bilibili.com/video/BV1Gx411z7x2?p1&vd_sourcecc0e43b449de7e8663ca1f89dd5fea7d 目录万用表外观测量电阻测量通断/二极管测量电容测量温度测量电流测量电压测量三极管万用表外观 测量…

程序员讨论 《黑客帝国》 (三) 情感

人总会与人比较&#xff0c;找出自己拥有而别人没有的东西&#xff0c;从而建立起自信心。早期机器就已经在记忆和运算能力上超越人类&#xff0c;于是人类嘲笑机器没有智慧&#xff0c;突然有一天机器出现了智慧&#xff0c;能解决复杂问题&#xff0c;学会“骗人”了。人类傻…

在GridView开头插入自动编号的方法

网上看了很多方法&#xff0c;发现都是照抄别人&#xff0c;而且&#xff0c;都是把第一列替换掉了&#xff0c;往往不是我们的理想结果。经过本人的实践&#xff0c;下面方法觉得更好用一些。就是不知道数据量过大时&#xff0c;效率怎么样&#xff0c;不过既然能用&#xff0…

python数据整理 高一_关于Python爬虫的最全知识梳理,项目经理花了三天总结出来的经验...

作爲零基础小白&#xff0c;大体上可分爲三个阶段去完成&#xff0c;第一阶段是入门&#xff0c;掌握必备基础知识&#xff0c;比如Python基础、网络央求的基本原理等&#xff0c;第二阶段是模仿&#xff0c;跟着别人的爬虫代码学&#xff0c;弄懂每一行代码&#xff0c;熟习主…

GNS3中不同型号路由器支持的模块表

Dynamips 支持的模块C7200 开始Slot 0:C7200-IO-FE <------> 支持1 个Fastethernet 接口C7200-IO-2FE <------> 支持2 个Fastethernet 接口(DynamipsGUI 2.3 里面没有这个选项,想用只有自己添加了)C7200-IO-GE-E <------> 插这个卡以后会同时出现2 个端口,Et…

南京:第三届软博会“外包”将唱主角

南京&#xff1a;第三届软博会“外包”将唱主角 新华网江苏频道2007-08-17 09:10:31 来源: 本网综合 据《江南时报》报道&#xff0c;再过半个月&#xff0c;名列“中国十大知名展会品牌”之一的南京“软博会”——第三届中国&#xff08;南京&#xff09;国际软件产品博览会将…

vue鼠标右键自定义菜单_vue-右键菜单功能

[TOC]>[success] # :-: vue-右键菜单功能[在线demo点击我](https://xunleif2e.github.io/vue-context-menu/demo/dist/#/)项目中有时候会有右键菜单的需求&#xff0c;所以在github找了一个[右键菜单](https://github.com/xunleif2e/vue-context-menu)的插件&#xff0c;使用…

Zookeeper:fsync超时导致实例异常

一、问题描述 2019-02-19 08:44左右&#xff0c;实时计算服务重启&#xff0c;报错显示找不到zk集群的leader节点&#xff0c;同时ZooKeeper集群有告警显示连接超时&#xff1a; 指标[连接耗时(ms)18221]符合告警规则[连接耗时(ms)>3000] 二、排查过程 查看当前集群状态&…

断言(assert)的用法

参考&#xff1a;https://www.runoob.com/w3cnote/c-assert.html 目录作用总结与注意事项Demo作用 assert 是个宏&#xff0c;并且作用并非"报错"。 assert() 的用法像是一种"契约式编程"&#xff0c;程序满足我的假设条件&#xff0c;才能正常良好的运作…

oracle 变量

插入 日期时间 循环插入 declaretotal date: trunc(sysdate-1) ;beginfor i_count in 1..10000 LOOPinsert into DQ_DATE(date_time) values ( total );total : total 1/24;end loop; end; 转载于:https://www.cnblogs.com/kingxiaozi/p/3790327.html

马云语录,非常值得一看(转)

来源:计算机网1999至今 在杭州设立研究开发中心&#xff0c;以香港为总部&#xff0c;创办阿里巴巴网站(Alibaba.com) 孙正义跟我有同一个观点&#xff0c;一个方案是一流的Idea加三流的实施&#xff1b;另外一个方案&#xff0c;一流的实施&#xff0c;三流的Idea&#xff0c;…

keepalived mysql双主架构图_基于keepalived Mysql双主热备配置

基于keepalived双主热备:一.环境:OS:CentOS 6.5 X64DB Version:Percona Mysql 5.7.15-9-log路径:/app/mysql57数据文件路径:/data/mysql57/dataDB1:192.168.213.4DB2:192.168.213.5二.安装keepalived包(两台主机都需操作)1.下载keepalived包cd /usr/local/toolswget http://www…

centos7 docker安装和使用_入门教程

centos7 docker安装和使用_入门教程 原文:centos7 docker安装和使用_入门教程说明&#xff1a;本文也是参考互联网上的文章写的&#xff0c;感谢相关作者的贡献。 操作系统 64位CentOS Linux release 7.2.1511 (Core) 配置好IP&#xff1a;192.168.1.160 修改yum源 目的是提升对…

公钥、私钥、数字签名和数字证书

参考:公钥、私钥、数字签名和数字证书的概念及解密 地址:https://blog.csdn.net/oscar999/article/details/123489420 作者:oscar999 目录 概念解析https 的非对称加密和对称加密如何产生密钥和证书使用keytool 产生公私钥到一个密钥库文件中从密钥库文件导出证书openssl 将…

curl命令具体解释

对于windows用户假设用Cygwin模拟unix环境的话&#xff0c;里面没有带curl命令&#xff0c;要自己装&#xff0c;所以建议用Gow来模拟&#xff0c;它已经自带了curl工具&#xff0c;安装后直接在cmd环境中用curl命令就可&#xff0c;由于路径已经自己主动给你配置好了。 linux …