SetCompressor /SOLID lzma
!include LogicLib.nsh
!include nsDialogs.nsh
!include "StrFunc.nsh"
!include "TextFunc.nsh"
!include "WordFunc.nsh"
!insertmacro LineFind
!insertmacro WordFind2X
RequestExecutionLevel user # for Windows Vista

Icon puzzle.ico
OutFile ExtensionConverter_1.3.exe
ShowInstDetails show
${StrRep}
${StrLoc}

; diese Sprachdateien haben statt "Installieren"-Tasten nur "Weiter"-Tasten.
LoadLanguageFile "${NSISDIR}\Contrib\Language files\English_EConv.nlf"
LoadLanguageFile "${NSISDIR}\Contrib\Language files\German_EConv.nlf"

Name ExtensionConverter
Caption "ExtensionConverter 1.3"

Var Dialog
Var Label
Var ListBox1
Var ListBox2
Var Index
LangString welcome ${LANG_ENGLISH_ECONV} "Welcome to ExtensionConverter. $\r$\n$\r$\nYou can use this program to convert old Firefox add-ons to the new version-3.6.3 format.$\r$\n$\r$\nPlease choose:"
LangString welcome ${LANG_GERMAN_ECONV} "Willkommen im ExtensionConverter$\r$\n$\r$\nDieses Programm wird Ihre alten Firefox-Erweiterungen in das neue Firefox-3.6.3-Format konvertieren.$\r$\n$\r$\nBitte wählen Sie:"

LangString source_code ${LANG_ENGLISH_ECONV} "The source code script of this NSIS is available at "
LangString source_code ${LANG_GERMAN_ECONV} "Der Quellcode dieses kleinen Programms ist hier verfügbar:"

LangString use_again ${LANG_ENGLISH_ECONV} "There are old extensions installed on this computer, but they stopped working after my update to Firefox 3.6.3 (or below)."
LangString use_again ${LANG_GERMAN_ECONV} "Auf diesem Computer sind Extensions, die seit dem Update auf Firefox 3.6.3 (oder niedriger) nicht mehr laufen, doch ich habe sie noch nicht gelöscht."
LangString convert_xpi ${LANG_ENGLISH_ECONV} "I want to convert a single extension in an XPI file."
LangString convert_xpi ${LANG_GERMAN_ECONV} "Ich möchte eine einzelne Extension in einer XPI-Datei konvertieren."

Function ClickLink
    ExecShell open "http://blaeul.de/docs/de_software.php"
FunctionEnd
Var RadioLocal
Var RadioXpi
Function CreateWelcomePage

    nsDialogs::Create /NOUNLOAD 1018
    Pop $Dialog

    ${If} $Dialog == error
        Abort
    ${EndIf}

    ${NSD_CreateLabel} 0 0 100% 50u $(welcome)
    Pop $Label

    ${NSD_CreateRadioButton} 0 50u 100% 20u $(use_again)
    Pop $RadioLocal

    ${NSD_CreateRadioButton} 0 70u 100% 20u $(convert_xpi)
    Pop $RadioXpi
    ${NSD_SetState} $RadioLocal ${BST_CHECKED}

    ${NSD_CreateLabel} 0 108u 100% 10u $(source_code)
    Pop $Label

    ${NSD_CreateLink} 0 119u 100% 10u "http://blaeul.de/docs/de_software.php"
    Pop $Label
    ${NSD_OnClick} $Label ClickLink

    nsDialogs::Show

FunctionEnd
Var XpiFile
Function ExitWelcomePage
    ${NSD_GetState} $RadioLocal $RadioLocal
    ${NSD_GetState} $RadioXpi $RadioXpi
    ${If} $RadioXpi == ${BST_CHECKED}
        nsDialogs::SelectFileDialog /NOUNLOAD open "" "Firefox extensions (*.xpi)|*.xpi"
        Pop $XpiFile
    ${EndIf}
FunctionEnd
Page custom CreateWelcomePage ExitWelcomePage

; XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXx

LangString directory ${LANG_ENGLISH_ECONV} "Select the target directory:"
LangString directory ${LANG_GERMAN_ECONV} "Bitte wählen Sie das Zielverzeichnis aus:"
Function AddDir
    IfFileExists $1 0 End_of_AddDir

    ${If} $RadioXpi == ${BST_UNCHECKED}
        SendMessage $ListBox1 ${LB_SELECTSTRING} -1 `STR:$1` $Index
        StrCmp $Index "-1" 0 End_of_AddDir # Verzeichnis schon in der Liste?
        ${NSD_LB_AddString} $ListBox1 $1
        SendMessage $ListBox1 ${LB_SELECTSTRING} -1 `STR:$1`
    ${EndIf}
    End_of_AddDir:
FunctionEnd
Var FirefoxExe
Function ChoosePortable
    nsDialogs::SelectFileDialog /NOUNLOAD open "" "FirefoxPortable.exe|FirefoxPortable.exe"
    Pop $FirefoxExe
    StrCpy $1 $FirefoxExe -20 ; remove file name
    StrCpy $1 "$1\Data\profile"
    Call AddDir
FunctionEnd
Function CreateDirectoryPage
    ${If} $RadioLocal == ${BST_CHECKED}
        nsDialogs::Create /NOUNLOAD 1018
        Pop $Dialog

        ${NSD_CreateLabel} 0 0 100% 10u $(directory)
        Pop $Label

        ${NSD_CreateButton} "-80u" 70u 79u 18u "Portable Firefox"
        Pop $Label
        ${NSD_OnClick} $Label ChoosePortable


        ${NSD_CreateListBox} 0 10u 100% 50u ""
        Pop $ListBox1
    ${EndIf}

    StrCpy $3 $APPDATA\Mozilla\Firefox
    StrCpy $4 0

begin_to_search_profiles:
    StrCpy $0 0

loop:
    ReadINIStr $1 $3\profiles.ini Profile$0 Path
    ${StrRep} $1 $1 "/" "\"
    IfErrors done
    ReadINIStr $2 $3\profiles.ini Profile$0 IsRelative
    StrCmp $2 1 0 add_install_dir

    # make absolute path
    StrCpy $1 $3\$1

add_install_dir:
    Call AddDir


install_done:
    IntOp $0 $0 + 1
    Goto loop

done:
    DetailPrint "done at $0 "
    StrCmp $0 0 0 end_of_profile_loop

    # Firefox is not installed.
    Goto install_done

end_of_profile_loop:
    StrCmp $4 1 find_next_user
    StrCpy $4 1

    Push "C:\Dokumente und Einstellungen\"
    Push "D:\Dokumente und Einstellungen\"
    Push "E:\Dokumente und Einstellungen\"
    Push "C:\Documents and Settings\"
    Push "D:\Documents and Settings\"
    Push "E:\Documents and Settings\"
search:
    FindFirst $6 $7 "$5*"

loop_for_users:
    StrCmp $7 "" done_with_users
    StrCpy $3 $5$7\Anwendungsdaten\Mozilla\Firefox
    IfFileExists $3 begin_to_search_profiles find_next_user
    StrCpy $3 $5$7\Application Data\Mozilla\Firefox
    IfFileExists $3 begin_to_search_profiles find_next_user

find_next_user:
    FindNext $6 $7
    Goto loop_for_users

done_with_users:
    FindClose $6
    ClearErrors
    Pop $5
    IfErrors 0 search


    ${If} $RadioLocal == ${BST_CHECKED}
        SendMessage $ListBox1 ${LB_GETCOUNT} 0 0 $0
        IntCmp $0 1 +3 0 +3
        MessageBox MB_OK|MB_ICONSTOP "Mozilla was not found!$\r$\nIf you have any idea why, tell me via 'christian@blaeul.de'.$\r$\n$\r$\nThanks."
        Abort

        nsDialogs::Show
    ${EndIf}
FunctionEnd
Function ExitDirectoryPage
    ${If} $RadioLocal == ${BST_CHECKED}
        SendMessage $ListBox1 ${LB_GETCURSEL} 0 0 $0
        System::Call 'user32::SendMessage(i, i, i, t) i($ListBox1, ${LB_GETTEXT}, r0, .r5)'
        # now $5 will contain the user-selected directory
    ${EndIf}
FunctionEnd
Page custom CreateDirectoryPage ExitDirectoryPage

; XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXx

Var CurTitle            # name of the current extension
Var CurTargetType # there are 2 konkurrierende specifications
Function GetTitleAndType
    ${WordFind2X} $R9 "<em:name>" "</em:name>" "E+1" $0
    IfErrors search_for_target_type
    StrCpy $CurTitle $0
    StrCpy $CurTargetType "single"

search_for_target_type:
    ${WordFind2X} $R9 'em:name="' '"' "E+1" $0
    IfErrors no_target_found
    StrCpy $CurTitle $0
    StrCpy $CurTargetType "multi"

no_target_found:
    Push $0
FunctionEnd

Var CurVersion
Var CurId
Var InTarget
Function UpdateSingleTargetExtension
    ${StrLoc} $0 $R9 "</em:targetApplication>" >
    StrCmp $0 "" +2 0
    StrCpy $InTarget false

    ${StrLoc} $0 $R9 "<em:targetApplication>" >
    StrCmp $0 "" +2 0
    StrCpy $InTarget true

    ${StrLoc} $0 $R9 "<em:updateURL>http:" >
    ${If} $0 != ""
        ${StrLoc} $0 $R9 "</em:updateURL>" >
        ${If} $0 != ""
            StrCpy $R9 SkipWrite
        ${EndIf}
    ${EndIf}

    ${If} $InTarget == true
        ${WordFind2X} $R9 "<em:id>" "</em:id>" "E+1" $0
        IfErrors +2
        StrCpy $CurId $0
        ${If} $CurId == "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"  # Firefox
            ${WordFind2X} $R9 "<em:maxVersion>" "</em:maxVersion>" "E+1" $0
            ${Unless} ${Errors}
                StrLen $4 $0
                StrCpy $CurVersion $0 1 # Hauptversion
                ${If} $CurVersion >= 3
                    StrCpy $CurVersion $0 1 2 # Unterversion
                    ${If} $CurVersion >= 6
                        ${NSD_LB_AddString} $ListBox1 $CurTitle
                    ${Else}
                        StrCpy $0 $R9 # make a working copy
                        ${StrLoc} $1 $R9 "</em:maxVersion>" >
                        ${StrLoc} $2 $R9 "<em:maxVersion>" <
                        StrCpy $0 $R9 -$2
                        StrCpy $2 $R9 "" $1
                        StrCpy $R9 "$03.99$2"
                        ${NSD_LB_AddString} $ListBox2 $CurTitle
                    ${EndIf}
                ${Else}
                    StrCpy $0 $R9 # make a working copy
                    ${StrLoc} $1 $R9 "</em:maxVersion>" >
                    ${StrLoc} $2 $R9 "<em:maxVersion>" <
                    StrCpy $0 $R9 -$2
                    StrCpy $2 $R9 "" $1
                    StrCpy $R9 "$03.99$2"
                    ${NSD_LB_AddString} $ListBox2 $CurTitle
                ${EndIf}
            ${EndUnless}
        ${EndIf}
    ${EndIf}

    Push $R9
FunctionEnd

Function UpdateMultiTargetExtension
    ${StrLoc} $0 $R9 "/>" >
    StrCmp $0 "" +2 0
    StrCpy $InTarget false

    ${StrLoc} $1 $R9 "<RDF:Description " >
    StrCmp $0 "" +2 0
    StrCpy $InTarget true

    ${If} $1 > $0
        StrCpy $InTarget true
    ${EndIf}

    ${StrLoc} $0 $R9 "<em:updateURL>http:" >
    ${If} $0 != ""
        ${StrLoc} $0 $R9 "</em:updateURL>" >
        ${If} $0 != ""
            StrCpy $R9 SkipWrite
        ${EndIf}
    ${EndIf}

    ${If} $InTarget == true
        ${WordFind2X} $R9 'em:id="' '"' "E+1" $0
        IfErrors +2
        StrCpy $CurId $0
        ${If} $CurId == "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"
            ${WordFind2X} $R9 'em:maxVersion="' '"' "E+1" $0
            ${Unless} ${Errors}
                StrLen $4 $0
                StrCpy $CurVersion $0 1 # Hauptversion
                ${If} $CurVersion >= 3
                    StrCpy $CurVersion $0 1 2 # Unterversion
                    ${If} $CurVersion >= 6
                        ${NSD_LB_AddString} $ListBox1 $CurTitle
                    ${Else}
                        StrCpy $0 $R9 # make a working copy
                        ${StrLoc} $2 $R9 'em:maxVersion="' >
                        IntOp $1 $2 + $4
                        IntOp $1 $1 + 15
                        IntOp $2 $2 + 15
                        StrCpy $0 $R9 $2
                        StrCpy $2 $R9 "" $1
                        StrCpy $R9 "$03.99$2"
                        ${NSD_LB_AddString} $ListBox2 "$CurTitle"
                    ${EndIf}
                ${Else}
                    StrCpy $0 $R9 # make a working copy
                    ${StrLoc} $2 $R9 'em:maxVersion="' >
                    IntOp $1 $2 + $4
                    IntOp $1 $1 + 15
                    IntOp $2 $2 + 15
                    StrCpy $0 $R9 $2
                    StrCpy $2 $R9 "" $1
                    StrCpy $R9 "$03.99$2"
                    ${NSD_LB_AddString} $ListBox2 "$CurTitle"
                ${EndIf}
            ${EndUnless}
        ${EndIf}
    ${EndIf}

    Push $R9
FunctionEnd



# Damit heißt die erste Taste 'Weiter' und nicht 'Installieren'
; Function CreateDummyPage
; FunctionEnd
; Page custom CreateDummyPage


; XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXx


LangString not_changed ${LANG_ENGLISH_ECONV} "These extensions were not modified, because they were ready for Firefox 3.6.3.:"
LangString not_changed ${LANG_GERMAN_ECONV} "Diese Erweiterungen waren bereits Firefox 3.6.3-kompatibel und wurden nicht verändert:"
LangString have_been_modified ${LANG_ENGLISH_ECONV} "The following extensions have been modified:"
LangString have_been_modified ${LANG_GERMAN_ECONV} "Folgende Erweiterungen wurden aktualisiert:"

Function CreateFinalPage


    nsDialogs::Create /NOUNLOAD 1018
    Pop $Dialog

    ${NSD_CreateLabel} 0 0 100% 18u $(not_changed)
    Pop $Label

    ${NSD_CreateListBox} 0 18u 100% 40u ""
    Pop $ListBox1

    ${NSD_CreateLabel} 0 70u 100% 12u $(have_been_modified)
    Pop $Label

    ${NSD_CreateListBox} 0 82u 100% 40u ""
    Pop $ListBox2


    ${If} $RadioLocal == ${BST_CHECKED}

        FindFirst $6 $7 "$5\extensions\*"

loop_for_extensions:
        StrCmp $7 "" end_of_installer
        StrCpy $3 $5\extensions\$7\install.rdf
        IfFileExists $3 0 find_next_extension

        # we found an install.rdf file
        StrCpy $CurTitle ""
        ${LineFind} "$3" "/NUL" "" GetTitleAndType
        StrCmp $CurTitle "" find_next_extension

        # the file contains a valid extension title
        ${If} $CurTargetType == 'single'
            ${LineFind} "$3" "" "" UpdateSingleTargetExtension
        ${ElseIf} $CurTargetType == 'multi'
            ${LineFind} "$3" "" "" UpdateMultiTargetExtension
        ${EndIf}

find_next_extension:
        FindNext $6 $7
        Goto loop_for_extensions

end_of_installer:
        # clear the extension cache
        Delete $5\extensions.cache
        Delete $5\extensions.ini
        Delete $5\extensions.rdf

    ${ElseIf} $RadioXpi == ${BST_CHECKED}

        ${If} $XpiFile == "Error"
        ${OrIf} $XpiFile == ""
            Abort ; user didn't select a file^
        ${Else}
            SetOutPath $TEMP
            File unzip.exe
            ExecWait 'unzip -u -o "$XpiFile" install.rdf' $0
            Delete unzip.exe
            IfErrors 0 +2
            MessageBox MB_OK|MB_ICONSTOP "Unzip failed"
            StrCmp $0 1 0 +2
            MessageBox MB_OK|MB_ICONSTOP "Unzip: One or more warning errors were encountered, but processing completed successfully anyway. This includes zipfiles where one or more files was skipped due to unsupported compression method"
            StrCmp $0 2 0 +2
            MessageBox MB_OK|MB_ICONSTOP "A generic error in the xpi file format was detected. Processing may have completed successfully anyway; some broken zipfiles created by other archivers have simple work-arounds."
            StrCmp $0 3 0 +2
            MessageBox MB_OK|MB_ICONSTOP "A severe error in the xpi file format was detected. Processing probably failed immediately."
            StrCmp $0 9 0 +2
            MessageBox MB_OK|MB_ICONSTOP "The specified xpi file was not found:$\r$\n$\r$\n$XpiFile"
            StrCmp $0 11 0 +2
            MessageBox MB_OK|MB_ICONSTOP "'install.rdf' file was not found inside the xpi file."
            StrCmp $0 50 0 +2
            MessageBox MB_OK|MB_ICONSTOP "The disk is (or was) full during extraction."
            StrCmp $0 51 0 +2
            MessageBox MB_OK|MB_ICONSTOP "The end of the ZIP archive was encountered prematurely."
            StrCmp $0 80 0 +2
            MessageBox MB_OK|MB_ICONSTOP "The user aborted UnZip prematurely with control-C (or similar)"
            StrCmp $0 81 0 +2
            MessageBox MB_OK|MB_ICONSTOP "Testing or extraction of one or more files failed due to unsupported compression methods or unsupported decryption."

            StrCpy $3 "$TEMP\install.rdf"

            ${LineFind} "$3" "/NUL" "" GetTitleAndType
            ${If} $CurTitle == ""
                MessageBox MB_OK|MB_ICONSTOP "install.rdf was not found or not understood."
                Abort
            ${EndIf}

            ${If} $CurTargetType == 'single'
                ${LineFind} "$3" "" "" UpdateSingleTargetExtension
            ${ElseIf} $CurTargetType == 'multi'
                ${LineFind} "$3" "" "" UpdateMultiTargetExtension
            ${EndIf}

            File zip.exe
            ExecWait 'zip -f "$XpiFile" install.rdf' $0
            IfErrors 0 +3
            MessageBox MB_OK|MB_ICONSTOP "Re-zipping failed"
            Abort
            StrCmp $0 9 0 +3
            MessageBox MB_OK|MB_ICONSTOP "Zip was interrupted by user (or superuser) action."
            Abort
            StrCmp $0 10 0 +3
            MessageBox MB_OK|MB_ICONSTOP "Zip encountered an error creating or using a temporary file."
            Abort
            StrCmp $0 14 0 +3
            MessageBox MB_OK|MB_ICONSTOP "Zip encountered an error writing to the xpi file."
            Abort
            StrCmp $0 15 0 +3
            MessageBox MB_OK|MB_ICONSTOP "Could not open the XPI file for writing. Check its properties, maybe its marked as read-only."
            Abort
            Delete zip.exe
            Delete install.rdf
        ${EndIf}
    ${EndIf}
    nsDialogs::Show

FunctionEnd

page instfiles
Section single_xpi_file
    SetAutoClose true
SectionEnd
Page custom CreateFinalPage