ios - 检查类型为 "NeXT/Apple typedstream"版本 4 (NSArchiver) 的文件

标签 ios objective-c macos nscoding nsarchiving

对于数据恢复程序,我需要能够从 NSArchiver 写入的文件中提取值和类型,而无需访问 Apple 的 CF/NS 框架。

OS X file 命令报告这样的文件:

NeXT/Apple typedstream data, little endian, version 4, system 1000

是否有任何文档说明这些文件是如何编码的,或者有没有人想出可以解析它们的代码?

这是此类数据的示例(也为:downloadable):

04 0B 73 74 72 65 61 6D 74 79 70 65 64 81 E8 03  ..streamtyped...
84 01 40 84 84 84 12 4E 53 41 74 74 72 69 62 75  ..@....NSAttribu
74 65 64 53 74 72 69 6E 67 00 84 84 08 4E 53 4F  tedString....NSO
62 6A 65 63 74 00 85 92 84 84 84 08 4E 53 53 74  bject.......NSSt
72 69 6E 67 01 94 84 01 2B 06 46 65 73 6B 65 72  ring....+.Fesker
86 84 02 69 49 01 06 92 84 84 84 0C 4E 53 44 69  ...iI.......NSDi
63 74 69 6F 6E 61 72 79 00 94 84 01 69 01 92 84  ctionary....i...
96 96 1D 5F 5F 6B 49 4D 4D 65 73 73 61 67 65 50  ...__kIMMessageP
61 72 74 41 74 74 72 69 62 75 74 65 4E 61 6D 65  artAttributeName
86 92 84 84 84 08 4E 53 4E 75 6D 62 65 72 00 84  ......NSNumber..
84 07 4E 53 56 61 6C 75 65 00 94 84 01 2A 84 99  ..NSValue....*..
99 00 86 86 86                                   .....

这包含一个 NSAttributedString。我有类似的示例,其中包含 NSMutableAttributedStrings 等,但最终都解析为 NSAttributedStrings,我喜欢获取文本。我不关心其余部分,但我需要知道它是否有效。

我目前的解决方案是使用 NSUnarchiver,假设我总能在其中找到一个 NSAttributedString,获取它的第一个元素并读取它的文本,然后从中重新创建一个存档,看看它是否与原始数据相同。如果我收到异常或返回不同的存档,我认为存档已损坏或无效:

NSData *data = [[NSData alloc] initWithBytesNoCopy:dataPtr length:dataLen freeWhenDone:false];
NSUnarchiver *a = NULL;

// The algorithm simply assumes that the data contains a NSAttributedString, retrieves it,
// and then recreates the NSArchived version from it in order to tell its size.
@try {
    a = [[NSUnarchiver alloc] initForReadingWithData:data];
    NSAttributedString *s = [a decodeObject];

    // re-encode the string item so we can tell its length
    NSData *d = [NSArchiver archivedDataWithRootObject:s];
    if ([d isEqualTo:[data subdataWithRange:NSMakeRange(0,d.length)]]) {
        lenOut = (int) d.length;
        okay = true; // -> lenOut is valid, though textOut might still fail, see @catch below
        textOut = [s.string cStringUsingEncoding:NSUTF8StringEncoding];
    } else {
        // oops, we don't get back what we had as input, so let's better not consider this valid
    }
} @catch (NSException *e) {
    // data is invalid
}

但是,上面的代码有几个问题:

  1. 它不是 x 平台。我也需要它才能在 Windows 上运行。
  2. 一些损坏数据的示例导致写入 stderr 或系统日志(不确定是哪个)的不需要的错误消息,例如:*** mmap(size=18446744071608111104) 失败(错误代码=12)*** 错误: 无法分配区域 *** 在 malloc_error_break 中设置一个断点进行调试(我提交了一份关于此的错误报告,遗憾的是,该错误报告已关闭,因为“无法修复”)。
  3. 没有什么能保证 NSUnarchiver 代码是 100% 防崩溃的。 malloc 错误就是一个例子。在某些情况下,我还不如得到一个总线错误,那将是致命的。如果我有用于解析的自定义代码,我可以自己处理(并修复我遇到的任何崩溃)。 (更新:我刚刚发现一些无效数据确实使 NSUnarchiver 崩溃并带有 SIGSEGV。)

因此,我需要自定义代码来解码这些类型的文件。我看过一些,但无法理解它使用的代码。显然,有长度字段和类型字段,类型显然在 0x81 到 0x86 之间。此外,前 16 个字节是 header ,包括偏移量 14-15 处的系统代码 (0x03E8 = 1000)。

我也想知道源代码是否在一些旧的 NeXT 源或曾经存在的 Windows 版本中可用,但我在哪里可以找到它? (注意:我被定向到 GNUstep 源代码(“core.20131003.tar.bz2”),我在其中找到了它的 NSUnarchiver 源代码,但该代码显然是从 1998 年开始的,使用了它自己的编码,这不是理解这种“流式”编码。)

最佳答案

虽然我不知道该格式的任何文档,但您可以通过检查旧版 Darwin(或可能是 OpenStep)版本的公共(public)源代码来找到您正在寻找的信息。

例如,查看 objc-1.tar.gz 中的 typedstream.m 文件中 typedstream 的实现在 this mirror of an old darwin distribution .

此源代码应该能够读/写typedstream。请务必在使用时确认 Apple 的许可证。

关于ios - 检查类型为 "NeXT/Apple typedstream"版本 4 (NSArchiver) 的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18834352/

相关文章:

ios - 如何将按钮旋转回水平方向?

ios - 两个 View 之间的转换适用于 iOS8,但不适用于 iOS9

ios - 无法使用 Storyboard 设置将出现在 App Startup 上的第一个 View Controller

iphone - 如何检测 AVCaptureDevice 的闪光灯何时完成以及静止图像捕获何时开始?

macos - 是否可以将 pyobjc 与特权 XPC 帮助工具和 XPCInterface API 一起使用?

ios - 关于ScrollView与PageControl的几个问题

ios - Sprite Kit SKSpriteNode 绘制在屏幕外

ios - 如何检查 NSTimer 是否已经失效

python - 如何使用 Pyinstaller 打包的 Kivy Python 应用程序在 OSX 菜单栏中创建菜单项?

python - 导入错误 : No Module named six; six already installed