arblant
firefox-vpn-client / app / windows / installer / firefox-vpn.iss
firefox-vpn.iss313 lines · 17.2 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313
; The Windows installer of Firefox VPN (Inno Setup 6). scripts\build-windows.ps1
; compiles it with the built app:
;
;   ISCC /DAppVersion=1.1.9 /DSourceDir=<the app's folder> /DOutputDir=<dir>
;        /DOutputName=<file name without .exe> firefox-vpn.iss
;
; It installs for the current user only, without administrator rights, by
; default into %LOCALAPPDATA%\Programs\Firefox VPN Client (apart from
; Mozilla's own client). The first install lets the user choose another
; folder; it must be one the user can write to, because the app keeps its
; data (accounts, settings, logs) in user-data beside it. A new version
; installs over the old one, in the same folder, and keeps user-data; the
; app also updates itself (core\internal\update): it replaces its files with
; a new version's and sets the version this Setup's entry in Windows' list
; of installed apps shows (AppId). An uninstall that keeps the data notes
; its folder, which the next install offers again.
;
; The TUN mode's service is the one part that needs administrator rights:
; Setup always runs core\firefox-vpn-tun.exe install, which asks for them
; itself and installs the service in Program Files; the uninstall removes it
; again.

#define AppName "FoxyVPN"
#define AppExe "firefox-vpn.exe"
#define AppDir "FoxyVPN Client"
#ifndef AppVersion
  #define AppVersion "0.0.0"
#endif
#ifndef SourceDir
  #error SourceDir must name the built app's folder
#endif
#ifndef OutputDir
  #define OutputDir "."
#endif
#ifndef OutputName
  #define OutputName "Firefox-VPN-Setup"
#endif

[Setup]
; The same id in every version, so a new one replaces the old; the app's
; own update finds this Setup's entry by it (core\internal\update).
AppId={{6F3A2C1E-9B4D-4E7A-8C21-5D0F7B9E4A63}
AppName={#AppName}
AppVersion={#AppVersion}
AppVerName={#AppName} {#AppVersion}
AppPublisher=Arman
AppPublisherURL=https://github.com/armanlife/firefox-vpn-client
AppSupportURL=https://github.com/armanlife/firefox-vpn-client/issues
AppUpdatesURL=https://github.com/armanlife/firefox-vpn-client/releases
VersionInfoVersion={#AppVersion}
DefaultDirName={code:DefaultDir}
; The folder is asked on the first install only; an update goes where the
; installed version is.
DisableDirPage=auto
UsePreviousAppDir=yes
DisableProgramGroupPage=yes
PrivilegesRequired=lowest
ArchitecturesAllowed=x64compatible
ArchitecturesInstallIn64BitMode=x64compatible
OutputDir={#OutputDir}
OutputBaseFilename={#OutputName}
SetupIconFile=..\runner\resources\app_icon.ico
UninstallDisplayIcon={app}\{#AppExe}
UninstallDisplayName={#AppName}
Compression=lzma2/ultra64
SolidCompression=yes
WizardStyle=modern
; A running copy is closed before its files are replaced.
CloseApplications=force
RestartApplications=no
ShowLanguageDialog=auto

[Languages]
Name: "en"; MessagesFile: "compiler:Default.isl"
Name: "fa"; MessagesFile: "languages\Farsi.isl"
Name: "ar"; MessagesFile: "compiler:Languages\Arabic.isl"
Name: "ru"; MessagesFile: "compiler:Languages\Russian.isl"
Name: "tr"; MessagesFile: "compiler:Languages\Turkish.isl"
Name: "az"; MessagesFile: "languages\Azerbaijan.isl"
Name: "id"; MessagesFile: "languages\Indonesian.isl"
Name: "es"; MessagesFile: "compiler:Languages\Spanish.isl"
Name: "fr"; MessagesFile: "compiler:Languages\French.isl"
Name: "hu"; MessagesFile: "compiler:Languages\Hungarian.isl"
Name: "pt"; MessagesFile: "compiler:Languages\BrazilianPortuguese.isl"
Name: "vi"; MessagesFile: "languages\Vietnamese.isl"
Name: "bn"; MessagesFile: "languages\Bengali.islu"

[CustomMessages]
; Uninstalling asks about the data, keeping it unless the user chooses
; otherwise.
DataQuestion=Keep your accounts and settings?
DataText=They stay in the user-data folder, so installing the app again brings them back. Delete them only if you will not use Firefox VPN again.
DataKeep=Keep them (recommended)
DataDelete=Delete them
fa.DataQuestion=حساب‌ها و تنظیمات شما نگه داشته شوند؟
fa.DataText=در پوشه user-data می‌مانند و با نصب دوباره برنامه برمی‌گردند. فقط اگر دیگر از Firefox VPN استفاده نمی‌کنید پاکشان کنید.
fa.DataKeep=نگه داشته شوند (پیشنهادی)
fa.DataDelete=پاک شوند
ar.DataQuestion=هل تريد الاحتفاظ بحساباتك وإعداداتك؟
ar.DataText=تبقى في مجلد user-data، فتعود عند تثبيت التطبيق مرة أخرى. احذفها فقط إذا كنت لن تستخدم Firefox VPN مجددًا.
ar.DataKeep=احتفظ بها (موصى به)
ar.DataDelete=احذفها
ru.DataQuestion=Сохранить ваши аккаунты и настройки?
ru.DataText=Они останутся в папке user-data, и при повторной установке приложение их вернёт. Удаляйте их, только если больше не будете пользоваться Firefox VPN.
ru.DataKeep=Сохранить (рекомендуется)
ru.DataDelete=Удалить
tr.DataQuestion=Hesaplarınız ve ayarlarınız saklansın mı?
tr.DataText=user-data klasöründe kalırlar; uygulamayı yeniden kurduğunuzda geri gelirler. Yalnızca Firefox VPN'i bir daha kullanmayacaksanız silin.
tr.DataKeep=Sakla (önerilen)
tr.DataDelete=Sil
az.DataQuestion=Hesablarınız və ayarlarınız saxlanılsın?
az.DataText=Onlar user-data qovluğunda qalır və tətbiqi yenidən quraşdıranda geri qayıdır. Yalnız Firefox VPN-dən bir daha istifadə etməyəcəksinizsə silin.
az.DataKeep=Saxla (tövsiyə olunur)
az.DataDelete=Sil
id.DataQuestion=Simpan akun dan pengaturan Anda?
id.DataText=Semuanya tetap di folder user-data, jadi akan kembali saat aplikasi dipasang lagi. Hapus hanya jika Anda tidak akan memakai Firefox VPN lagi.
id.DataKeep=Simpan (disarankan)
id.DataDelete=Hapus
es.DataQuestion=¿Conservar tus cuentas y ajustes?
es.DataText=Se quedan en la carpeta user-data, así que vuelven al instalar de nuevo la aplicación. Bórralos solo si no vas a volver a usar Firefox VPN.
es.DataKeep=Conservarlos (recomendado)
es.DataDelete=Borrarlos
fr.DataQuestion=Conserver vos comptes et paramètres ?
fr.DataText=Ils restent dans le dossier user-data et reviennent si vous réinstallez l'application. Ne les supprimez que si vous n'utiliserez plus Firefox VPN.
fr.DataKeep=Les conserver (recommandé)
fr.DataDelete=Les supprimer
hu.DataQuestion=Megtartja a fiókjait és a beállításait?
hu.DataText=A user-data mappában maradnak, így az alkalmazás újratelepítésekor visszakerülnek. Csak akkor törölje őket, ha többé nem használja a Firefox VPN-t.
hu.DataKeep=Megtartás (ajánlott)
hu.DataDelete=Törlés
pt.DataQuestion=Manter suas contas e configurações?
pt.DataText=Elas ficam na pasta user-data e voltam se você instalar o aplicativo de novo. Apague-as só se não for mais usar o Firefox VPN.
pt.DataKeep=Manter (recomendado)
pt.DataDelete=Apagar
vi.DataQuestion=Giữ lại tài khoản và cài đặt của bạn?
vi.DataText=Chúng vẫn nằm trong thư mục user-data, nên sẽ quay lại khi bạn cài lại ứng dụng. Chỉ xóa nếu bạn sẽ không dùng Firefox VPN nữa.
vi.DataKeep=Giữ lại (khuyên dùng)
vi.DataDelete=Xóa
bn.DataQuestion=আপনার অ্যাকাউন্ট ও সেটিংস রেখে দেবেন?
bn.DataText=এগুলো user-data ফোল্ডারে থেকে যায়, তাই অ্যাপটি আবার ইনস্টল করলে ফিরে আসে। Firefox VPN আর ব্যবহার না করলে তবেই মুছুন।
bn.DataKeep=রেখে দিন (প্রস্তাবিত)
bn.DataDelete=মুছে ফেলুন
; A chosen folder the user cannot write to (such as Program Files).
DirNotWritable=Firefox VPN can't write to this folder. It keeps your accounts and settings beside itself, so it needs a folder you can change without administrator rights (not Program Files). Choose another folder.
fa.DirNotWritable=Firefox VPN نمی‌تواند در این پوشه بنویسد. حساب‌ها و تنظیمات کنار خود برنامه نگه داشته می‌شوند، پس پوشه‌ای لازم است که بدون دسترسی Administrator قابل تغییر باشد (نه Program Files). پوشه دیگری انتخاب کنید.
ar.DirNotWritable=لا يستطيع Firefox VPN الكتابة في هذا المجلد. فهو يحتفظ بحساباتك وإعداداتك بجانبه، لذا يحتاج إلى مجلد يمكنك تعديله دون صلاحيات المسؤول (وليس Program Files). اختر مجلدًا آخر.
ru.DirNotWritable=Firefox VPN не может записывать в эту папку. Аккаунты и настройки хранятся рядом с программой, поэтому нужна папка, которую можно менять без прав администратора (не Program Files). Выберите другую папку.
tr.DirNotWritable=Firefox VPN bu klasöre yazamıyor. Hesaplarınız ve ayarlarınız uygulamanın yanında tutulur; bu yüzden yönetici hakları olmadan değiştirebileceğiniz bir klasör gerekir (Program Files değil). Başka bir klasör seçin.
az.DirNotWritable=Firefox VPN bu qovluğa yaza bilmir. Hesablarınız və ayarlarınız tətbiqin yanında saxlanılır, ona görə də administrator hüquqları olmadan dəyişə biləcəyiniz qovluq lazımdır (Program Files yox). Başqa qovluq seçin.
id.DirNotWritable=Firefox VPN tidak dapat menulis ke folder ini. Akun dan pengaturan Anda disimpan di samping aplikasi, jadi diperlukan folder yang dapat Anda ubah tanpa hak administrator (bukan Program Files). Pilih folder lain.
es.DirNotWritable=Firefox VPN no puede escribir en esta carpeta. Guarda tus cuentas y ajustes junto a sí mismo, así que necesita una carpeta que puedas modificar sin permisos de administrador (no Program Files). Elige otra carpeta.
fr.DirNotWritable=Firefox VPN ne peut pas écrire dans ce dossier. Il garde vos comptes et paramètres à côté de lui ; il lui faut donc un dossier modifiable sans droits d'administrateur (pas Program Files). Choisissez un autre dossier.
hu.DirNotWritable=A Firefox VPN nem tud írni ebbe a mappába. A fiókjait és a beállításait maga mellett tárolja, ezért olyan mappa kell, amelyet rendszergazdai jogok nélkül módosíthat (nem a Program Files). Válasszon másik mappát.
pt.DirNotWritable=O Firefox VPN não consegue gravar nesta pasta. Ele guarda suas contas e configurações ao lado de si, então precisa de uma pasta que você possa alterar sem direitos de administrador (não a Program Files). Escolha outra pasta.
vi.DirNotWritable=Firefox VPN không thể ghi vào thư mục này. Tài khoản và cài đặt của bạn được lưu ngay cạnh ứng dụng, nên cần một thư mục bạn có thể thay đổi mà không cần quyền quản trị (không phải Program Files). Hãy chọn thư mục khác.
bn.DirNotWritable=Firefox VPN এই ফোল্ডারে লিখতে পারছে না। আপনার অ্যাকাউন্ট ও সেটিংস অ্যাপের পাশেই রাখা হয়, তাই এমন একটি ফোল্ডার দরকার যা অ্যাডমিনিস্ট্রেটর অনুমতি ছাড়াই বদলানো যায় (Program Files নয়)। অন্য একটি ফোল্ডার বেছে নিন।

[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"

; Versions before 1.1.2 kept the core beside the app; it is in core\ now.
[InstallDelete]
Type: files; Name: "{app}\firefox-vpn-core.exe"

[Files]
; Never an existing data folder, if one was in the source.
Source: "{#SourceDir}\*"; DestDir: "{app}"; Excludes: "user-data,portable"; Flags: ignoreversion recursesubdirs createallsubdirs

[Icons]
Name: "{autoprograms}\{#AppName}"; Filename: "{app}\{#AppExe}"
Name: "{autodesktop}\{#AppName}"; Filename: "{app}\{#AppExe}"; Tasks: desktopicon

[Run]
; The TUN service, always (no task to choose), with its own administrator
; prompt; declined, the app installs it the first time TUN mode is chosen.
; Not in a silent run: no prompt there, and an installed service updates
; itself from the app.
Filename: "{app}\core\firefox-vpn-tun.exe"; Parameters: "install"; Flags: waituntilterminated skipifsilent; Check: not TunServiceInstalled
Filename: "{app}\{#AppExe}"; Description: "{cm:LaunchProgram,{#AppName}}"; Flags: nowait postinstall skipifsilent

; The TUN service goes with the app: through its pipe, with no prompt while
; it runs; it does nothing when the service is not installed.
[UninstallRun]
Filename: "{app}\core\firefox-vpn-tun.exe"; Parameters: "uninstall"; Flags: waituntilterminated; RunOnceId: "RemoveTunService"

; The app updates itself (core\internal\update) by replacing its files, so
; this uninstaller does not know every file a later version brought: the
; app's own files and folders go, whichever version put them there.
; user-data stays for the question below.
[UninstallDelete]
Type: filesandordirs; Name: "{app}\core"
Type: filesandordirs; Name: "{app}\data"
Type: files; Name: "{app}\*.dll"
Type: files; Name: "{app}\{#AppExe}"
Type: files; Name: "{app}\native_assets.json"

[Code]
const
  RunKey = 'Software\Microsoft\Windows\CurrentVersion\Run';
  InternetKey = 'Software\Microsoft\Windows\CurrentVersion\Internet Settings';
  // Where an uninstall that kept the data notes the folder it is in.
  KeptKey = 'Software\{#AppName}';
  KeptValue = 'KeptDataIn';

// The folder a first install offers: the one an uninstalled copy left its
// data in, so installing again brings the data back; else the usual one.
function DefaultDir(Param: String): String;
begin
  if not RegQueryStringValue(HKCU, KeptKey, KeptValue, Result) or
     not DirExists(AddBackslash(Result) + 'user-data') then
    Result := ExpandConstant('{localappdata}\Programs\{#AppDir}');
end;

// TunServiceInstalled tells whether the TUN mode's Windows service is
// installed (core\cmd\firefox-vpn-tun).
function TunServiceInstalled: Boolean;
begin
  Result := RegKeyExists(HKLM, 'SYSTEM\CurrentControlSet\Services\FirefoxVPNTun');
end;

// IsUnder tells whether Dir is Parent or a folder inside it.
function IsUnder(Dir, Parent: String): Boolean;
begin
  Result := Pos(AddBackslash(Lowercase(Parent)), AddBackslash(Lowercase(Dir))) = 1;
end;

// CanWrite tells whether the user can create files in Dir, which the app's
// user-data needs; a folder it had to make for the test is removed again.
// Setup started as administrator can write to the system's folders, which
// the app, started normally, cannot: those are refused outright.
function CanWrite(Dir: String): Boolean;
var
  Made: Boolean;
  Probe: String;
begin
  if IsAdmin and (IsUnder(Dir, ExpandConstant('{commonpf32}')) or
     IsUnder(Dir, ExpandConstant('{commonpf64}')) or
     IsUnder(Dir, ExpandConstant('{commonappdata}')) or
     IsUnder(Dir, ExpandConstant('{win}'))) then
  begin
    Result := False;
    Exit;
  end;
  Made := not DirExists(Dir);
  Result := ForceDirectories(Dir);
  if Result then
  begin
    Probe := AddBackslash(Dir) + 'write-test.tmp';
    Result := SaveStringToFile(Probe, '', False);
    DeleteFile(Probe);
  end;
  if Made then
    RemoveDir(Dir);
end;

// A chosen folder the user cannot write to is refused before anything is
// installed (also in a silent install with /DIR).
function NextButtonClick(CurPageID: Integer): Boolean;
begin
  Result := True;
  if (CurPageID = wpSelectDir) and not CanWrite(WizardDirValue) then
  begin
    SuppressibleMsgBox(CustomMessage('DirNotWritable'), mbError, MB_OK, IDOK);
    Result := False;
  end;
end;

// Installed: the new copy's own uninstall entry knows its folder now.
procedure CurStepChanged(CurStep: TSetupStep);
begin
  if CurStep = ssPostInstall then
  begin
    RegDeleteValue(HKCU, KeptKey, KeptValue);
    RegDeleteKeyIfEmpty(HKCU, KeptKey);
  end;
end;

// Uninstalling: the app's autostart entry goes, and so does a Windows
// proxy setting the app left pointing at its own (now gone) proxy; then
// the data, if the user wants. Kept data's folder is noted for the next
// install.
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
var
  Enabled: Cardinal;
  Server: String;
  Data: String;
begin
  if CurUninstallStep = usUninstall then
  begin
    RegDeleteValue(HKCU, RunKey, '{#AppName}');
    if RegQueryDWordValue(HKCU, InternetKey, 'ProxyEnable', Enabled) and (Enabled = 1) and
       RegQueryStringValue(HKCU, InternetKey, 'ProxyServer', Server) and
       (Pos('127.0.0.1:', Server) = 1) then
      RegWriteDWordValue(HKCU, InternetKey, 'ProxyEnable', 0);
  end;
  if CurUninstallStep = usPostUninstall then
  begin
    Data := ExpandConstant('{app}\user-data');
    // Keep is the first and default button; a silent uninstall keeps too.
    if DirExists(Data) and not UninstallSilent and
       (TaskDialogMsgBox(CustomMessage('DataQuestion'), CustomMessage('DataText'), mbConfirmation,
          MB_YESNO, [CustomMessage('DataKeep'), CustomMessage('DataDelete')], 0) = IDNO) then
      DelTree(Data, True, True, True);
    if DirExists(Data) then
      RegWriteStringValue(HKCU, KeptKey, KeptValue, ExpandConstant('{app}'))
    else
    begin
      RegDeleteValue(HKCU, KeptKey, KeptValue);
      RegDeleteKeyIfEmpty(HKCU, KeptKey);
    end;
    RemoveDir(ExpandConstant('{app}'));
  end;
end;