You find this example project in your Plugins Download as a Xojo project file within the examples folder: /MacExtras/Sparkle/UpdaterKit/AppCast Creator/AppCast Creator
Class MainWindow Inherits Window
Control iAppCastURL Inherits TextField
ControlInstance iAppCastURL Inherits TextField
End Control
Control StaticText1 Inherits Label
ControlInstance StaticText1 Inherits Label
End Control
Control iDescription Inherits TextField
ControlInstance iDescription Inherits TextField
End Control
Control StaticText2 Inherits Label
ControlInstance StaticText2 Inherits Label
End Control
Control iItemTitle Inherits TextField
ControlInstance iItemTitle Inherits TextField
End Control
Control StaticText4 Inherits Label
ControlInstance StaticText4 Inherits Label
End Control
Control iItemDescriptionURL Inherits TextField
ControlInstance iItemDescriptionURL Inherits TextField
End Control
Control StaticText5 Inherits Label
ControlInstance StaticText5 Inherits Label
End Control
Control iPubDate Inherits TextField
ControlInstance iPubDate Inherits TextField
End Control
Control StaticText6 Inherits Label
ControlInstance StaticText6 Inherits Label
End Control
Control iVersion Inherits TextField
ControlInstance iVersion Inherits TextField
End Control
Control StaticText7 Inherits Label
ControlInstance StaticText7 Inherits Label
End Control
Control iMacURL Inherits TextField
ControlInstance iMacURL Inherits TextField
End Control
Control StaticText8 Inherits Label
ControlInstance StaticText8 Inherits Label
End Control
Control iMacSig Inherits TextField
ControlInstance iMacSig Inherits TextField
End Control
Control StaticText9 Inherits Label
ControlInstance StaticText9 Inherits Label
End Control
Control iMacLength Inherits TextField
ControlInstance iMacLength Inherits TextField
End Control
Control StaticText10 Inherits Label
ControlInstance StaticText10 Inherits Label
End Control
Control iWin32URL Inherits TextField
ControlInstance iWin32URL Inherits TextField
End Control
Control StaticText11 Inherits Label
ControlInstance StaticText11 Inherits Label
End Control
Control iWin32MD5 Inherits TextField
ControlInstance iWin32MD5 Inherits TextField
End Control
Control StaticText12 Inherits Label
ControlInstance StaticText12 Inherits Label
End Control
Control iWin32Length Inherits TextField
ControlInstance iWin32Length Inherits TextField
End Control
Control StaticText13 Inherits Label
ControlInstance StaticText13 Inherits Label
End Control
Control PushButton1 Inherits PushButton
ControlInstance PushButton1 Inherits PushButton
EventHandler Sub Action()
savePref
Save
End EventHandler
End Control
Control StaticText14 Inherits Label
ControlInstance StaticText14 Inherits Label
End Control
Control iItemDescriptionURLde Inherits TextField
ControlInstance iItemDescriptionURLde Inherits TextField
End Control
Control StaticText15 Inherits Label
ControlInstance StaticText15 Inherits Label
End Control
Control iWin64URL Inherits TextField
ControlInstance iWin64URL Inherits TextField
End Control
Control Label1 Inherits Label
ControlInstance Label1 Inherits Label
End Control
Control iWin64MD5 Inherits TextField
ControlInstance iWin64MD5 Inherits TextField
End Control
Control Label2 Inherits Label
ControlInstance Label2 Inherits Label
End Control
Control iWin64Length Inherits TextField
ControlInstance iWin64Length Inherits TextField
End Control
Control Label3 Inherits Label
ControlInstance Label3 Inherits Label
End Control
Control iLin32URL Inherits TextField
ControlInstance iLin32URL Inherits TextField
End Control
Control Label4 Inherits Label
ControlInstance Label4 Inherits Label
End Control
Control iLin32MD5 Inherits TextField
ControlInstance iLin32MD5 Inherits TextField
End Control
Control Label5 Inherits Label
ControlInstance Label5 Inherits Label
End Control
Control iLin32Length Inherits TextField
ControlInstance iLin32Length Inherits TextField
End Control
Control Label6 Inherits Label
ControlInstance Label6 Inherits Label
End Control
Control iLin64URL Inherits TextField
ControlInstance iLin64URL Inherits TextField
End Control
Control Label7 Inherits Label
ControlInstance Label7 Inherits Label
End Control
Control iLIn64MD5 Inherits TextField
ControlInstance iLIn64MD5 Inherits TextField
End Control
Control Label8 Inherits Label
ControlInstance Label8 Inherits Label
End Control
Control iLin64Length Inherits TextField
ControlInstance iLin64Length Inherits TextField
End Control
Control Label9 Inherits Label
ControlInstance Label9 Inherits Label
End Control
EventHandler Sub Open()
LoadDefaultValues
LoadPref
FindFiles
CalculateFields
End EventHandler
Protected Sub CalculateFields()
// We calculate here the values we can handle automatically
if MacFile = nil then
iMacLength.Text = ""
else
iMacLength.text = Format(MacFile.Length, "0")
end if
if Win32File <> nil then
iWin32Length.text = Format(Win32File.Length, "0")
else
iWin32Length.Text = ""
end if
if Win64File <> nil then
iWin64Length.text = Format(Win64File.Length, "0")
else
iWin64Length.Text = ""
end if
if Lin32File <> nil then
iLin32Length.text = Format(Lin32File.Length, "0")
else
iLin32Length.Text = ""
end if
if Lin64File <> nil then
iLin64Length.text = Format(Lin64File.Length, "0")
else
iLin64Length.Text = ""
end if
// Calculate MD5 Checksum
iWin32MD5.text = CheckSum(Win32file)
iWin64MD5.text = CheckSum(Win64file)
iLin32MD5.text = CheckSum(Lin32file)
iLin64MD5.text = CheckSum(Lin64file)
// Make a signature for Mac file
if MacFile = nil then
iMacSig.text = ""
else
dim s as new Shell
s.Execute "ruby "+SignUpdateFile.ShellPath+" "+MacFile.ShellPath+" "+PrivateDSAKeyFile.ShellPath
iMacSig.text = ReplaceLineEndings(s.Result, "")
end if
End Sub
Protected Function CheckSum(f as FolderItem) As string
if f <> nil then
dim b as BinaryStream = BinaryStream.Open(f, false)
if b<>nil then
dim s as string = b.Read(b.Length)
return MD5StringMBS(s)
end if
end if
End Function
Protected Sub FindFiles()
// Change the pathes to match your setup!
dim AppCastCreatorFolder as FolderItem = GetFolderItem("")
dim UpdaterKitFolder as FolderItem = AppCastCreatorFolder.parent
dim OnServerFolder as FolderItem = UpdaterKitFolder.Child("on the server")
MacFile = OnServerFolder.Child("UpdaterExampleMac.zip")
Win32File = OnServerFolder.Child("UpdaterExampleWin.exe")
Win64File = nil
Lin32File = nil
Lin64File = nil
dim SparkleFolder as FolderItem = UpdaterKitFolder.Child("Sparkle")
dim SampleKeysFolder as FolderItem = SparkleFolder.Child("sample keys")
PrivateDSAKeyFile = SampleKeysFolder.Child("dsa_priv.pem")
SignUpdateFile = SparkleFolder.Child("sign_update.rb")
End Sub
Protected Sub LoadDefaultValues()
// Some default values for testing
iAppCastURL.Text = "http://www.monkeybreadsoftware.de/UpdaterTest/appcast.xml"
iDescription.text = "Most recent changes with links to updates."
iItemTitle.Text = "Version 2.0"
iDescription.text = "Most recent changes with links to updates."
iItemDescriptionURL.text = "http://www.monkeybreadsoftware.de/UpdaterTest/description.html"
iItemDescriptionURLde.text = "http://www.monkeybreadsoftware.de/UpdaterTest/description-de.html"
iPubDate.text = "21 Feb 2010 20:00:00 +0000"
iMacURL.text = "http://www.monkeybreadsoftware.de/UpdaterTest/UpdaterExampleMac.zip"
iVersion.text = "2.0"
iWin32URL.text = "http://www.monkeybreadsoftware.de/UpdaterTest/UpdaterExampleWin.exe"
End Sub
Protected Sub LoadPref()
// A simple way to load preferences from a text file with key=value style
dim f as FolderItem = GetFolderItem("AppCast Creator.pref")
if f = nil or f.Exists = false then Return
dim t as TextInputStream = TextInputStream.Open(f)
if t=nil then Return
while not t.eof
dim s as string = t.ReadLine(encodings.UTF8)
dim p as integer = instr(s, "=")
dim Key as string = left(s,p-1)
dim value as string = mid(s,p+1)
Select case key
case "iAppCastURL"
iAppCastURL.Text = value
case "iDescription"
iDescription.Text = value
case "iItemTitle"
iItemTitle.Text = value
case "iItemDescriptionURL"
iItemDescriptionURL.Text = value
case "iItemDescriptionURLde"
iItemDescriptionURLde.Text = value
case "iPubDate"
iPubDate.Text = value
case "iVersion"
iVersion.Text = value
case "iMacURL"
iMacURL.Text = value
case "iWinURL"
iWin32URL.Text = value
case "iWin32URL"
iWin32URL.Text = value
case "iWin64URL"
iWin64URL.Text = value
case "iLin32URL"
iLin32URL.Text = value
case "iLin64URL"
iLin64URL.Text = value
end Select
wend
End Sub
Protected Sub Save()
// Create the appcast file.
// You may need to modify this in order to add new languages
dim f as FolderItem = GetFolderItem("appcast.xml")
dim t as TextOutputStream = TextOutputStream.Create(f)
WriteLine t,"<?xml version=""1.0"" encoding=""utf-8""?> "
WriteLine t,"<rss version=""2.0"" xmlns:dc=""http://purl.org/dc/elements/1.1/"" xmlns:sparkle=""http://www.andymatuschak.org/xml-namespaces/sparkle""> "
WriteLine t," <channel> "
WriteLine t," <title>Updates</title> "
WriteLine t," <link>" + iAppCastURL.Text + "</link> "
WriteLine t," <description>" + iDescription.Text + "</description> "
WriteLine t," <language>en</language> "
WriteLine t," <item> "
WriteLine t," <title>" + iItemTitle.Text + "</title> "
WriteLine t," <sparkle:releaseNotesLink xml:lang=""en"">" + iItemDescriptionURL.Text + "</sparkle:releaseNotesLink> " // English
WriteLine t," <sparkle:releaseNotesLink xml:lang=""de"">" + iItemDescriptionURLde.Text + "</sparkle:releaseNotesLink> " // German
WriteLine t," <pubDate>" + iPubDate.Text + "</pubDate> "
WriteLine t," <enclosure sparkle:version=""" + iVersion.Text + """"
if iMacURL.Text <> "" then
WriteLine t," url=""" + iMacURL.Text + """"
WriteLine t," sparkle:dsaSignature=""" + iMacSig.Text + """"
WriteLine t," length=""" + iMacLength.Text + """"
end if
if iWin32URL.Text <> "" then
WriteLine t," urlWin32=""" + iWin32URL.Text + """"
WriteLine t," lengthWin32=""" + iWin32Length.Text + """"
WriteLine t," MD5Win32=""" + iWin32MD5.Text + """"
end if
if iWin64URL.Text <> "" then
WriteLine t," urlWin64=""" + iWin64URL.Text + """"
WriteLine t," lengthWin64=""" + iWin64Length.Text + """"
WriteLine t," MD5Win64=""" + iWin64MD5.Text + """"
end if
if iLin32URL.Text <> "" then
WriteLine t," urlLinux32=""" + iLin32URL.Text + """"
WriteLine t," lengthLinux32=""" + iLin32Length.Text + """"
WriteLine t," MD5Linux32=""" + iLin32MD5.Text + """"
end if
if iLin64URL.Text <> "" then
WriteLine t," urlLinux64=""" + iLin64URL.Text + """"
WriteLine t," lengthLinux64=""" + iLin64Length.Text + """"
WriteLine t," MD5Linux64=""" + iLin64MD5.Text + """"
end if
WriteLine t," type=""application/octet-stream"" />"
WriteLine t," </item> "
WriteLine t," </channel> "
WriteLine t,"</rss> "
End Sub
Protected Sub SavePref()
// An easy way to save editfields to a text file
dim f as FolderItem = GetFolderItem("AppCast Creator.pref")
dim t as TextOutputStream = TextOutputStream.Create(f)
write t, iAppCastURL
write t, iDescription
write t, iItemTitle
write t, iItemDescriptionURL
write t, iItemDescriptionURLde
write t, iPubDate
write t, iVersion
write t, iMacURL
write t, iWin32URL
write t, iWin64URL
write t, iLin32URL
write t, iLin64URL
End Sub
Protected Sub WriteLine(t as TextOutputStream, s as string)
// Write a line with right encoding
t.WriteLine ConvertEncoding(s, encodings.UTF8)
End Sub
Protected Sub write(t as TextOutputStream, e as TextField)
// Writes the content of an editfield to a text output stream
t.WriteLine ConvertEncoding(e.Name+"="+e.Text, encodings.UTF8)
End Sub
Note "About"
Property Protected Lin32File As FolderItem
Property Protected Lin64File As FolderItem
Property Protected MacFile As FolderItem
Property Protected PrivateDSAKeyFile As FolderItem
Property Protected SignUpdateFile As FolderItem
Property Protected Win32File As FolderItem
Property Protected Win64File As FolderItem
End Class
MenuBar MenuBar1
MenuItem FileMenu = "&Ablage"
MenuItem FileQuit = "#App.kFileQuit"
MenuItem EditMenu = "&Bearbeiten"
MenuItem EditUndo = "&Rückgängig"
MenuItem UntitledMenu1 = "-"
MenuItem EditCut = "&Ausschneiden"
MenuItem EditCopy = "&Kopieren"
MenuItem EditPaste = "&Einfügen"
MenuItem EditClear = "#App.kEditClear"
MenuItem UntitledMenu0 = "-"
MenuItem EditSelectAll = "&Alles auswählen"
End MenuBar