当前位置: 首页 > 知识库问答 >
问题:

通过Thrift从Chrome扩展保存到Evernote的二进制文件在Unicode转换后被篡改

裴良弼
2023-03-14

编辑:这个问题归结为UTF-8转换,请在这里讨论:UTF-8:它应该持有那个string=encode(decode(string))吗?如果不是,如何实现?

我正试图使用非官方的神田软件API将一个PDF文件从Chrome扩展保存到Evernote。本质上,它使用Thrift,并提供根据Evernote API创建和发送数据结构的方法。为了进行测试,我使用了一个字节长度为2898的示例PDF文件。

调用CreateNote()方法时,数据最终会进入SDK的thrift.js,在那里它被UTF编码并放置到适当的数据结构中。这些函数被调用:

    writeString:function(str) {
        var result = Array.prototype.map.call(this.encode(str).split(""), this.stringToHex); // <----- I tried to skip this encoding for the data body
        this.writeI32(result.length);
        for (var i = 0; i < result.length; i++) {
            this.ra.push(result[i]);
        }
    },
...
    encode:function(string) {
        string = string.replace(/\r\n/g, "\n");
        var utftext = "";
        for (var n = 0; n < string.length; n++) {

            var c = string.charCodeAt(n);

            if (c < 128) {
                utftext += String.fromCharCode(c);
            }
            else if ((c > 127) && (c < 2048)) {
                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);
            }
            else {
                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);
            }
        }
        return utftext;
    },
...
    writeI32:function(i32) {
        var i32out = new Array();
        i32out[0] = 0xff & i32 >> 24;
        i32out[1] = 0xff & i32 >> 16;
        i32out[2] = 0xff & i32 >> 8;
        i32out[3] = 0xff & i32;

        var result = Array.prototype.map.call(i32out, this.byteToHex);
        for (var i = 0; i < 4; i++) {
            this.ra.push(result[i]);
        }

    },

我真的不明白Thrift在这个级别上是如何工作的,为什么它需要对包括二进制附件正文在内的所有数据进行编码,但正如您所看到的,它会导致PDF的数据(以及所有其他要传输的字符串数据)被UTF编码,所以.长度现在是3018字节。这一切都通过API,文件显示在Evernote前端(见图),但它没有被解码回来,大小为3018字节,所以PDF搞砸了。

Evernote前端的结果图像

我试图通过跳过仅对数据体的encode()调用来强制解决方案,但这会导致文件以某种方式被丢弃。

你能告诉我问题是来自我的误解、SDK还是Evernote后端,以及如何修复它吗?我为此失眠了。

供参考:我通过XMLHttpRequest获取原始文件,如下所示:

function getLink(url, callback) {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', document.getElementById('url1').value, true);
  xhr.responseType = 'text';
  xhr.overrideMimeType('text/plain; charset=x-user-defined');

  xhr.onload = function(e) {
    if (this.status == 200) {
      // Note: .response instead of .responseText
      alert("String(this.response) " + String(this.response).length);
      alert("String(this.responseText) " + String(this.responseText).length);
      blob = String(this.response);
      AddNote1(url, blob, function(response) {
        document.getElementById('result').innerHTML += String(response).replace(/\n/g, "<br/>") + "<br/>";
        document.getElementById('result').innerHTML += blob.slice(1, 20);
        } );
      }
    };
  xhr.send();
  }

结果数据看起来正常,字符串也正常。长度为2898。然后,我继续添加示例中描述的注释。同样,它检查得很好,字节字符串完整地进入CreateNote(),因此这再次仅供参考:

function AddNote1(Name, ContentFile, callback)
{
    var noteStore = get_NoteStore();
    var note = new Note();
    note.title = Name;
    var na = new NoteAttributes();
    //na.author = "someone";
    na.sourceURL = Name;
    na.source = "web.clip";
    note.attributes = na;

    var data = new Data();
    var resource = new Resource();
    binaryData = ContentFile;
    data.size = binaryData.length;
    alert(binaryData.length + '*' + ContentFile.length);
    data.bodyHash = raw_md5(binaryData);
    data.body = binaryData;
    resource.mime = "application/pdf";
    resource.data = data;
    var resAttributes = new ResourceAttributes();
    resAttributes.fileName = String(Name).replace(/^.*[\/\\]/g, '');
    resource.attributes = resAttributes;
    note.resources = Array(resource);
    //important to set correct content
    var content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
        + "<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml2.dtd\"><en-note>";
    content += String("Oi Wei").replace(/\n/g, "<br/>") + "<br/>";
    content += "<en-media type=\"application/pdf\" hash=\"" + md5(binaryData) + "\"/>";
    content += "</en-note>";
    note.content = content;
    //response is a created note
    //callback function process response
    var response = noteStore.createNote(Eventnote.Auth.get_auth_token(), note);
    if (callback !== undefined) {
      callback(response);
      }

共有1个答案

纪正德
2023-03-14

是否有任何Javascript utf8\u decode()实现没有此问题?

从这里拍摄:

function encode_utf8( s )
{
  return unescape( encodeURIComponent( s ) );
}

function decode_utf8( s )
{
  return decodeURIComponent( escape( s ) );
}
 类似资料:
  • 我已经创建了一个chrome扩展来学习英语,它可以构建一个包含源代码/翻译等的词典。 现在,我想将这个“文件”(我将/会用字典条目构建一个“文件”)发送到Google Drive,并在我的Android应用程序中使用这个文件。 但我不想将此文件保存在我的个人驱动器帐户中,而是保存在当前用户的驱动器中,即使用chrome扩展名的用户(当然,如果该用户有驱动器帐户)。 在我找到的所有例子中,他们为“我

  • 问题内容: 如何将文件转换为二进制文件?我的项目只需要它。我需要通过二进制文件加密文件。 问题答案: 如果您要访问ACTUAL BINARY形式,则读入文件并将每个字节转换为二进制表示形式… 编辑: 以下是一些代码,可将字节转换为带有位的字符串: 如果要访问文件中的字节,则只需使用以下代码(在第一种情况下也可以使用此代码): 要使用这两段代码,您现在可以遍历每个字节并使用以下位创建一个String

  • 问题内容: 我为数据库中的存储过程生成了完整的脚本集。当我创建Mercurial存储库并添加这些文件时,它们都以二进制形式添加。显然,我仍然可以获得版本控制的好处,但是会损失很多效率,文本文件的“差异化”等。我验证了这些文件的确只是文本。 为什么这样做呢? 我应该怎么做才能避免这种情况? 有没有办法让汞改变他们对这些文件的看法? 这是变更集日志的片段: 预先感谢您的帮助吉姆 问题答案: 为了符合M

  • 本文向大家介绍十进制到二进制转换,包括了十进制到二进制转换的使用技巧和注意事项,需要的朋友参考一下 十进制数字也可以转换为二进制格式。要将十进制数转换为二进制数,我们需要将数字除以2,直到达到0或1。然后,在每一步骤中,其余部分将分开存储以形成相反的二进制等效数。 在此算法中,我们将遵循递归方法。这将帮助我们在不使用堆栈数据结构的情况下解决问题。在实现中,我们知道函数的递归将遵循内部堆栈。我们将使

  • 一个朋友提出了这个挑战。只是为了训练,我试图使用反应式扩展来解决它,但我没有运气。这并不奇怪,因为我还是Rx的新手。 这就是问题所在: 正整数N内的孔径是其二进制表示中的任意连续零的最大序列,其两端被1包围。 例如,数字9具有二进制表示1001,并且包含长度为2的光圈。数字529具有二进制表示100001001,包含两个光圈:一个是长度4,一个是长度3。数字20具有二进制表示10100,包含一个长

  • 我正在编写一个C#程序,将MS SQL Server2008R2中的一个表中的所有数据复制到MySQL中的一个表中。我正在使用,并从第一个表中用以下代码填充它: +----------------------------------------------------------------------------------------------------------------------