[英]How to intercept uploading of email attachments with a Firefox XUL extension in outlook.com web mail
I have a XUL extension which uses a native Windows DLL and js-ctypes to encrypt files inside the local file system. 我有一个XUL扩展名,它使用本机Windows DLL和js-ctypes加密本地文件系统中的文件。 I have already tested a menu driven version of it and it seems to work fine. 我已经测试了它的菜单驱动版本,并且看起来工作正常。
Now I would like to do the following: When creating a new email with attachments, be able to "catch" the attachment file and process it (meaning: encrypt it) before uploading to the composed email message. 现在,我要执行以下操作:在创建带有附件的新电子邮件时,能够“捕获”附件文件并对其进行处理(意味着:对其进行加密),然后再将其上传到所编写的电子邮件中。 I would like to do it in a transparent fashion so the user does not have to go through the menu driven process except for providing the password for encryption. 我想以透明的方式进行操作,因此用户除了提供用于加密的密码外,不必经过菜单驱动的过程。
I want to do this inside the outlook.com web based email (not Office version). 我想在基于Outlook.com网络的电子邮件(不是Office版本)中执行此操作。
I know it is a long shot, but does anybody have an idea on where to start looking? 我知道这是一个远景,但是有人对从哪里开始寻找想法吗? Anybody has done something like this in the past? 过去有人做过这样的事情吗?
Thanks in advance! 提前致谢!
A good place to start is an addon that already does what you want (in a generic way): 一个不错的起点是一个已经完成了您想要的(以通用方式)的插件:
https://addons.mozilla.org/en-US/firefox/addon/tamper-data/ https://addons.mozilla.org/en-US/firefox/addon/tamper-data/
On the download page it says Use tamperdata to view and modify HTTP/HTTPS headers and post parameters
. 在下载页面上,显示Use tamperdata to view and modify HTTP/HTTPS headers and post parameters
。 You're interested in changing 'post parameters' so that's a good place to start. 您对更改“后参数”感兴趣,因此这是一个不错的起点。
But if you just want to implement this yourself.... 但是,如果您只是想自己实现这一点...。
I've answered this out-of-order, in order to progress in the way you might build up the solution in development. 我已经无序地回答了这个问题,以便在开发过程中逐步建立解决方案。
In the final extension, you'll need to: 在最后的扩展中,您需要:
Intercepting the request & replacing the existing POST content 拦截请求并替换现有的POST内容
The basics are that you need to implement an nsIObserver passing an nsIHTTPChannel as the "subject" for observation. 其基本用法就是你需要实现nsIObserver传递一个nsIHTTPChannel作为“主题”进行观察。 The "notification" you wish to observe is called http-on-modify-request
. 您希望观察的“通知”称为http-on-modify-request
。
There are simple examples ( 1 , 2 ) for intercepting GET
requests in the documentation for http-on-modify-request
, however intercepting POST
requests is more complicated. 有简单的例子( 1 , 2用于拦截) GET
的文档中请求http-on-modify-request
,但是截取POST
请求是比较复杂的。
Getting at the POST request body: 进入POST请求正文:
There's a mozillazine forum thread that deals with this exact topic. 有一个mozillazine论坛主题可以处理这个确切的主题。 Kamelot9
's 2nd post in that thread details how to (1) get at the post body: Kamelot9
在该线程中的Kamelot9
文章详细介绍了如何(1)获得文章正文:
var httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel);
var uploadChannel = httpChannel.QueryInterface(Ci.nsIUploadChannel);
var uploadChannelStream = uploadChannel.uploadStream;
uploadChannelStream
.QueryInterface(Ci.nsISeekableStream)
.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);
var stream = Cc["@mozilla.org/binaryinputstream;1"]
.createInstance(Ci.nsIBinaryInputStream);
stream.setInputStream(uploadChannelStream);
var postBytes = stream.readByteArray(stream.available());
var poststr = String.fromCharCode.apply(null, postBytes);
where aSubject
here comes as a parameter to your http-on-modify-request
notification. 这里的aSubject
用作您的http-on-modify-request
通知的参数。 You can then just modify poststr
. 然后,您可以只修改poststr
。 Depending on the server, you might also need to modify the Content-length
header (or your post may be truncated). 根据服务器的不同,您可能还需要修改Content-length
标头(否则您的帖子可能会被截断)。
Replacing POST request content: 替换POST请求内容:
Once you've got your modified POST body, you need to (2) replace the existing content of the inputStream
in the uploadChannel
with your own: 修改后的POST正文后,您需要(2)用您自己的内容替换uploadChannel
inputStream
的现有内容:
var inputStream = Cc["@mozilla.org/io/string-input-stream;1"]
.createInstance(Ci.nsIStringInputStream);
inputStream.setData(poststr, poststr.length);
uploadChannel.setUploadStream(
inputStream,
"application/x-www-form-urlencoded",
-1);
// do this last - setUploadStream resets requestMethod to PUT
httpChannel.requestMethod = "POST";
Cc
and Ci
above are just shorthand for Components.classes
and Components.interfaces
respectively. 上面的Cc
和Ci
分别只是Components.classes
和Components.interfaces
简写。 These shorthand variables may already be set up, or you can define them yourself. 这些速记变量可能已经设置,或者您可以自己定义它们。
Parsing the form data: 解析表单数据:
I think that normally for a file upload, the Content-type:
will be multipart/form-data
. 我认为通常对于文件上传, Content-type:
将是multipart/form-data
。
To get down to the particular 'attachment' you're interested in, you'll need to: 要深入了解您感兴趣的特定“附件”,您需要:
BASE64
) 删除已使用的任何文本编码(例如: BASE64
) In the POST headers, you'll get something like: 在POST标头中,您将获得类似以下内容的信息:
Content-Type: multipart/form-data; boundary=JGUOAeGT3Fjgjcdk6s35F2mPVVyTdzgR
where 'JGUOAeGT3Fjgjcdk6s35F2mPVVyTdzgR' is the MIME boundary. 其中“ JGUOAeGT3Fjgjcdk6s35F2mPVVyTdzgR”是MIME边界。 In the body of the POST, the content will start will be formatted like this: 在POST正文中,开始的内容将采用以下格式:
--[boundary]
CONTENT-PART #1
--[boundary]
CONTENT-PART #2
--[boundary]
Each CONTENT-PART
above will have some HTTP headers, a blank line, then the body of that particular CONTENT-PART
. 上面的每个CONTENT-PART
都有一些HTTP标头,一个空行,然后是该特定CONTENT-PART
的正文。
An example from another stackoverflow question : 来自另一个stackoverflow问题的示例:
Content-Disposition: form-data; name="updates"; filename="update1353963418000.json"
Content-Type: application/json; charset=UTF-8
Content-Transfer-Encoding: binary
{"collectionType":"activities","date":"2012-11-26","ownerId":"qw12er23","ownerType":"user","subscriptionId":"112233-activities"}]
In this case, the Content-Transfer-Encoding
is binary (raw, encoded) UTF8, so you wouldn't need to do any more work to be able to read the JSON in the body of the CONTENT-PART
. 在这种情况下, Content-Transfer-Encoding
是二进制(原始,编码的)UTF8,因此您无需再做任何工作就能读取CONTENT-PART
正文中的JSON。
In your case, the browser will be sending a binary file, so it'll likely have set the Content-Transfer-Encoding
to base64
, which means you'll need to Base64-decode the body of the CONTENT-PART
to get to your real binary file. 在您的情况下,浏览器将发送一个二进制文件,因此它可能已将Content-Transfer-Encoding
为base64
,这意味着您需要Base64解码CONTENT-PART
的主体才能到达您的真正的二进制文件。 If base64data
contains the encoded content, then this will give you the raw binary data: 如果base64data
包含编码的内容,那么这将为您提供原始二进制数据:
var rawData = atob(base64data);
At that point you can do whatever encryption you want on rawData
. 那时,您可以对rawData
进行所需的任何加密。
Remeber, you'll have to re-encode the binary data after your encryption (using btoa
), then you'll need to re-assemble the multipart envelope, before re-constructing the POST request body. 记住,加密后(使用btoa
)必须重新编码二进制数据,然后在重新构造POST请求正文之前,需要重新组装多部分信封。 (Don't forget to get .length
of the final request body so that you can substitute in the Content-length
in the request headers.). (不要忘记获取最终请求主体的.length
,以便您可以在请求标头中替换Content-length
。)
targetting the request(s): 定位请求:
That's the basic mechanism for modifying a POST request. 这是修改POST请求的基本机制。 But you've still got to single out your particular POST requests (examine the POST request URL in the observer notification) so that you allow other POST requests to proceed as normal without invoking your modification code. 但你仍然有挑出你特别POST请求(审查观察者通知POST请求的URL),这样就允许其他POST请求正常进行,而不必调用您的修改代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.