我正在编写一个程序(对于 Mac OS X,使用 Objective-C),我需要以编程方式创建一堆 .webloc 文件。
.webloc 文件是在您将 URL 从 Safari 的位置栏拖放到某个文件夹后创建的简单文件。
一般来说,我需要一种方法来在文件系统中创建指向 Web 中某个位置的项目。据我了解,应该在 Mac OS X 上使用 .webloc 文件。
那么,是否可以制作一个具有有效 url 和一些标题的 .webloc 文件?
我正在编写一个程序(对于 Mac OS X,使用 Objective-C),我需要以编程方式创建一堆 .webloc 文件。
.webloc 文件是在您将 URL 从 Safari 的位置栏拖放到某个文件夹后创建的简单文件。
一般来说,我需要一种方法来在文件系统中创建指向 Web 中某个位置的项目。据我了解,应该在 Mac OS X 上使用 .webloc 文件。
那么,是否可以制作一个具有有效 url 和一些标题的 .webloc 文件?
它鲜为人知 - 但也有一个简单的基于 plist 的 weblocs 文件格式。
创建 webloc 文件时,您不需要使用其他三张海报描述的资源方法来保存它们。你也可以写一个简单的plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>URL</key>
<string>http://apple.com</string>
</dict>
</plist>
二进制资源格式仍在使用中,如果您想读取 plist 文件 - 那么请确保您需要读取这两种文件格式。但是在编写文件时 - 使用基于 plist 的格式 - 它要容易得多。
文件的.webloc
数据叉中没有任何内容;相反,它将它引用的 URL 作为资源存储在其资源分支中。您可以使用DeRez(1)工具在命令行上看到这一点
.webloc
在这里,我针对这个问题从 Safari 地址栏中拖出的文件运行了它:
% DeRez "Desktop/Crafting .webloc file - Stack Overflow.webloc"
data 'drag' (128, "Crafting .webloc file -#1701953") {
$"0000 0001 0000 0000 0000 0000 0000 0003" /* ................ */
$"5445 5854 0000 0100 0000 0000 0000 0000" /* TEXT............ */
$"7572 6C20 0000 0100 0000 0000 0000 0000" /* url ............ */
$"7572 6C6E 0000 0100 0000 0000 0000 0000" /* urln............ */
};
data 'url ' (256, "Crafting .webloc file -#1701953") {
$"6874 7470 3A2F 2F73 7461 636B 6F76 6572" /* http://stackover */
$"666C 6F77 2E63 6F6D 2F71 7565 7374 696F" /* flow.com/questio */
$"6E73 2F31 3436 3537 352F 6372 6166 7469" /* ns/146575/crafti */
$"6E67 2D77 6562 6C6F 632D 6669 6C65" /* ng-webloc-file */
};
data 'TEXT' (256, "Crafting .webloc file -#1701953") {
$"6874 7470 3A2F 2F73 7461 636B 6F76 6572" /* http://stackover */
$"666C 6F77 2E63 6F6D 2F71 7565 7374 696F" /* flow.com/questio */
$"6E73 2F31 3436 3537 352F 6372 6166 7469" /* ns/146575/crafti */
$"6E67 2D77 6562 6C6F 632D 6669 6C65" /* ng-webloc-file */
};
data 'urln' (256, "Crafting .webloc file -#1701953") {
$"4372 6166 7469 6E67 202E 7765 626C 6F63" /* Crafting .webloc */
$"2066 696C 6520 2D20 5374 6163 6B20 4F76" /* file - Stack Ov */
$"6572 666C 6F77" /* erflow */
};
唯一可能需要在其中的资源是 ID 256 的'url '
和'TEXT'
资源,这些资源可能也不需要资源名称。'urln'
如果您还想包含 URL 指向的文档的标题,该资源可能会很方便。该'drag'
资源告诉系统这是一个剪辑文件,但我不确定在这个时代是否需要它。
要使用资源和文件的资源分支,您可以使用资源管理器——Carbon 的底层部分之一,它可以追溯到原始 Mac。然而,资源管理器有几个 Cocoa 包装器,例如Nathan Day 的 NDResourceFork。
.webloc
文件(更一般地,Internet 位置文件)以其定义可追溯到 Mac OS 8.x 的格式编写。它是基于资源的,源自您从拖动的对象(如文本或图像)创建文件时获得的剪辑格式。
写入的资源是存储 URL 的'url '
256 和'TEXT'
256,以及可选的 'urln' 256,包含与 URL 关联的文本。 'drag'
128 指向其他两个(或三个)资源。
NTWeblocFile 是Cocoatech 开源框架CocoaTechFoundation(BSD 许可)的一部分,支持从 Objective-C 编写这些文件。如果您想为 URL 单独指定标题,则需要修改该类,以便它将 URL 以外的内容写入'urln'
资源中。
在 Mac OS X 10.3 和更高版本中,URL 也被写入(也可能被写入)到文件数据分支的属性列表中。请参阅其他答案以了解其工作原理...
另一种制作“网络快捷方式”的方法是.url
这里已经提到的文件。
内容看起来像(比基于 plist xml 的简单得多):
[InternetShortcut]
URL=http://www.apple.com/
注意文件有 3 行,最后一行是空的。
它使用基于资源叉的二进制格式。
有效的解决方法:
以下是谷歌浏览器的做法:WriteURLToNewWebLocFileResourceFork
这完成了基本任务,不需要任何第三方库。(警告:最小的错误检查。)
// data for 'drag' resource (it's always the same)
#define DRAG_DATA_LENGTH 64
static const unsigned char _dragData[DRAG_DATA_LENGTH]={
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
0x54, 0x45, 0x58, 0x54, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x75, 0x72, 0x6C, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x75, 0x72, 0x6C, 0x6E, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static void _addData(NSData *data, ResType type, short resId, ResFileRefNum refNum)
{
Handle handle;
if (PtrToHand([data bytes], &handle, [data length])==noErr) {
ResFileRefNum previousRefNum=CurResFile();
UseResFile(refNum);
HLock(handle);
AddResource(handle, type, resId, "\p");
HUnlock(handle);
UseResFile(previousRefNum);
}
}
void WeblocCreateFile(NSString *location, NSString *name, NSURL *fileUrl)
{
NSString *contents=[NSString stringWithFormat:
@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
@"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
@"<plist version=\"1.0\">\n"
@"<dict>\n"
@"<key>URL</key>\n"
@"<string>%@</string>\n"
@"</dict>\n"
@"</plist>\n", location];
if ([[contents dataUsingEncoding:NSUTF8StringEncoding] writeToURL:fileUrl options:NSDataWritingAtomic error:nil])
{
// split into parent and filename parts
NSString *parentPath=[[fileUrl URLByDeletingLastPathComponent] path];
NSString *fileName=[fileUrl lastPathComponent];
FSRef parentRef;
if(FSPathMakeRef((const UInt8 *)[parentPath fileSystemRepresentation], &parentRef, NULL)==noErr)
{
unichar fileNameBuffer[[fileName length]];
[fileName getCharacters:fileNameBuffer];
FSCreateResFile(&parentRef, [fileName length], fileNameBuffer, 0, NULL, NULL, NULL);
if (ResError()==noErr)
{
FSRef fileRef;
if(FSPathMakeRef((const UInt8 *)[[fileUrl path] fileSystemRepresentation], &fileRef, NULL)==noErr)
{
ResFileRefNum resFileReference = FSOpenResFile(&fileRef, fsWrPerm);
if (resFileReference>0 && ResError()==noErr)
{
_addData([NSData dataWithBytes:_dragData length:DRAG_DATA_LENGTH], 'drag', 128, resFileReference);
_addData([location dataUsingEncoding:NSUTF8StringEncoding], 'url ', 256, resFileReference);
_addData([location dataUsingEncoding:NSUTF8StringEncoding], 'TEXT', 256, resFileReference);
_addData([name dataUsingEncoding:NSUTF8StringEncoding], 'urln', 256, resFileReference);
CloseResFile(resFileReference);
}
}
}
}
}
}