对于数据恢复程序,我需要能够从 NSArchiver 编写的文件中提取值+类型,而无需访问 Apple 的 CF / NS 框架。
操作系统Xfile
命令报告此类文件:
NeXT/Apple typedstream data, little endian, version 4, system 1000
是否有关于如何编码这些文件的任何文档,或者是否有人提出了可以解析它们的代码?
这是此类数据的示例(另外:可下载 http://files.tempel.org/Various/NSArchiver_sample.hex):
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 [email protected] /cdn-cgi/l/email-protection
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
}
但是,上述代码存在几个问题:
- 这不是x平台。我也需要这个在 Windows 上工作。
- 某些损坏数据的示例会导致将不需要的错误消息写入 stderr 或 syslog(不确定是哪一个),例如:
*** mmap(size=18446744071608111104) failed (error code=12) *** error: can't allocate region *** set a breakpoint in malloc_error_break to debug
(我提交了一份关于此问题的错误报告,遗憾的是该报告被关闭为“无法修复”)。
- 没有什么可以保证 NSUnarchiver 代码 100% 不会崩溃。 malloc 错误就是一个例子。在某些情况下我可能会遇到总线错误,这将是致命的。如果我有用于解析的自定义代码,我可以自己处理(并修复我遇到的任何崩溃)。 (更新:我刚刚发现一些无效数据确实会因 SIGSEGV 导致 NSUnarchiver 崩溃。)
因此,我需要自定义代码来解码这些类型的档案。我看过一些,但无法理解它使用的代码。显然,有长度字段和类型字段,显然类型的范围在 0x81 到 0x86 之间。另外,前 16 个字节是标头,包括偏移量 14-15 处的系统代码 (0x03E8 = 1000)。
我还想知道源代码是否可以在一些旧的 NeXT 源或曾经存在的 Windows 版本中找到,但我在哪里可以找到呢? (注意:我被定向到 GNUstep 源代码(“core.20131003.tar.bz2”),在其中我找到了它的 NSUnarchiver 源代码,但是该代码显然是 1998 年的,使用它自己的编码,它不理解这个“流类型” ” 编码。)