Subversion Repositories autosfx

Rev

Rev 2 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2 Rev 3
Line 1... Line 1...
1
unit ExtractorMain;
1
unit ExtractorMain;
2
 
2
 
3
{$DEFINE USE_DZIP_UNPACK}
3
{$DEFINE USE_DZIP_UNPACK}
4
 
4
 
5
// todo: compilerswitch, der auch selectdirectory() anzeigt (ohne foldercreate)
-
 
6
 
-
 
7
interface
5
interface
8
 
6
 
9
uses
7
uses
10
  Windows, SysUtils, Classes, Controls, Forms, Dialogs, StdCtrls, ShellAPI,
8
  Windows, SysUtils, Classes, Controls, Forms, Dialogs, StdCtrls, ShellAPI,
11
  ExtCtrls, ComCtrls, ZipMstr19, ZMMsgStr19, ZMMsg19, ZMDelZip19,
9
  ExtCtrls, ComCtrls, ZipMstr19, ZMMsgStr19, ZMMsg19, ZMDelZip19,
Line 24... Line 22...
24
    procedure CancelBtnClick(Sender: TObject);
22
    procedure CancelBtnClick(Sender: TObject);
25
    procedure FormCreate(Sender: TObject);
23
    procedure FormCreate(Sender: TObject);
26
    procedure AutoTimerTimer(Sender: TObject);
24
    procedure AutoTimerTimer(Sender: TObject);
27
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
25
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
28
  private
26
  private
-
 
27
    ExtractionInProcess: boolean;
-
 
28
    uz: TZipMaster19;
29
    RenamingOldPrefix: string;
29
    RenamingOldPrefix: string;
30
    RenamingNewPrefix: string;
30
    RenamingNewPrefix: string;
31
    zb: TZIPBehavior;
31
    zb: TZIPBehavior;
32
    BaseDir: string;
32
    BaseDir: string;
33
    AbortUnzip: boolean;
33
    AbortUnzip: boolean;
34
    StopAskingPassword: boolean;
34
    StopAskingPassword: boolean;
35
    LastTriedPassword: string;
35
    LastTriedPassword: string;
36
    OverwriteDecision: TOverwriteDecision;
36
    CachedOverwriteDecision: TOverwriteDecision;
37
    {$IFNDEF USE_DZIP_UNPACK}
37
    {$IFNDEF USE_DZIP_UNPACK}
38
    procedure ExtractDllFromResource(ADirectory: string);
38
    procedure ExtractDllFromResource(ADirectory: string);
39
    {$ENDIF}
39
    {$ENDIF}
40
    procedure ExtractZipHere(AZipfile: string);
40
    procedure ExtractZipHere(AZipfile: string);
41
    procedure ArcExtFNChange(Sender: TObject; var FileName: TZMString; const BaseDir: TZMString; var IsChanged: Boolean);
41
    procedure EvExtFNChange(Sender: TObject; var FileName: TZMString; const BaseDir: TZMString; var IsChanged: Boolean);
42
    procedure ArcProzess(Sender: TObject; details: TZMProgressDetails);
42
    procedure EvProgress(Sender: TObject; details: TZMProgressDetails);
43
    procedure ArcTick(Sender: TObject);
43
    procedure EvTick(Sender: TObject);
44
    procedure ArcCheckTerminate(Sender: TObject; var abort: Boolean);
44
    procedure EvCheckTerminate(Sender: TObject; var abort: Boolean);
45
    procedure ConfirmOverwrite(Sender: TObject; const ForFile: TZMString;
45
    procedure EvConfirmOverwrite(Sender: TObject; const ForFile: TZMString;
46
      IsOlder: Boolean; var DoOverwrite: Boolean; DirIndex: Integer);
46
      IsOlder: Boolean; var DoOverwrite: Boolean; DirIndex: Integer);
47
    procedure ArcPassword(Sender: TObject; IsZipAction: Boolean;
47
    procedure EvPasswordEvent(Sender: TObject; IsZipAction: Boolean;
48
      var NewPassword: String; const ForFile: TZMString; var RepeatCount: Longword;
48
      var NewPassword: String; const ForFile: TZMString; var RepeatCount: Longword;
49
      var Action: TMsgDlgBtn);
49
      var Action: TMsgDlgBtn);
50
    procedure SkipEvent(Sender: TObject; const ForFile: TZMString;
50
    procedure EvSkipEvent(Sender: TObject; const ForFile: TZMString;
51
      SkipType: TZMSkipTypes; var ExtError: Integer);
51
      SkipType: TZMSkipTypes; var ExtError: Integer);
52
    function StripBaseDir(const s: string): string;
52
    function StripBaseDir(const s: string): string;
53
  end;
53
  end;
54
 
54
 
55
var
55
var
56
  MainForm: TMainForm;
56
  MainForm: TMainForm;
57
 
57
 
58
implementation
58
implementation
59
 
59
 
60
uses
60
uses
61
  ExtractorPassword, ExtractorError, Functions, SFXAutoRun, ExtractorComment;
61
  ExtractorPassword, ExtractorError, Functions, SFXAutoRun, ExtractorComment,
-
 
62
  BrowseFolder;
62
 
63
 
63
const
64
const
64
  MaxTries = 15;
65
  EvPasswordTries = 15;
65
 
66
 
66
{$R *.dfm}
67
{$R *.dfm}
67
 
68
 
68
{$R zmstr1900102\DLL\ResDLL-Maker\ZMRes19_dll.res}
69
{$R zmstr1900102\DLL\ResDLL-Maker\ZMRes19_dll.res}
69
 
70
 
Line 141... Line 142...
141
  end;
142
  end;
142
end;
143
end;
143
 
144
 
144
procedure TMainForm.ExtractZipHere(AZipfile: string);
145
procedure TMainForm.ExtractZipHere(AZipfile: string);
145
var
146
var
146
  uz: TZipMaster19;
-
 
147
  l: TStringList;
147
  l: TStringList;
148
  s: string;
148
  s: string;
149
  ec: Integer;
149
  ec: Integer;
150
  ar: TExecuteSFXAutoRunResult;
150
  ar: TExecuteSFXAutoRunResult;
151
  GeneralBaseDir: string;
151
  GeneralBaseDir: string;
-
 
152
const
-
 
153
  C_Explorer_Open_Param = '"%s"';
-
 
154
  C_Explorer_Select_Param = '/n,/select,"%s"';
-
 
155
  EXPLORER_EXE = 'explorer';
152
resourcestring
156
resourcestring
153
  Lng_Aborted = 'Der laufende Prozess wurde abgebrochen. Das extrahierten Dateien sind somit unvollständig.';
157
  Lng_Aborted = 'Der laufende Prozess wurde abgebrochen. Das extrahierten Dateien sind somit unvollständig.';
154
  Lng_Zip_Error = 'ZIP-Master Fehler "%s" (%d)';
158
  Lng_Zip_Error = 'ZIP-Master Fehler "%s" (%d)';
155
  Lng_AutoRunFailed = 'SFX-AutoRun fehlgeschlagen. Die entpackten Inhalte werden nun angezeigt.';
159
  Lng_AutoRunFailed = 'SFX-AutoRun fehlgeschlagen. Die entpackten Inhalte werden nun angezeigt.';
156
  Lng_Unknown_Error = 'Unbekannter Fehler: Dateien sind nicht aufzufinden!';
160
  Lng_Unknown_Error = 'Unbekannter Fehler: Dateien sind nicht aufzufinden!';
Line 158... Line 162...
158
begin
162
begin
159
  AZipfile := ExpandUNCFileName(AZipfile);
163
  AZipfile := ExpandUNCFileName(AZipfile);
160
  RenamingOldPrefix := '';
164
  RenamingOldPrefix := '';
161
  RenamingNewPrefix := '';
165
  RenamingNewPrefix := '';
162
 
166
 
-
 
167
  if Assigned(uz) then uz.Free; // uz ist global, damit AbortDLL aufgerufen werden kann
-
 
168
 
163
  uz := TZipMaster19.Create(nil);
169
  uz := TZipMaster19.Create(nil);
164
  try
170
  try
-
 
171
    ExtractionInProcess := true;
165
    {$IFNDEF USE_DZIP_UNPACK}
172
    {$IFNDEF USE_DZIP_UNPACK}
166
    uz.DLLDirectory := GetTempDirectory + DelZipDLL_Name;
173
    uz.DLLDirectory := GetTempDirectory + DelZipDLL_Name;
167
    {$ENDIF}
174
    {$ENDIF}
168
    uz.DLL_Load := true;
175
    uz.DLL_Load := true;
169
 
176
 
Line 173... Line 180...
173
 
180
 
174
    uz.Unattended := true;
181
    uz.Unattended := true;
175
    uz.ExtrOptions := [ExtrDirNames, ExtrOverWrite, ExtrFreshen, ExtrUpdate,
182
    uz.ExtrOptions := [ExtrDirNames, ExtrOverWrite, ExtrFreshen, ExtrUpdate,
176
      ExtrForceDirs, ExtrNTFS];
183
      ExtrForceDirs, ExtrNTFS];
177
 
184
 
178
    if zb.ConflictBehavior <> cbAvoid then
-
 
179
    begin
-
 
180
      uz.OnExtractOverwrite := ConfirmOverwrite;
185
    uz.OnExtractOverwrite := EvConfirmOverwrite;
181
    end;
-
 
182
    uz.OnProgress := ArcProzess;
186
    uz.OnProgress := EvProgress;
183
    uz.OnTick := ArcTick;
187
    uz.OnTick := EvTick;
184
    uz.OnCheckTerminate := ArcCheckTerminate;
188
    uz.OnCheckTerminate := EvCheckTerminate;
185
    uz.OnPasswordError := ArcPassword;
189
    uz.OnPasswordError := EvPasswordEvent;
186
    uz.PasswordReqCount := MaxTries;
190
    uz.PasswordReqCount := EvPasswordTries;
187
    uz.OnSkipped := SkipEvent;
191
    uz.OnSkipped := EvSkipEvent;
188
    uz.OnSetExtName := ArcExtFNChange;
192
    uz.OnSetExtName := EvExtFNChange;
189
    // TODO: Mehr events?
-
 
190
 
193
 
191
    // Find out base dirtory
194
    // Find out base dirtory
192
 
195
 
193
    GeneralBaseDir := '';
196
    GeneralBaseDir := '';
194
    case zb.ExtractionTarget of
197
    case zb.ExtractionTarget of
Line 200... Line 203...
200
        begin
203
        begin
201
          GeneralBaseDir := GetSpecialFolderPath(CSIDL_DESKTOP);
204
          GeneralBaseDir := GetSpecialFolderPath(CSIDL_DESKTOP);
202
        end;
205
        end;
203
      etAsk:
206
      etAsk:
204
        begin
207
        begin
205
          if not AdvSelectDirectory(Lng_SelectDir, '', GeneralBaseDir, False, False, True) then
208
          GeneralBaseDir := MySelectDirectory(Lng_SelectDir);
206
          begin
-
 
207
            Exit;
209
          if GeneralBaseDir = '' then Exit;
208
          end;
-
 
209
        end;
210
        end;
210
    end;
211
    end;
211
    GeneralBaseDir := IncludeTrailingPathDelimiter(GeneralBaseDir);
212
    GeneralBaseDir := IncludeTrailingPathDelimiter(GeneralBaseDir);
212
 
213
 
213
    // Semantic scanning of ZIP to determinate the final extraction directory
214
    // Semantic scanning of ZIP to determinate the final extraction directory
Line 309... Line 310...
309
      if not ar.AutoRunSectionAvailable or ar.OpenUnzippedContent then
310
      if not ar.AutoRunSectionAvailable or ar.OpenUnzippedContent then
310
      begin
311
      begin
311
        if DirectoryExists(s) then
312
        if DirectoryExists(s) then
312
        begin
313
        begin
313
          // If it is a folder, open it
314
          // If it is a folder, open it
-
 
315
 
314
          ShellExecute(0, 'open', 'explorer',
316
          ShellExecute(0, 'open', EXPLORER_EXE,
315
            PChar('"'+s+'"'), '', SW_NORMAL);
317
            PChar(Format(C_Explorer_Open_Param, [s])), '', SW_NORMAL);
316
        end
318
        end
317
        else if FileExists(s) then
319
        else if FileExists(s) then
318
        begin
320
        begin
319
          // If it is a file, then only select it
321
          // If it is a file, then only select it
320
 
322
 
321
          // Que: Funktioniert das auch ohne "/n"?
323
          // Que: Funktioniert das auch ohne "/n"?
322
          // Im Moment wird bei einem BESTEHENDEN Fenster
324
          // Im Moment wird bei einem BESTEHENDEN Fenster
323
          // die Selektion nicht durchgeführt.
325
          // die Selektion nicht durchgeführt.
324
 
326
 
325
          ShellExecute(0, 'open', 'explorer',
327
          ShellExecute(0, 'open', EXPLORER_EXE,
326
            PChar('/n,/select,"'+s+'"'), '', SW_NORMAL);
328
            PChar(Format(C_Explorer_Select_Param, [s])), '', SW_NORMAL);
327
        end
329
        end
328
        else
330
        else
329
        begin
331
        begin
-
 
332
          if not AbortUnzip then
-
 
333
          begin
330
          MessageDlg(Lng_Unknown_Error, mtError, [mbOk], 0);
334
            MessageDlg(Lng_Unknown_Error, mtError, [mbOk], 0);
331
        end;
335
          end;
332
      end;
336
        end;
-
 
337
      end;
333
    finally
338
    finally
334
      l.Free;
339
      l.Free;
335
    end;
340
    end;
336
  finally
341
  finally
337
    uz.Free;
342
    uz.Free;
-
 
343
    ExtractionInProcess := false;
338
  end;
344
  end;
339
end;
345
end;
340
 
346
 
341
procedure TMainForm.ArcProzess(Sender: TObject; details: TZMProgressDetails);
347
procedure TMainForm.EvProgress(Sender: TObject; details: TZMProgressDetails);
342
begin
348
begin
343
  CurrentFileLabel.Caption := details.ItemName;
349
  CurrentFileLabel.Caption := details.ItemName;
344
 
350
 
345
  progressBar.Position := details.TotalPosition;
351
  progressBar.Position := details.TotalPosition;
346
  progressBar.Max := details.TotalSize;
352
  progressBar.Max := details.TotalSize;
Line 349... Line 355...
349
  itemBar.Max := details.ItemSize;
355
  itemBar.Max := details.ItemSize;
350
 
356
 
351
  Application.ProcessMessages;
357
  Application.ProcessMessages;
352
end;
358
end;
353
 
359
 
354
procedure TMainForm.ArcExtFNChange(Sender: TObject;
360
procedure TMainForm.EvExtFNChange(Sender: TObject;
355
  var FileName: TZMString; const BaseDir: TZMString;
361
  var FileName: TZMString; const BaseDir: TZMString;
356
  var IsChanged: Boolean);
362
  var IsChanged: Boolean);
357
begin
363
begin
358
  if RenamingOldPrefix = RenamingNewPrefix then Exit;
364
  if RenamingOldPrefix = RenamingNewPrefix then Exit;
359
  FileName := RenamingNewPrefix + Copy(FileName, 1+Length(RenamingOldPrefix), Length(FileName)-Length(RenamingOldPrefix));
365
  FileName := RenamingNewPrefix + Copy(FileName, 1+Length(RenamingOldPrefix), Length(FileName)-Length(RenamingOldPrefix));
360
  IsChanged := true;
366
  IsChanged := true;
361
end;
367
end;
362
 
368
 
363
procedure TMainForm.ArcTick(Sender: TObject);
369
procedure TMainForm.EvTick(Sender: TObject);
364
begin
370
begin
365
  Application.ProcessMessages;
371
  Application.ProcessMessages;
366
end;
372
end;
367
 
373
 
368
procedure TMainForm.ArcCheckTerminate(Sender: TObject; var abort: Boolean);
374
procedure TMainForm.EvCheckTerminate(Sender: TObject; var abort: Boolean);
369
begin
375
begin
370
  abort := AbortUnzip;
376
  abort := AbortUnzip;
371
end;
377
end;
372
 
378
 
373
procedure TMainForm.ConfirmOverwrite(Sender: TObject; const ForFile: TZMString;
379
procedure TMainForm.EvConfirmOverwrite(Sender: TObject; const ForFile: TZMString;
374
  IsOlder: Boolean; var DoOverwrite: Boolean; DirIndex: Integer);
380
  IsOlder: Boolean; var DoOverwrite: Boolean; DirIndex: Integer);
375
resourcestring
381
resourcestring
376
  Lng_Overwrite = 'Bestehende Datei "%s" überschreiben?';
382
  Lng_Overwrite = 'Bestehende Datei "%s" überschreiben?';
377
var
383
var
378
  res: Integer;
384
  res: Integer;
Line 395... Line 401...
395
    begin
401
    begin
396
      DoOverwrite := true;
402
      DoOverwrite := true;
397
      Exit;
403
      Exit;
398
    end;
404
    end;
399
 
405
 
400
    if OverwriteDecision = odUndefined then
406
    if CachedOverwriteDecision = odUndefined then
401
    begin
407
    begin
402
      res := MessageDlg(Format(Lng_Overwrite, [ForFile]), mtConfirmation, [mbYes, mbNo, mbYesToAll, mbNoToAll], 0);
408
      res := MessageDlg(Format(Lng_Overwrite, [ForFile]), mtConfirmation, [mbYes, mbNo, mbYesToAll, mbNoToAll], 0);
403
      DoOverwrite := (res = mrYes) or (res = mrYesToAll);
409
      DoOverwrite := (res = mrYes) or (res = mrYesToAll);
404
      if res = mrNoToAll then OverwriteDecision := odOverwriteNothing;
410
      if res = mrNoToAll then CachedOverwriteDecision := odOverwriteNothing;
405
      if res = mrYesToAll then OverwriteDecision := odOverwriteAll;
411
      if res = mrYesToAll then CachedOverwriteDecision := odOverwriteAll;
406
    end
412
    end
407
    else
413
    else
408
    begin
414
    begin
409
      DoOverwrite := OverwriteDecision = odOverwriteAll;
415
      DoOverwrite := CachedOverwriteDecision = odOverwriteAll;
410
    end;
416
    end;
-
 
417
  end
-
 
418
  else if zb.ConflictBehavior = cbAvoid then
-
 
419
  begin
-
 
420
    // Nothing to do
411
  end;
421
  end;
412
end;
422
end;
413
 
423
 
414
procedure TMainForm.ArcPassword(Sender: TObject; IsZipAction: Boolean;
424
procedure TMainForm.EvPasswordEvent(Sender: TObject; IsZipAction: Boolean;
415
  var NewPassword: String; const ForFile: TZMString; var RepeatCount: Longword;
425
  var NewPassword: String; const ForFile: TZMString; var RepeatCount: Longword;
416
  var Action: TMsgDlgBtn);
426
  var Action: TMsgDlgBtn);
417
var
427
var
418
  repc: integer;
428
  repc: integer;
419
begin
429
begin
420
  repc := MaxTries - RepeatCount + 1;
430
  repc := EvPasswordTries - RepeatCount + 1;
421
 
431
 
422
  // Eine Passworteingabe wurde abgebrochen. Frage nicht mehr nach.
432
  // Eine Passworteingabe wurde abgebrochen. Frage nicht mehr nach.
423
  if StopAskingPassword then Exit;
433
  if StopAskingPassword then Exit;
424
 
434
 
425
  // Wurde schonmal ein Passwort eingegeben?
435
  // Wurde schonmal ein Passwort eingegeben?
Line 437... Line 447...
437
      // Leider nein
447
      // Leider nein
438
      LastTriedPassword := '';
448
      LastTriedPassword := '';
439
    end;
449
    end;
440
  end;
450
  end;
441
 
451
 
442
  if PasswordDlg.ShowModal(StripBaseDir(ForFile), repc, MaxTries) = mrOk then
452
  if PasswordDlg.ShowModal(StripBaseDir(ForFile), repc, EvPasswordTries) = mrOk then
443
  begin
453
  begin
444
    NewPassword := PasswordDlg.Password.Text;
454
    NewPassword := PasswordDlg.Password.Text;
445
    if NewPassword = '' then NewPassword := ' '; // Neue Eingabe erzwingen.
455
    if NewPassword = '' then NewPassword := ' '; // Neue Eingabe erzwingen.
446
    LastTriedPassword := NewPassword;
456
    LastTriedPassword := NewPassword;
447
  end
457
  end
Line 454... Line 464...
454
 
464
 
455
procedure TMainForm.CancelBtnClick(Sender: TObject);
465
procedure TMainForm.CancelBtnClick(Sender: TObject);
456
resourcestring
466
resourcestring
457
  Lng_AbortExtract = 'Extrahieren abbrechen?';
467
  Lng_AbortExtract = 'Extrahieren abbrechen?';
458
begin
468
begin
-
 
469
  if not ExtractionInProcess then
-
 
470
  begin
-
 
471
    Close;
-
 
472
    Exit;
-
 
473
  end;
-
 
474
 
459
  if MessageDlg(Lng_AbortExtract, mtConfirmation, mbYesNoCancel, 0) = mrYes then
475
  if MessageDlg(Lng_AbortExtract, mtConfirmation, mbYesNoCancel, 0) = mrYes then
460
  begin
476
  begin
461
    CancelBtn.Enabled := false;
477
    CancelBtn.Enabled := false;
-
 
478
    uz.AbortDLL;
462
    AbortUnzip := true;
479
    AbortUnzip := true;
-
 
480
    // Close wird durch den Timer durchgeführt
-
 
481
    Exit;
463
  end;
482
  end;
464
end;
483
end;
465
 
484
 
466
procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
485
procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
467
begin
486
begin
-
 
487
  if not ExtractionInProcess then
-
 
488
  begin
-
 
489
    CanClose := true;
-
 
490
    Exit;
-
 
491
  end;
-
 
492
 
468
  if not AbortUnzip then
493
  if not AbortUnzip then
469
  begin
494
  begin
470
    CancelBtn.Click;
-
 
471
    CanClose := false;
495
    CanClose := false;
-
 
496
    CancelBtn.Click;
472
  end;
497
  end;
473
end;
498
end;
474
 
499
 
475
procedure TMainForm.FormCreate(Sender: TObject);
500
procedure TMainForm.FormCreate(Sender: TObject);
476
resourcestring
501
resourcestring
Line 563... Line 588...
563
        // Future: Mehr als nur 1 Parameter erlauben?
588
        // Future: Mehr als nur 1 Parameter erlauben?
564
        MessageDlg(Lng_TooManyArguments, mtError, [mbOk], 0);
589
        MessageDlg(Lng_TooManyArguments, mtError, [mbOk], 0);
565
      end;
590
      end;
566
    end;
591
    end;
567
  finally
592
  finally
568
    AbortUnzip := true; // Damit es zu keiner Abfrage in OnCloseQuery kommt
-
 
569
    Close;
593
    Close;
570
  end;
594
  end;
571
end;
595
end;
572
 
596
 
573
function TMainForm.StripBaseDir(const s: string): string;
597
function TMainForm.StripBaseDir(const s: string): string;
Line 575... Line 599...
575
  // Warnung: Es wird nicht überprüft, ob der String auch
599
  // Warnung: Es wird nicht überprüft, ob der String auch
576
  // wirklich mit dem BaseDir beginnt!
600
  // wirklich mit dem BaseDir beginnt!
577
  result := Copy(s, Length(BaseDir)+1, Length(s)-Length(BaseDir));
601
  result := Copy(s, Length(BaseDir)+1, Length(s)-Length(BaseDir));
578
end;
602
end;
579
 
603
 
580
procedure TMainForm.SkipEvent(Sender: TObject; const ForFile: TZMString;
604
procedure TMainForm.EvSkipEvent(Sender: TObject; const ForFile: TZMString;
581
  SkipType: TZMSkipTypes; var ExtError: Integer);
605
  SkipType: TZMSkipTypes; var ExtError: Integer);
582
resourcestring
606
resourcestring
583
  Lng_PasswordWrong = 'Das Passwort wurde zu oft falsch eingegeben. Die Datei "%s" wird nicht extrahiert.';
607
  Lng_PasswordWrong = 'Das Passwort wurde zu oft falsch eingegeben. Die Datei "%s" wird nicht extrahiert.';
584
begin
608
begin
585
  if (SkipType = stBadPassword) and not StopAskingPassword then
609
  if (SkipType = stBadPassword) and not StopAskingPassword then