使用loadOneTab复制Form方法 [英] Replication of Form method with loadOneTab

查看:156
本文介绍了使用loadOneTab复制Form方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



下面是表单代码的一个例子:

p>

 < form target =_ blankenctype =multipart / form-data
action =https:// www.example.com/method =POST>
< input value =data:image / png; base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4 // 8 / w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg ==name =image_contenttype =hidden>
< input value =name =filenametype =hidden>
< input value =name =image_urltype =hidden>
< / form>

当我尝试使用 loadOneTab(),结果 POST 不完全相同,因此结果与上面不一样。
在检查标题时,价值不完全发送(获得裁剪),它设置 Content-Length:0

我必须缺少的东西。

  let postStream = Components.classes ['@ mozilla.org/network/mime-input-stream; 1'] 
.createInstance Components.interfaces.nsIMIMEInputStream);
postStream.addHeader('Content-Type','multipart / form-data');
postStream.addHeader('filename','');
postStream.addHeader('image_url','');
postStream.addHeader('image_content','data:image / png; base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4 // 8 / w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg ==');
postStream.addContentLength = true;
window.gBrowser.loadOneTab('https://www.example.com/',
{inBackground:false,postData:postStream});

注意:image_content值为'data:image / png; base64'数据URI

NoScript会导致发送表单和XSS的问题,我更喜欢使用 loadOneTab 作为 inBackground FormData 来组成 code> postData 的请求,但不幸的是我们不能这样做,因为目前没有办法从 FormData 实例( nsIXHRSendable 不可写,不幸的是),所以我们必须创建一个 multipart / form-data 流自己。

由于您可能还想发布一些文件数据,所以我也添加了文件上传。 ;)

 函数encodeFormData(data,charset){
let encoder = Cc [@ mozilla.org/intl / saveascharset; 1\" ]。
createInstance(Ci.nsISaveAsCharset);
encoder.Init(charset ||utf-8,
Ci.nsISaveAsCharset.attr_EntityAfterCharsetConv +
Ci.nsISaveAsCharset.attr_FallbackDecimalNCR,
0);
let encode = function(val,header){
val = encoder.Convert(val);
if(header){
val = val.replace(/ \r\\\
/ g,).replace(// g,\\\\) ;
}
return val;
}

let boundary =---- boundary--+ Date.now();
让mpis = Cc ['@ mozilla.org/io/multiplex-input-stream; 1']。
createInstance(Ci.nsIMultiplexInputStream);
let item =;
for(let k of Object.keys(data)){
item + = - + boundary +\r\\\
;
let v = data [k];
如果(v实例Ci.nsIFile){
让fstream = Cc [@ mozilla.org/network/file-input-stream; 1]。
createInstance(Ci.nsIFileInputStream);
fstream.init(v,-1,-1,Ci.nsIFileInputStream.DEFER_OPEN);
item + =Content-Disposition:form-data; name = \+ encode(k,true)+\; +
filename = \+ encode(v.leafName,true)+\\r\\\
;
让ctype =application / octet-stream;
尝试{
let mime = Cc [@ mozilla.org/mime;1\"].getService(Ci.nsIMIMEService);
ctype = mime.getTypeFromFile(v)|| CTYPE;
}
catch(ex){
console.warn(failed to get type,ex);
}
item + =Content-Type:+ ctype +\r\\\
\r\\\
;
让ss = Cc [@ mozilla.org/io/string-input-stream; 1]。
createInstance(Ci.nsIStringInputStream);
ss.data = item;
mpis.appendStream(ss);
mpis.appendStream(fstream);
item =;
$ b $ else {
item + =Content-Disposition:form-data; name = \+ encode(k,true)+\\r\ n\r\\\
;
item + = encode(v);
}
item + =\r\\\
;
}
item + = - + boundary +--\r\\\
;
让ss = Cc [@ mozilla.org/io/string-input-stream; 1]。
createInstance(Ci.nsIStringInputStream);
ss.data = item;
mpis.appendStream(ss);
让postStream = Cc [@ mozilla.org/network/mime-input-stream; 1]。
createInstance(Ci.nsIMIMEInputStream);
postStream.addHeader(Content-Type,
multipart / form-data; boundary =+ boundary);
postStream.setData(mpis);
postStream.addContentLength = true;
返回postStream;



$ b $您可以使用额外的 nsIMIMEInputStream 而不是字符串连接在一起的东西,但这会更糟糕,没有真正的优点)。

然后可以使用如:

  let file = Services.dirsvc.get(Desk,Ci.nsIFile); 
file.append(australis-xphällow,wörld.png);

让postData = encodeFormData({
filename:,
image_url:,
image_content:--somne​​ value - - ,
contents:文件
},iso8859-1);

gBrowser.loadOneTab(http://www.example.org/,{
inBackground:false,
postData:postData
});


If I dynamically insert a form object into a page, submit and remove the form and it works fine.

Here is an example of the form code:

<form target="_blank" enctype="multipart/form-data" 
      action="https://www.example.com/" method="POST">
  <input value="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" name="image_content" type="hidden">
  <input value="" name="filename" type="hidden">
  <input value="" name="image_url" type="hidden">
</form>

When I try to do the same process with loadOneTab(), result POST is not exactly the same and therefore the result is not the same as above.
On checking the headers, "some value" is not sent fully (gets cropped) and it sets Content-Length: 0.
I must be missing something.

let postStream = Components.classes['@mozilla.org/network/mime-input-stream;1']
                   .createInstance(Components.interfaces.nsIMIMEInputStream);
postStream.addHeader('Content-Type', 'multipart/form-data');
postStream.addHeader('filename', '');
postStream.addHeader('image_url', '');
postStream.addHeader('image_content', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==');
postStream.addContentLength = true;
window.gBrowser.loadOneTab('https://www.example.com/',
    {inBackground: false, postData: postStream});

Note: image_content value is 'data:image/png;base64' Data URI
NoScript causes issues with sending form and XSS and I prefer to use loadOneTab for the inBackground

解决方案

Normally, one would use FormData to compose the postData of a request, but unfortunately we cannot do so here, as there is currently no way to get the stream (and other information) from a FormData instance (nsIXHRSendable is not scriptable, unfortunately), so we'll have to create a multipart/form-data stream ourselves.

Since it is likely you'll want to post some file data as well, I added file uploads as well. ;)

function encodeFormData(data, charset) {
  let encoder = Cc["@mozilla.org/intl/saveascharset;1"].
                createInstance(Ci.nsISaveAsCharset);
  encoder.Init(charset || "utf-8",
               Ci.nsISaveAsCharset.attr_EntityAfterCharsetConv + 
               Ci.nsISaveAsCharset.attr_FallbackDecimalNCR,
               0);
  let encode = function(val, header) {
    val = encoder.Convert(val);
    if (header) {
      val = val.replace(/\r\n/g, " ").replace(/"/g, "\\\"");
    }
    return val;
  }

  let boundary = "----boundary--" + Date.now();
  let mpis = Cc['@mozilla.org/io/multiplex-input-stream;1'].
             createInstance(Ci.nsIMultiplexInputStream);
  let item = "";
  for (let k of Object.keys(data)) {
    item += "--" + boundary + "\r\n";
    let v = data[k];
    if (v instanceof Ci.nsIFile) {
      let fstream = Cc["@mozilla.org/network/file-input-stream;1"].
                    createInstance(Ci.nsIFileInputStream); 
      fstream.init(v, -1, -1, Ci.nsIFileInputStream.DEFER_OPEN);
      item += "Content-Disposition: form-data; name=\"" + encode(k, true) + "\";" +
              " filename=\"" + encode(v.leafName, true) + "\"\r\n";
      let ctype = "application/octet-stream";
      try {
        let mime = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
        ctype = mime.getTypeFromFile(v) || ctype;
      }
      catch (ex) {
        console.warn("failed to get type", ex);
      }
      item += "Content-Type: " + ctype + "\r\n\r\n";
      let ss = Cc["@mozilla.org/io/string-input-stream;1"].
               createInstance(Ci.nsIStringInputStream);
      ss.data = item;
      mpis.appendStream(ss);
      mpis.appendStream(fstream);
      item = "";
    }
    else {
      item += "Content-Disposition: form-data; name=\"" + encode(k, true) + "\"\r\n\r\n";
      item += encode(v);
    }
    item += "\r\n";
  }
  item += "--" + boundary + "--\r\n";
  let ss = Cc["@mozilla.org/io/string-input-stream;1"].
           createInstance(Ci.nsIStringInputStream);
  ss.data = item;
  mpis.appendStream(ss);
  let postStream = Cc["@mozilla.org/network/mime-input-stream;1"].
                   createInstance(Ci.nsIMIMEInputStream);
  postStream.addHeader("Content-Type",
                       "multipart/form-data; boundary=" + boundary);
  postStream.setData(mpis);
  postStream.addContentLength = true;
  return postStream;
}

(You could use additional nsIMIMEInputStream instead of string-concatenating stuff together, but this would perform worse and has no real merit).

Which can then be used like e.g.:

let file = Services.dirsvc.get("Desk", Ci.nsIFile);
file.append("australis-xp hällow, wörld.png");

let postData = encodeFormData({
  "filename": "",
  "image_url": "",
  "image_content": "--somne value ---",
  "contents": file
}, "iso8859-1");

gBrowser.loadOneTab("http://www.example.org/", {
  inBackground: false,
  postData: postData
});

这篇关于使用loadOneTab复制Form方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆