Вопрос

Я пишу программу (для Mac OS X с использованием Objective-C), и мне нужно программно создать несколько файлов .webloc.

Файл .webloc — это просто файл, который создается после перетаскивания URL-адреса из адресной строки Safari в какую-либо папку.

Вообще говоря, мне нужен подход для создания элементов в файловой системе, указывающих на какое-то место в Интернете.Насколько я понимаю, для этого в Mac OS X следует использовать файлы .webloc.

Итак, можно ли создать файл .webloc, имеющий действительный URL-адрес и заголовок?

Это было полезно?

Решение

Об этом мало известно, но существует также простой формат файлов на основе 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 файлы (в более общем смысле файлы местоположений в Интернете) записываются в формате, определение которого восходит к Mac OS 8.x.Он основан на ресурсах и основан на формате обрезки, который вы получаете при создании файла из перетаскиваемых объектов, таких как текст или изображения.

Написанные ресурсы 'url ' 256 и 'TEXT' 256, в котором хранится URL-адрес, и, при необходимости, «urln» 256, содержащий текст, связанный с URL-адресом. 'drag' 128 очков остальным двум (или трем) ресурсам.

NTWeblocFile, часть Платформа с открытым исходным кодом Cocotech CocoaTechFoundation (лицензия BSD) поддерживает запись этих файлов из Objective-C.Если вы хотите указать заголовок отдельно от URL-адреса, вам необходимо изменить класс, чтобы он записывал в URL-адрес нечто иное, чем URL-адрес. 'urln' ресурс.

В Mac OS X 10.3 и более поздних версиях URL-адрес также записывается (также может быть записан) в список свойств в вилке данных файла.Посмотрите другой ответ, как это работает...

А .webloc в вилке данных файла ничего нет;вместо этого он сохраняет URL-адрес, на который ссылается, как ресурс в своей ответвлении ресурса.Вы можете увидеть это в командной строке, используя команду ДеРес(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 */
};

Единственные ресурсы, которые, вероятно, должны там быть, - это 'url ' и 'TEXT' ресурсы с идентификатором 256, и им, вероятно, тоже не нужны имена ресурсов.А 'urln' Ресурс может быть полезен, если вы хотите также включить заголовок документа, на который указывает URL.А 'drag' ресурс сообщает системе, что это вырезочный файл, но я не уверен, нужен ли он там в наши дни.

Для работы с ресурсами и ответвлением файла вы используете Resource Manager — одну из базовых частей Carbon, восходящую к оригинальному Mac.Однако есть несколько оболочек Cocoa для Resource Manager, например: NDResourceFork Натана Дэя.

Другой способ сделать «веб-ярлык» — .url файл, упомянутый здесь уже.
Содержимое выглядит так (намного проще, чем plist на основе xml):

[InternetShortcut]
URL=http://www.apple.com/

Обратите внимание, что файл состоит из 3 строк, последняя строка пуста.

Дополнительная информация о формате файла .url

Он использует двоичный формат на основе разветвления ресурсов.

Допустимые обходные пути:

  • Попросите пользователя перетащить URL-адрес из вашего приложения (NSURLPboardType) в Finder.Finder создаст для вас веб-блок.
  • Создайте веб-ярлык Windows (файл .URL).Они имеют INI-подобный формат на основе разветвления данных и должны быть документированы где-нибудь в Интернете;ОС поддерживает их, как и веб-блоки.

Вот как это делает Google Chrome: 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);
                    }
                }
            }
        }
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top