Objective c 制作.webloc文件

Objective c 制作.webloc文件,objective-c,cocoa,macos,macos-carbon,Objective C,Cocoa,Macos,Macos Carbon,我正在编写一个程序(针对MacOSX,使用Objective-C),我需要以编程方式创建一组.webloc文件 .webloc文件只是在您将URL从Safari的位置栏拖放到某个文件夹后创建的文件 一般来说,我需要一种在文件系统中创建指向Web中某个位置的项的方法。据我所知,在Mac OS X上应该使用.webloc文件 那么,是否可以创建一个具有有效url和标题的.webloc文件?它使用基于资源叉的二进制格式 有效的解决办法: 让用户将URL从应用程序(NSURLPBARDTYPE)拖动到

我正在编写一个程序(针对MacOSX,使用Objective-C),我需要以编程方式创建一组.webloc文件

.webloc文件只是在您将URL从Safari的位置栏拖放到某个文件夹后创建的文件

一般来说,我需要一种在文件系统中创建指向Web中某个位置的项的方法。据我所知,在Mac OS X上应该使用.webloc文件


那么,是否可以创建一个具有有效url和标题的.webloc文件?

它使用基于资源叉的二进制格式

有效的解决办法:

  • 让用户将URL从应用程序(NSURLPBARDTYPE)拖动到查找程序。Finder将为您创建一个webloc
  • 创建Windows Web快捷方式(.URL文件)。这些文件具有类似INI的基于数据叉的格式,应该记录在互联网上的某个地方;操作系统支持webloc,也支持webloc

A
.webloc
文件的数据叉中没有任何内容;相反,它将引用为资源的URL存储在其资源分支中。您可以使用该工具在命令行上看到这一点

在这里,我在一个
.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'
资源,这些资源可能也不需要资源名称。如果您还想包含URL指向的文档的标题,那么
'urln'
资源可能很方便。
'drag'
资源告诉系统这是一个剪辑文件,但我不确定它在当今时代是否需要存在


要使用资源和文件的资源分支,您可以使用资源管理器—一个可以追溯到原始Mac的底层碳块。但是,资源管理器有几个Cocoa包装,例如。

。webloc
文件(更一般地说,是Internet位置文件)是以定义可追溯到Mac OS 8.x的格式编写的。它基于资源,源于从拖动的对象(如文本或图像)创建文件时获得的剪辑格式

编写的资源是存储url的
'url'
256和
'TEXT'
256,也可以是包含与url关联的文本的“urln”256<代码>“拖动”128个点到其他两个(或三个)资源

CocoaTechFoundation(BSD许可)的一部分NTWeblocFile支持从Objective-C写入这些文件。如果要单独为URL指定标题,则需要修改该类,使其将URL以外的内容写入
'urln'
资源


在Mac OS X 10.3及更高版本中,URL也会写入(也可以写入)文件数据叉中的属性列表。请参阅另一个答案,了解其工作原理。

这是鲜为人知的,但也有一种简单的基于plist的webloc文件格式

创建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>

统一资源定位地址
http://apple.com
二进制资源格式仍在使用中,如果要读取plist文件,请确保需要同时读取这两种文件格式。但是,在编写文件时——使用基于plist的格式——要简单得多。

另一种制作“web快捷方式”的方法是
。url
这里已经提到过的文件。
内容如下所示(比基于plist-xml的要简单得多):

注意文件有3行,最后一行是空的


这完成了基本任务,不需要任何第三方库。(注意:最小错误检查。)

//用于“拖动”资源的数据(总是相同的)
#定义拖动数据长度64
静态常量无符号字符拖动数据[拖动数据长度]={
0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,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、0x00、0x00、0x00、0x00、,
0x75、0x72、0x6C、0x20、0x00、0x00、0x01、0x00、0x00、0x00、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、0x00、0x00、0x00};
静态void\u addData(NSData*data,ResType类型,short resId,ResFileRefNum refNum)
{
把手;
if(PtrToHand([data bytes],&handle,[data length])==noErr){
ResFileRefNum previousRefNum=CurResFile();
UseResFile(refNum);
锁(手柄);
AddResource(句柄、类型、剩余“\p”);
HUnlock(手柄);
UseResFile(previousRefNum);
}
}
void WeblocCreateFile(NSString*位置、NSString*名称、NSURL*文件URL)
{
NSString*内容=[NSString stringWithFormat:
@“\n”
@“\n”
@“\n”
@“\n”
@“URL\n”
@“%@\n”
@“\n”
@“\n”,位置];
if([[contents dataUsingEncoding:NSUTF8StringEncoding]writeToURL:fileUrl选项:nsdatawriteingatomic error:nil])
{        
//拆分为父级和文件名部分
NSString*parentPath=[[fileUrl URLByDeletingLastPathComponent]路径];
NSString*文件名=[fileUrl lastPathComponent];
FSRef parentRef;
if(FSPathMakeRef((const UInt8*)[parentPath fileSystemRepresentation],&parentRef,NULL)==noErr)
{
unichar fileNameBuffer[[文件名长度]];
[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)==no
[InternetShortcut]
URL=http://www.apple.com/
// 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);
                    }
                }
            }
        }
    }
}