Mozilla Thunderbird的扩展开发

运维 系统运维
触发事件可以在我们自己的MFC子程序中模拟目标程序中的事件。Mozilla平台下如何扩展Thunderbird,本文主要讲的是,通过socket通信来实现MFC对Thunderbird的控制需求。

  最近遇到这样一个需求:在我们的MFC程序中控制Thunderbird。拿到这个奇怪的需求后,有了这么几个想法:1)用全局钩子试着勾住Thunderbird,可细想好像不对。2)用spy++探查点击Thunderbird的各个菜单,按钮时触发的事件,总归是win32平台上跑的程序,归根到底还是事件触发,从理论上说应该是可以在我们自己的MFC程序中模拟标目程序中的各个事件触发。

  但接触到Mozilla的socket方面的知识后,放弃了上面的想法,改用socket通信来实现此需求。一来Thunderbird源代码可以自行修改,因此可以加入一些代码使之成为一个类似HTTP服务器的服务器端程序,二来使用socket进行连接与语言无关,因此C++的程序可以和javascript的程序完成通信,但缺点也很明显,要占用端口,只涉及到本地机器的通信却使用了socket这样的网络通信机制。

  先来介绍下完成这个功能用到的基本知识:由于输入流基接口nsIInputStream没有提供任何从javascript中读取数据的方法,而只能在C++中读取,因此我们必须使用一个可脚本化的输入流来对其进行包装,这个可脚本化的输入流实现了nsIScriptableInputStream接口。

  当然也可以使用其他流类型,比如为了读取二进制数据,我们可以使用nsIBinaryInputStream,反正在javascript中,你总得以其他形式的流来包装基流。

  在Mozilla中,网络数据的读和写是在一个单独的线程中进行的,从socket中读数据是异步的,这就意味着只要socket中有数据存在,就在后台读取数据,而程序会收到数据可读的通知信息,这就意味着我们需要创建一个监听者来监听这个信息。

  对于异步读取数据,我们还需要创建一个输入流Pump,之所以Mozilla选择“泵”这个名称是因为当有数据存在时它就发送小块的数据给监听者。这个Pump实现了nsIInputStreamPump接口,这个接口继承自nsIRequest,后者提供了暂停连接和特定的缓存行为(这些一般的socket程序用不上,但像HTTP这样构建在socket上的高层次应用会用得上的)。

  pump.asyncRead(dataListener,null);

  asyncRead函数用来给Pump对象设置一个监听者,当有数据到来或连接关闭时,监听者就会被调用。监听者对象应该实现nsIStreamListener接口,这个接口有一个方法onDataAvailable,当有额外数据可读时就会被调用。此接口继承自nsIRequestObserver,这个接口有两个方法,onStartRequest,onStopRequest,这两个方法在输入流的开始和结束时分别被调用,因此这3个方法都应该实现。

  下面是客户端代码,使用最简单的阻塞式TCP连接:

  

void CClientTestDlg::OnSend()  
 
  {//发送按钮  
 
  UpdateData();  
 
  if(str.IsEmpty())  
 
  {  
 
  list.InsertString(0,"发送的字符串不能为空。");  
 
  return;  
 
  }  
 
  //strcpy(msg.msg,(LPCTSTR)str);  
 
  char szText[1024];  
 
  strcpy(szText,(LPCTSTR)str);  
 
  SOCKET socket = ::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);  
 
  if(socket==INVALID_SOCKET)  
 
  {  
 
  list.InsertString(0,"创建socket发生错误。");  
 
  return;  
 
  }  
 
  SOCKADDR_IN servAddr;  
 
  servAddr.sin_family = AF_INET;  
 
  servAddr.sin_port = htons(25501);  
 
  servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");  
 
  if(::connect(socket,(sockaddr*)&servAddr,sizeof(servAddr))==-1)  
 
  {  
 
  list.InsertString(0,"连接服务器发生错误。");  
 
  return;  
 
  }  
 
  if(::send(socket,szText,strlen(szText),0) == SOCKET_ERROR)// recv(ServerSocket,buf,sizeof(buf),0);  
 
  {  
 
  list.InsertString(0,"发送数据发生错误。");  
 
  return;  
 
  }  
 
  int bytesRecv = SOCKET_ERROR;  
 
  char buffer[1024];  
 
  memset(buffer,0,1024);  
 
  bytesRecv = recv( socket, buffer, 1024, 0 );  
 
  DWORD dwerr = WSAGetLastError();  
 
  CString str;  
 
  str.Format("%s",buffer);  
 
  list.InsertString(0,str);  
 
  ::closesocket(socket);  
 
  } 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.

#p#

  服务器端代码,通过修改Thunderbird源代码,使之成为一个类似HTTP服务器的服务器端

 

 //***************************************************************************  
 
  //Author: phinecos  
 
  //Date : 2008/5/19  
 
  //Description:服务器监听对象  
 
  //Contact:phinecos@163.com  
 
  //***************************************************************************  
 
  //服务器端对象  
 
  const CI = Components.interfaces, CC = Components.classes, CR = Components.results;  
 
  var gServer = null;//服务器对象  
 
  var gUtility = null;//工具类对象  
 
  //var gConnection = null;//客户端连接对象  
 
  function tBirdBiffServerOnLoad()  
 
  {//启动监听服务器  
 
  try  
 
  {  
 
  gUtility = new tBirdBiffUtility();//新建日志对象  
 
  gUtility.initialize();  
 
  gUtility.log("tBirdBiffServerUi.tBirdBiffServerOnLoad", "Thunderbird biff server loaded");  
 
  gServer = new tBirdBiffServer();//新建服务器对象  
 
  gServer.initialize();//初始化服务器端  
 
  gUtility.log("tBirdBiffServerOnLoad","start server");  
 
  }  
 
  catch(err)  
 
  {  
 
  gUtility.log("tBirdBiffServerOnLoad","start server failed");  
 
  }  
 
  }  
 
  function tBirdBiffServerOnClose()  
 
  {//关闭服务器  
 
  gUtility.log("tBirdBiffServerOnClose","close server");  
 
  gServer.finalize();  
 
  gServer = null;  
 
  gUtility = null;  
 
  }  
 
  function tBirdBiffServer()  
 
  {  
 
  this.serverSocket = null;//服务器端socket  
 
  this.port = null;//服务器端口  
 
  this.initialized = false;  
 
  gUtility.log("tBirdBiffServer constructor","construct ok");  
 
  }  
 
  tBirdBiffServer.prototype =  
 
  {  
 
  getServerSocket: function()  
 
  {//创建服务器端socket  
 
  this.serverSocket = CC["@mozilla.org/network/server-socket;1"].createInstance(CI.nsIServerSocket);  
 
  if(!this.serverSocket)  
 
  {  
 
  gUtility.log("tBirdBiffServer.getServerSocket","Unable to get a server socket");  
 
  }  
 
  else  
 
  {  
 
  try  
 
  {  
 
  this.serverSocket.init(this.port, false, -1);//初始化socket,绑定到端口port上  
 
  this.serverSocket.asyncListen(tBirdBiffServerSocketListener);//开始异步监听  
 
  gUtility.log("tBirdBiffServer.getServerSocket","Server socket established");  
 
  }  
 
  catch(e)  
 
  {  
 
  gUtility.log("tBirdBiffServer.getServerSocket, Server socket established error");  
 
  this.serverSocket = null;  
 
  }  
 
  }  
 
  },  
 
  closeServerSocket: function()  
 
  {//关闭服务器端socket  
 
  if(!this.serverSocket)  
 
  {  
 
  this.serverSocket.close(null);  
 
  this.serverSocket = null;  
 
  }  
 
  },  
 
  initialize: function()  
 
  {  
 
  if(this.initialized)  
 
  {  
 
  return;  
 
  }  
 
  this.port = 25501;//获取端口号  
 
  gUtility.log("tBirdBiffServer.initialize","port is: "+this.port);  
 
  this.getServerSocket();//创建服务器端socket  
 
  this.initialized = true;  
 
  gUtility.log("tBirdBiffServer.initialize","initialize ok!");  
 
  },  
 
  finalize: function()  
 
  {//退出程序  
 
  if(!this.initialized)  
 
  {  
 
  return;  
 
  }  
 
  this.closeServerSocket();//关闭服务器端socket  
 
  gUtility.log("tBirdBiffServer.finalize","server Finalized");  
 
  },  
 
  }  
 
  var listener =  
 
  {  
 
  finished : function(data)  
 
  {//数据读取完毕  
 
  ParseCommand(data);//解析命令字  
 
  }  
 
  }  
 
  const tBirdBiffServerSocketListener =  
 
  {  
 
  onSocketAccepted: function(serverSocket, clientSocket)  
 
  {//接受来自客户端的socket请求  
 
  gUtility.log("tBirdBiffServerSocketListener.onSocketAccepted","Got a connection from: " + clientSocket.host + ":" + clientSocket.port);  
 
  var outputData = "Ok,server get your command";  
 
  var outstream = clientSocket.openOutputStream(0,0,0);  
 
  outstream.write(outputData,outputData.length);  
 
  try  
 
  {  
 
  //打开输入流  
 
  var stream = clientSocket.openInputStream(0,0,0);  
 
  var instream = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream);  
 
  instream.init(stream);  
 
  var dataListener =  
 
  {  
 
  data : "",//来自客户端的数据  
 
  onStartRequest: function(request, context){},  
 
  onStopRequest: function(request, context, status){  
 
  instream.close();  
 
  outstream.close();  
 
  listener.finished(this.data);  
 
  },  
 
  onDataAvailable: function(request, context, inputStream, offset, count){  
 
  this.data += instream.read(count);  
 
  },  
 
  };  
 
  var pump = Components.classes["@mozilla.org/network/input-stream-pump;1"].createInstance(Components.interfaces.nsIInputStreamPump);  
 
  pump.init(stream, -1, -1, 0, 0, false);  
 
  pump.asyncRead(dataListener,null);  
 
  }  
 
  catch(err)  
 
  {  
 
  gUtility.log("tBirdBiffServerConnection.setSocket",e);  
 
  return false;  
 
  }  
 
  },  
 
  onStopListening: function(serverSocket, status)  
 
  {//服务器端停止监听  
 
  gUtility.log("tBirdBiffServerSocketListener.onStopListening","Server socket has stopped listening");  
 
  }  
 
  } 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
  • 164.
  • 165.
  • 166.
  • 167.
  • 168.
  • 169.
  • 170.
  • 171.
  • 172.
  • 173.
  • 174.
  • 175.
  • 176.
  • 177.
  • 178.
  • 179.
  • 180.
  • 181.
  • 182.
  • 183.
  • 184.
  • 185.
  • 186.
  • 187.
  • 188.
  • 189.
  • 190.
  • 191.
  • 192.
  • 193.
  • 194.
  • 195.
  • 196.
  • 197.
  • 198.
  • 199.
  • 200.
  • 201.
  • 202.
  • 203.
  • 204.
  • 205.
  • 206.
  • 207.
  • 208.
  • 209.
  • 210.
  • 211.
  • 212.
  • 213.
  • 214.
  • 215.
  • 216.
  • 217.
  • 218.
  • 219.
  • 220.
  • 221.
  • 222.
  • 223.
  • 224.
  • 225.
  • 226.
  • 227.
  • 228.
  • 229.
  • 230.
  • 231.
  • 232.
  • 233.
  • 234.
  • 235.
  • 236.
  • 237.
  • 238.
  • 239.
  • 240.
  • 241.
  • 242.
  • 243.
  • 244.
  • 245.
  • 246.
  • 247.
  • 248.
  • 249.
  • 250.
  • 251.
  • 252.
  • 253.
  • 254.
  • 255.
  • 256.
  • 257.
  • 258.
  • 259.
  • 260.
  • 261.
  • 262.
  • 263.
  • 264.
  • 265.
  • 266.
  • 267.
  • 268.
  • 269.
  • 270.
  • 271.
  • 272.
  • 273.
  • 274.
  • 275.
  • 276.
  • 277.
  • 278.
  • 279.
  • 280.
  • 281.
  • 282.
  • 283.
  • 284.
  • 285.
  • 286.
  • 287.

【编辑推荐】

  1. Thunderbird 邮件导入导出的方法
  2. Thunderbird的安装方法
  3. Thunderbird 配置手册
  4. Ubuntu下安装Thunderbird
  5. Thunderbird 的相关扩展
  6. Thunderbird中常见问题解决
  7. 图文并茂 Thunderbird设置教程
  8. Thunderbird的使用技巧
责任编辑:zhaolei 来源: 网络转载
相关推荐

2011-01-18 17:49:29

2011-01-21 16:14:30

Thunderbird

2024-03-11 10:19:30

Plasmo浏览器Web

2009-06-12 14:31:59

Google WaveGoogle Wave

2011-07-21 13:30:18

Apple Safari 浏览器

2011-01-19 09:25:40

互联网

2012-10-22 16:49:56

IBMdw

2021-05-27 14:58:07

ThunderbirdMozilla密钥

2016-09-21 12:34:10

Chrome浏览器插件

2011-01-21 14:30:02

Thunderbird技巧

2011-05-12 16:30:44

Mozill应用商店HTML5

2011-01-18 17:35:08

Thunderbird安装方法

2011-12-07 10:03:11

Mozilla新闻

2009-07-28 17:27:26

Sun网络架构

2011-01-21 17:00:49

Thunderbird日历

2011-01-18 18:54:48

Thunderbird

2011-01-21 15:00:08

Thunderbirdmail

2011-01-18 18:28:49

Thunderbird配置

2011-01-21 17:12:48

ThunderbirdIMAP

2011-01-21 17:22:36

Thunderbird
点赞
收藏

51CTO技术栈公众号