[OS X] How do I create a webloc file ?

The subject says all:

How do I create a webloc file ?

What is a webloc file ?
This is a file who holds an URL as text and have:
file type: ilht
creator type: MACS
name extension: .webloc

You can just create a plist file with the extension .webloc

[code]<?xml version="1.0" encoding="UTF-8"?>

URL http://xojo.com [/code]

shao sean
Thank you for your kind suggestion.

I will try your code to be sure, but when I export (drag off the URL text from the URL Bar) to the Finder from the URL field (Firefox or Safari), I do not get what you suggest; thus my question.
The file name ends with .webloc and its contents is the URL, nothing else. (I use these files later to download what’s at that location).

Another suggestion ?

BTW: I tried using TextOutputStream and BinaryStream but I do not get what I get with a Firefox drop of the URL field.

Because I have not only one (but it can be) URL to save from where I store it/them, I use a loop to save the webloc files / FolderITem.Child("").

The FolderItem is set at the beginning of the save (I also save one image from a Canvas and text from one TextArea) method.

I think there is an older resource based webloc, which is what you might be seeing, but otherwise the above plist file does work (at least with Safari)…

Emile, a modern .webloc file as created by Safari, for instance, is a binary plist file. The plist file may be in textual (XML) format as well, like shao sean showed.

The plist file is the same format that’s also used for preference files in the Preferences folder.

If you want to read a weblog file, you can use the CFPreferences functions from macoslib - use the same code that it uses to read a preferences plist file, and you’ll find that it contains just one “URL” item. You can also rename the .webloc file to end in “.plist” and then, for instance, open it in Xcode to see what’s inside. BBedit (maybe also TextWrangler) can also open plist files, both binary and XML.

If you want to create one, just do what shao sean suggests. If you want to create a binary file, use macoslib’s CFPreferences functions.

shao, Thomas,

Thank you for your complete answers.

I created a .webloc file using shao advice and it runs my default browser (FireFox, but of course, I have Safari too) when hit twice (double-click). But it still does not have the correct icon (@ + HTTP).

It seems to me that Safari fills the .webloc file with text (yes, xml).

Thomas, you are right, to read that file, I need to do some more steps (far more than what I will do) if I want to create a Safari webloc file.

Firefox webloc files have the webloc icon, but holds only the URL. Very easy to read its contents.

Here’s the used code:

  WebLocBS = BinaryStream.Create(FldrFI.Child(URLName), True) // Overwrite if exists
  WebLocBS.Write(Build_Webloc(theURL))
  WebLocBS.Close

Since I wrote many files with the ‘similar’ data, I create a folder (FldrFI), then I write my webloc, Picture, rich text, etc. in that folder, thus FldrFI.Child(URLName).
Also, in Build_Webloc(theURL), theURL is the real data I only want and the method encapsulate it in xml data.

Yes, I could use TextOutputStream to do that, but TextOutputStream set the generated file as TEXT file.

I completely forgot how to set the just created file to a specific file type (that is with par of the file extension).

To set file type and creator codes, use FolderItem.MacCreator and MacType. They’re not shown in Xojo’s code completion any more but they’re still there.

But .weblocs created by Safari have no creator/type codes set. So, try setting those both to chr(0)+chr(0)+chr(0)+chr(0). Maybe that helps with the icon.

Thank you Thomas.

I’m a complete idiot (fortunately, sometimes only): I read:

This property has been DEPRECATED.

In the [LOCAL] documentation for FolderItem.MacType and do not read the next line:
Please use Uniform Type Identifiers as a replacement.

I will investigate.

file type: "ilht" file creator: "MACS"

com.apple.web-internet-location

Good…

(time to eat)

Emile, do not bother with the “Uniform Type Identifiers” because that’s only needed if you want to open webloc files, e.g. with a OpenDialog. When writing a new file, the URI won’t help you unless it is your own type. But it’s not your own type, it’s defined by Apple and already defined in the OSX.

So, basically, if you use .webloc as the extension, you should see a Safari icon.

Unless somehow the file’s creator and type codes got changed. In this case, either set them in code to either chr(0) as I wrote, or to the values sean wrote, do that by setting MacCreator and MacFile, and ignore the deprecation warning.

Or, the more correct way, set up a FileType set and leave the type and creator codes blank, and add the “com.apple.web-internet-location” as a URI there, and then use this filetype when you create the file with BinaryStream.

I added the UTI in the existing File Type Set, trashed teh previous standalone, build a brand new one and I still do not get the right icon.

Of course, the File Type Set exists, but it is not used. Code to save the URLs:

WebLocBS = BinaryStream.Create(FldrFI.Child(URLName), True) // Overwrite if exists
WebLocBS.Write(Build_Webloc(theURL))
WebLocBS.Close

Thomas:
I ran the AppleScipt below and get (read below too):
file type:"???", file creator:"???", type identifier:“com.apple.web-internet-location”
Probably what you says when you talked about setting $0000 in both type and creator. (because I used a BinaryStream to create the file).

#This is a multi purpose script (I do not need the invisible for this Xojo checking)
tell application “Finder”
return info for (choose file default location (target of front window as alias) with invisibles)
end tell

{name:“The Rolling Stones - Charlie Is My Darling 02.webloc”, creation date:date “mercredi 16 octobre 2013 15:06:41”, modification date:date “mercredi 16 octobre 2013 15:06:41”, size:279, folder:false, alias:false, package folder:false, visible:true, extension hidden:false, name extension:“webloc”, displayed name:“The Rolling Stones - Charlie Is My Darling 02.webloc”, default application:alias “Macintosh HD:Applications:Xcode.app:Contents:Developer:Platforms:iPhoneSimulator.platform:Developer:Applications:iPhone Simulator.app:”, kind:“HTML document”, file type:"???", file creator:"???", type identifier:“com.apple.web-internet-location”, locked:false, busy status:false, short version:"", long version:""}

Why iPhoneSimulator.app ? But I do not care, must I care ?

Of course, I can set the target application for this file extension to Firefox, but every person who will use that application have to do the same --> weird.

Emile, maybe you do not fully understand how the OSX registration for file types works.

Get the program “RCDefaultApp”. It’s a System Prefs item. Once installed, you can look at all registered types on your Mac. You can see which programs are registered for .webloc there.

I am not sure if “???” is just a way to display chr(0) or if it’s really “?” in there. Just write a little program in RB that reads MacCreator and MacFile from your created webloc file and then look at the actual values in the debugger. Are they 0?

Hi all,

[*] says what I added to my original code. The short answer is:

// URLs are stored in Cells of a 1 Column ListBox named LB
Dim WebLocFI As FolderItem // [*]

// Deal with the URLs (if there is one or more)
For LoopIdx = 0 to EntryCnt
  // Get one URL
  theURL = LB.Cell(LoopIdx,0)
  
  // Compute the file name
  // TF_Name is a TextField who holds the Folder name
  URLName = TF_Name.Text + " " + Format(LoopIdx,"00") + ".webloc"
  
  // Get a local reference            [*]
  WebLocFI = FldrFI.Child(URLName) // [*]
  If WebLocFI = Nil Then Exit      // [*]
  
  // Create a new file
  WebLocBS = BinaryStream.Create(WebLocFI, True) // Overwrite if exists
  
  // Fill the file with a "xml webloc code"
  WebLocBS.Write(Build_Webloc(theURL)) // Based on Safari / Finder webloc code
  
  // Set the type and creator    // [*]
  If WebLocFI <> Nil Then        // [*]
    WebLocFI.MacCreator = "MACS" // [*]
    WebLocFI.MacType    = "ilht" // [*]
  End If                         // [*]
  
  // Close the BinaryStream
  WebLocBS.Close
  WebLocBS = Nil
  
  // To avoid 1, Infinite loop
  If UserCancelled Then Exit
Next

Paste the code to TextEdit and set the Font to Courier (or another non proportional font) to enjoy it visually.

To make a long story very short, I only set MacCreator and MacType to the right values and get the correct icon. No need to go cryptic or use UTI.

The long answer in the next entry.

Emile, next time, please wrap your code in a “code” tag, see the “<>” icon.

Thomas: thank you for the tip.

Sorry Thomas, I do not think at that (I tried once the Picture tag and it does not displays the picture, so I stop watching these buttons).

I will do for the long answer (I have code there).

This is the long answer.

Hi Thomas, Readers, Xojo Team,

The Code button works fine. Thank you for the tip Thomas.

Thomas, I found the example below in “FolderItem.Type”:

Example

[code]dim f As New folderitem
f = GetOpenFolderItem("???")

If f.Type <> “” Then
MsgBox f.Type
Else
MsgBox “The Type is null”
End If
[/code]

So “???” = $0000 (from the OS X perspective).

the problem here is not (really) if I know OS X file technologies, but how Xojo deal with them.

Here’s code to save a Canvas.Backdrop, standard text, RTF text and URL (in a webloc file).
The code is in a “Save” PushButton’s Action event:

[code]Sub Action()
Dim FldrDlg As New SelectFolderDialog
Dim FldrFI As FolderItem
Dim EntryCnt As Integer
Dim LoopIdx As Integer
Dim URLName As String
Dim URLTOS As TextOutputStream
Dim PassTOS As TextOutputStream
Dim WebLocBS As BinaryStream
Dim theURL As String

// Nota: this is OS X tested only code

// ---------- ---------- ---------- ---------- ---------- ----------
// 1. Ask the user to choose a target folder
FldrDlg.ActionButtonCaption = “Select”
FldrDlg.Title = “Choose a Folder”
FldrDlg.InitialDirectory = SpecialFolder.Documents
FldrFI = FldrDlg.ShowModal
If FldrFI = Nil Then
// user canceled
Return
End If

// ---------- ---------- ---------- ---------- ---------- ----------
// 2. Save the URLs (stored in Rows of LB: a ListBox)
// I have a bunch of URLs stored in a ListBox

// a. How many Rows ?
EntryCnt = LB.ListCount - 1 // there is a bug here, not related to this subject

// b. Is there at least one URL to save ?
If EntryCnt > 0 Then
// Deal with the URLs (if there is one or more)
For LoopIdx = 0 to EntryCnt
// Get one URL
theURL = LB.Cell(LoopIdx,0)

  // Compute the file name
  // TF_Name is a TextField who holds the Folder name
  URLName = TF_Name.Text + " " + Format(LoopIdx,"00") + ".webloc"
  
  // Create a new file
  WebLocBS = BinaryStream.Create(FldrFI.Child(URLName), True) // Overwrite if exists

  // Fill the file with a "xml webloc code"
  WebLocBS.Write(Build_Webloc(theURL)) // Based on Safari / Finder webloc code
  
  // Close the BinaryStream
  WebLocBS.Close
  
 // To avoid 1, Infinite loop
 If UserCancelled Then Exit
Next

End If

// ---------- ---------- ---------- ---------- ---------- ----------
// 3. Save the comments (stored in a TextArea)

// a. Create the text file
URLTOS = TextOutputStream.Create(FldrFI.Child(“Comments.rtf”))

// b. Fill the file with the RTF contents of the TextArea
URLTOS.Write TA_Comments.StyledText.RTFData

// c. Close that TOS
URLTOS.Close // Close the TextOutputStream
URLTOS = Nil // Make sure it is closed…

// ---------- ---------- ---------- ---------- ---------- ----------
// 4. Save the password (stored in a TextField)

// a. Create the text file
PassTOS = TextOutputStream.Create(FldrFI.Child(“Password.txt”))

// b. Fill the file
PassTOS.Write TF_Password.Text

// c. Close that TOS
PassTOS.Close // Close the TextOutputStream
PassTOS = Nil // Make sure it is closed…

// ---------- ---------- ---------- ---------- ---------- ----------
// 5. Store the “cover” scan image from Canvas.Backdrop

// a. Get a FolderItem Reference to save the image
FldrFI = FldrFI.Child(“Front image.png”)

// b. Save the image
cImage.Backdrop.Save(FldrFI,Picture.SaveAsPNG)

// That’s All Folks !
End Sub[/code]

How do you write to a text or rtf file ?

// Write into a TEXT file:
URLTOS.Write TA_Comments.Text

// Write into a RTF file:
URLTOS.Write TA_Comments.StyledText.RTFData

Another difference is in the file creation: I used
Comments.txt for the TEXT file,
Comments.rtf for the RTF file.

I do not go in any OS definition nor Carbon Lib (as good as they can be).
[I changed the kind of text file while I wrote this text.]

You will note the used file types:

[code]-------------------------------------------------------------------------
| Type | Extension | Type definition (in French Finder) |
|-----------------------------------------------------------------------|
| URL/webloc | .webloc | HTML document |
| TEXT | .txt | Document format texte |
| RTF | .rtf | Document RTF |
| PNG | .png | Image PNG (Portable Network Graphics) |

[/code]
You also note that I used TextOutputStream to save as .txt and .rtf, but BinaryStream to store the .webloc data.

BTW: I just realized that I have a StandAlone of the previous version of this project: it may have changed things on the boot machine (I booted the computer with that built StandAlone).

Here are the data for some files using AppleScript:
Comments.rtf
{name:“Comments.rtf”, size:301, folder:false, alias:false, package folder:false, visible:true, extension hidden:false, name extension:“rtf”, displayed name:“Comments.rtf”, default application:alias “Macintosh HD:Applications:TextEdit.app:”, kind:“Document RTF”, file type:“TEXT”, file creator:“ttxt”, type identifier:“public.rtf”, locked:false, busy status:false, short version:"", long version:""}

Password.txt
{name:“Password.txt”, size:4, folder:false, alias:false, package folder:false, visible:true, extension hidden:false, name extension:“txt”, displayed name:“Password.txt”, default application:alias “Macintosh HD:Applications:TextEdit.app:”, kind:“Document format texte”, file type:“TEXT”, file creator:“ttxt”, type identifier:“public.plain-text”, locked:false, busy status:false, short version:"", long version:""}

Front image.png
{name:“Front image.png”, size:99921, folder:false, alias:false, package folder:false, visible:true, extension hidden:false, name extension:“png”, displayed name:“Front image.png”, default application:alias “Macintosh HD:Applications:Preview.app:”, kind:“Image PNG (Portable Network Graphics)”, file type:"", file creator:"", type identifier:“public.png”, locked:false, busy status:false, short version:"", long version:""}

and one webloc: Tarzan Daily Strip #3802 00.webloc
{name:“Tarzan Daily Strip #3802 00.webloc”, size:261, folder:false, alias:false, package folder:false, visible:true, extension hidden:false, name extension:“webloc”, displayed name:“Tarzan Daily Strip #3802 00.webloc”, default application:alias “Macintosh HD:Applications:Xcode.app:Contents:Developer:Platforms:iPhoneSimulator.platform:Developer:Applications:iPhone Simulator.app:”, kind:“HTML document”, file type:"???", file creator:"???", type identifier:“com.apple.web-internet-location”, locked:false, busy status:false, short version:"", long version:""}

after I add code to change file type and creator (but not with UTI [Uniform Type Indicator]) *:
Tarzan Daily Strip 01.webloc
{name:“Tarzan Daily Strip 01.webloc”, size:244, folder:false, alias:false, package folder:false, visible:true, extension hidden:false, name extension:“webloc”, displayed name:“Tarzan Daily Strip 01.webloc”, default application:alias “Macintosh HD:Applications:Xcode.app:Contents:Developer:Platforms:iPhoneSimulator.platform:Developer:Applications:iPhone Simulator.app:”, kind:“HTML document”, file type:“ilht”, file creator:“MACS”, type identifier:“com.apple.web-internet-location”, locked:false, busy status:false, short version:"", long version:""}

I found a correct answer for this question. New code to create a webloc file:

[code] // Added on 2013-10-17
Dim WebLocFI As FolderItem // [*]

// Deal with the URLs (if there is one or more)
For LoopIdx = 0 to EntryCnt
  // Get one URL
  theURL = LB.Cell(LoopIdx,0)
  
  // Compute the file name
  // TF_Name is a TextField who holds the Folder name
  URLName = TF_Name.Text + " " + Format(LoopIdx,"00") + ".webloc"
  
  // Get a local reference            [*]
  WebLocFI = FldrFI.Child(URLName) // [*]
  If WebLocFI = Nil Then Exit      // [*]
  
  // Create a new file
  WebLocBS = BinaryStream.Create(WebLocFI, True) // Overwrite if exists
  
  // Fill the file with a "xml webloc code"
  WebLocBS.Write(Build_Webloc(theURL)) // Based on Safari / Finder webloc code
  
  // Set the type and creator    // [*]
  If WebLocFI <> Nil Then        // [*]
    WebLocFI.MacCreator = "MACS" // [*]
    WebLocFI.MacType    = "ilht" // [*]
  End If                         // [*]
  
  // Close the BinaryStream
  WebLocBS.Close
  WebLocBS = Nil
  
  // To avoid 1, Infinite loop
  If UserCancelled Then Exit
Next

[/code]
The newly added code is suffixed with " [*]" (without the quotes.
Where is the UTI I was suggested to use ?
[this is a simple question without any malice]

At last, I may not know enough Xojo working, but it is hard to work with Xojo when you have to program differently depending on the kind of file you have to deal with.

I am sorry, but I am at the boundaries or my English knowledge: I cannot express myself correctly on the subject, but I will try:
If you want to create and fill a text file: one way to do things, [use TextOutputStream]
If you want to create and fill a text file: same way to do things,
If you want to create and save an image file: another way to do things, a different one [use BinaryStream]
If you want to create and fill a file with data: the way to do things is undefined and may drastically vary [use BinaryStream].

There is no consistency in the way to save data to file / disk: all depends on what you want to save.

The web interface does not told us about the 10,000 characters limit.