Evernote IOS SDK fetchResourceByHashWith 抛出异常

Evernote IOS SDK fetchResourceByHashWith throws exception

使用 Evernote IOS SDK 3.0 我想使用

从笔记中检索特定资源
fetchResourceByHashWith

这就是我的使用方式。仅针对此示例,为了 100% 确定哈希值的正确性,我首先使用 fetchNote 使用单个资源下载笔记,然后使用 fetchResourceByHashWith 使用其唯一哈希值请求该资源(当哈希看起来正确时我打印它)

ENSession.shared.primaryNoteStore()?.fetchNote(withGuid: guid, includingContent: true, resourceOptions: ENResourceFetchOption.includeData, completion: { note, error in
            if error != nil {
                print(error)
                seal.reject(error!)
            } else {
                let hash = note?.resources[0].data.bodyHash
                ENSession.shared.primaryNoteStore()?.fetchResourceByHashWith(guid: guid, contentHash: hash, options: ENResourceFetchOption.includeData, completion: { res, error in
                    if error != nil {
                        print(error)
                        seal.reject(error!)
                    } else {
                        print("works")
                        seal.fulfill(res!)
                    }})
            }
        })

调用 fetchResourceByHashWith 失败

Optional(Error Domain=ENErrorDomain Code=0 "Unknown error" UserInfo={EDAMErrorCode=0, NSLocalizedDescription=Unknown error})

等效设置适用于 Android SDK。 到目前为止,其他一切都在 IOS SDK 中工作(chunkSync、auth、获取笔记本等。所以这不是 auth 令牌的问题)

很高兴知道这是 sdk 错误还是我仍然做错了什么。

谢谢

这是 SDK "EDAM" Thrift 客户端存根代码中的错误。首先是分析,然后是您的解决方法。

Evernote 的底层 API 传输使用带有 documented schema. The SDK framework includes a layer of autogenerated stub code that is supposed to marshal input and output params correctly for each request and response. You are invoking the underlying getResourceByHash API method on the note store, which is defined per the docs to accept a string type for the contentHash argument. But it turns out the client is sending the hash value as a purely binary field. The service is failing to parse the request, so you're seeing a generic error on the client. This could reflect evolution in the API definition, but more likely this has always been broken in the iOS SDK (getResourceByHash probably doesn't see a lot of usage). If you dig into the more recent Python version of the SDK, or indeed also the Java/Android version 的 Thrift 协议,您可以看到此方法的不同模式:它 它会写一个字符串类型的字段,然后实际上 发出 一个二进制的。奇怪的是,这有效。如果你破解 iOS SDK 来做同样的事情,它也会工作。


解决方法:

  1. 最好的建议是报告错误,并且在笔记商店上避免使用这种方法。您可以通过不同的方式获取资源数据:首先,您实际上在响应 fetchNote 调用时获得了所需的所有数据,即 let resourceData = note?.resources[0].data.body,这很好!您还可以使用 他们自己的 guid(不是他们的散列)来提取个人资源,使用 fetchResource(使用 note?.resources[0].guid 作为参数)。当然,您可能真的想使用散列访问模式。那样的话...

  2. 您可以破解正确的协议行为。在您需要作为项目的一部分构建的 SDK 文件中,找到名为 ENTProtocol.m 的 ObjC 文件。找到方法+sendMessage:toProtocol:withArguments

它有一行是这样的:

[outProtocol writeFieldBeginWithName:field.name type:field.type fieldID:field.index];

将该行替换为:

[outProtocol writeFieldBeginWithName:field.name type:(field.type == TType_BINARY ? TType_STRING : field.type) fieldID:field.index];

重新生成项目,您应该会发现您的代码片段按预期工作。 然而,这是一个巨大的 hack,虽然我不认为任何其他笔记存储方法会受到它的不利影响,但其他内部用户存储或其他调用可能会突然开始变得有趣.此外,您还必须通过更新来维护黑客攻击。在 Evernote 发布适当的修复程序之前,最好报告错误并且不要使用该方法。