/Extractor.exe.manifest |
---|
File deleted |
/Extractor.rc |
---|
File deleted |
/BrowseFolder.pas |
---|
File deleted |
/TODO.TXT |
---|
File deleted |
/LICENSE |
---|
File deleted |
/MakeSFX.rc |
---|
File deleted |
/MakeSFX.exe.manifest |
---|
File deleted |
/resource.h |
---|
File deleted |
/Readme.md |
---|
File deleted |
\ No newline at end of file |
/MakeSFX.res |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/BuildTests.bat |
---|
1,5 → 1,4 |
@echo off |
MakeSFX Tests\helloworld.zip |
MakeSFX Tests\single_file.zip |
MakeSFX Tests\test.zip |
MakeSFX helloworld.zip |
MakeSFX test.zip |
pause. |
/Future.txt |
---|
10,7 → 10,3 |
testen, was bei leerer zip passieren würde |
type TZMReplaceOpts = (rplConfirm, rplAlways, rplNewer, rplNever); |
Bei MakeSFX.exe vorher einen Extraktionstest durchführen? (um z.B. Compressionsfehler etc. auszuschließen?) |
Einen ZIP-Packer/Modifier, der auch korrekte Kommentare erstellt (Checkboxes zur Unterstützung) machen? |
/ExtractorError.dfm |
---|
1,9 → 1,11 |
object ErrorForm: TErrorForm |
Left = 222 |
Top = 133 |
BorderIcons = [biSystemMenu] |
BorderStyle = bsSingle |
Caption = 'Fehler' |
ClientHeight = 406 |
ClientWidth = 583 |
ClientHeight = 365 |
ClientWidth = 355 |
Color = clBtnFace |
Font.Charset = ANSI_CHARSET |
Font.Color = clWindowText |
12,7 → 14,6 |
Font.Style = [] |
OldCreateOrder = False |
Position = poMainFormCenter |
OnResize = FormResize |
PixelsPerInch = 96 |
TextHeight = 13 |
object ErrorImg: TImage |
814,20 → 815,4 |
ParentFont = False |
TabOrder = 1 |
end |
object SaveBtn: TButton |
Left = 64 |
Top = 328 |
Width = 97 |
Height = 25 |
Caption = 'Liste speichern' |
TabOrder = 2 |
OnClick = SaveBtnClick |
end |
object SaveDialog: TSaveDialog |
DefaultExt = '.txt' |
Filter = 'Textdateien (*.txt)|*.txt|Alle Dateien (*.*)|*.*' |
Options = [ofOverwritePrompt, ofHideReadOnly, ofPathMustExist, ofEnableSizing] |
Left = 320 |
Top = 8 |
end |
end |
/Icon.ico |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/SFXBehavior.pas |
---|
41,7 → 41,7 |
C_ASFX_ET_DES = 'AutoSFX Extraction Target: Extract to Desktop'; |
C_ASFX_ET_ASK = 'AutoSFX Extraction Target: Choose directory'; |
EINRUECK = '> '; // Optional to all C_ASFX |
EINRUECK = '> '; // Optional |
const |
CB_DEFAULT = cbAvoid; |
109,15 → 109,12 |
function StripBehavior(c: string): string; |
procedure StripIt(s: string; allowEinrueck: boolean); |
procedure StripIt(s: string); |
begin |
if allowEinrueck then |
begin |
c := StringReplace(c, EINRUECK + s+#13#10, '', [rfReplaceAll, rfIgnoreCase]); |
c := StringReplace(c, EINRUECK + s+#13, '', [rfReplaceAll, rfIgnoreCase]); |
c := StringReplace(c, EINRUECK + s+#10, '', [rfReplaceAll, rfIgnoreCase]); |
c := StringReplace(c, EINRUECK + s, '', [rfReplaceAll, rfIgnoreCase]); |
end; |
c := StringReplace(c, s+#13#10, '', [rfReplaceAll, rfIgnoreCase]); |
c := StringReplace(c, s+#13, '', [rfReplaceAll, rfIgnoreCase]); |
126,20 → 123,20 |
end; |
begin |
StripIt(C_SIGNATURE, false); |
StripIt(C_SIGNATURE); |
StripIt(C_ASFX_CB_AVO, true); |
StripIt(C_ASFX_CB_OVR, true); |
StripIt(C_ASFX_CB_NEW, true); |
StripIt(C_ASFX_CB_ASK, true); |
StripIt(C_ASFX_CB_AVO); |
StripIt(C_ASFX_CB_OVR); |
StripIt(C_ASFX_CB_NEW); |
StripIt(C_ASFX_CB_ASK); |
StripIt(C_ASFX_CP_NON, true); |
StripIt(C_ASFX_CP_BEF, true); |
StripIt(C_ASFX_CP_AFT, true); |
StripIt(C_ASFX_CP_NON); |
StripIt(C_ASFX_CP_BEF); |
StripIt(C_ASFX_CP_AFT); |
StripIt(C_ASFX_ET_HER, true); |
StripIt(C_ASFX_ET_DES, true); |
StripIt(C_ASFX_ET_ASK, true); |
StripIt(C_ASFX_ET_HER); |
StripIt(C_ASFX_ET_DES); |
StripIt(C_ASFX_ET_ASK); |
result := c; |
end; |
/ExtractorMain.pas |
---|
1,13 → 1,17 |
unit ExtractorMain; |
{$DEFINE USE_DZIP_UNPACK} // recommended |
{$DEFINE DEBUG_MODE} |
{$DEFINE USE_DZIP_UNPACK} |
// TODO: Implement ExtractionTarget switch |
interface |
uses |
Windows, SysUtils, Classes, Controls, Forms, Dialogs, StdCtrls, ShellAPI, |
ExtCtrls, ComCtrls, ZipMstr19, ZMMsgStr19, ZMMsg19, ZMDelZip19, |
ZMCompat19, SFXBehavior, ShlObj; |
ZMCompat19, SFXBehavior; |
type |
TOverwriteDecision = (odUndefined, odOverwriteAll, odOverwriteNothing); |
24,8 → 28,6 |
procedure AutoTimerTimer(Sender: TObject); |
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); |
private |
ExtractionInProcess: boolean; |
uz: TZipMaster19; |
RenamingOldPrefix: string; |
RenamingNewPrefix: string; |
zb: TZIPBehavior; |
33,21 → 35,21 |
AbortUnzip: boolean; |
StopAskingPassword: boolean; |
LastTriedPassword: string; |
CachedOverwriteDecision: TOverwriteDecision; |
OverwriteDecision: TOverwriteDecision; |
{$IFNDEF USE_DZIP_UNPACK} |
procedure ExtractDllFromResource(ADirectory: string); |
{$ENDIF} |
procedure ExtractZipHere(AZipfile: string); |
procedure EvExtFNChange(Sender: TObject; var FileName: TZMString; const BaseDir: TZMString; var IsChanged: Boolean); |
procedure EvProgress(Sender: TObject; details: TZMProgressDetails); |
procedure EvTick(Sender: TObject); |
procedure EvCheckTerminate(Sender: TObject; var abort: Boolean); |
procedure EvConfirmOverwrite(Sender: TObject; const ForFile: TZMString; |
procedure ArcExtFNChange(Sender: TObject; var FileName: TZMString; const BaseDir: TZMString; var IsChanged: Boolean); |
procedure ArcProzess(Sender: TObject; details: TZMProgressDetails); |
procedure ArcTick(Sender: TObject); |
procedure ArcCheckTerminate(Sender: TObject; var abort: Boolean); |
procedure ConfirmOverwrite(Sender: TObject; const ForFile: TZMString; |
IsOlder: Boolean; var DoOverwrite: Boolean; DirIndex: Integer); |
procedure EvPasswordEvent(Sender: TObject; IsZipAction: Boolean; |
procedure ArcPassword(Sender: TObject; IsZipAction: Boolean; |
var NewPassword: String; const ForFile: TZMString; var RepeatCount: Longword; |
var Action: TMsgDlgBtn); |
procedure EvSkipEvent(Sender: TObject; const ForFile: TZMString; |
procedure SkipEvent(Sender: TObject; const ForFile: TZMString; |
SkipType: TZMSkipTypes; var ExtError: Integer); |
function StripBaseDir(const s: string): string; |
end; |
58,11 → 60,10 |
implementation |
uses |
ExtractorPassword, ExtractorError, Functions, SFXAutoRun, ExtractorComment, |
BrowseFolder; |
ExtractorPassword, ExtractorError, Functions, SFXAutoRun, ExtractorComment; |
const |
EvPasswordTries = 15; |
MaxTries = 15; |
{$R *.dfm} |
144,33 → 145,23 |
procedure TMainForm.ExtractZipHere(AZipfile: string); |
var |
uz: TZipMaster19; |
l: TStringList; |
s: string; |
ec: Integer; |
ar: TExecuteSFXAutoRunResult; |
GeneralBaseDir: string; |
ok: boolean; |
const |
C_Explorer_Open_Param = '"%s"'; |
C_Explorer_Select_Param = '/n,/select,"%s"'; |
EXPLORER_EXE = 'explorer'; |
resourcestring |
Lng_Aborted = 'Der laufende Prozess wurde abgebrochen. Das extrahierten Dateien sind somit unvollständig.'; |
Lng_Zip_Error = 'ZIP-Master Fehler "%s" (%d)'; |
Lng_AutoRunFailed = 'SFX-AutoRun fehlgeschlagen. Die entpackten Inhalte werden nun angezeigt.'; |
Lng_Unknown_Error = 'Unbekannter Fehler: Dateien sind nicht aufzufinden!'; |
Lng_SelectDir = 'Bitte wählen Sie ein Verzeichnis zum Extrahieren aus. Es wird maximal 1 Datei bzw. Ordner erstellt!'; |
Lng_WriteProtected = 'Das Verzeichnis ist nicht schreibbar! Bitte wählen Sie ein Anderes.'; |
begin |
AZipfile := ExpandUNCFileName(AZipfile); |
RenamingOldPrefix := ''; |
RenamingNewPrefix := ''; |
if Assigned(uz) then uz.Free; // uz ist global, damit AbortDLL aufgerufen werden kann |
uz := TZipMaster19.Create(nil); |
try |
ExtractionInProcess := true; |
{$IFNDEF USE_DZIP_UNPACK} |
uz.DLLDirectory := GetTempDirectory + DelZipDLL_Name; |
{$ENDIF} |
184,59 → 175,19 |
uz.ExtrOptions := [ExtrDirNames, ExtrOverWrite, ExtrFreshen, ExtrUpdate, |
ExtrForceDirs, ExtrNTFS]; |
uz.OnExtractOverwrite := EvConfirmOverwrite; |
uz.OnProgress := EvProgress; |
uz.OnTick := EvTick; |
uz.OnCheckTerminate := EvCheckTerminate; |
uz.OnPasswordError := EvPasswordEvent; |
uz.PasswordReqCount := EvPasswordTries; |
uz.OnSkipped := EvSkipEvent; |
uz.OnSetExtName := EvExtFNChange; |
// Find out base dirtory |
GeneralBaseDir := ''; |
if zb.ExtractionTarget = etExtractHere then |
if zb.ConflictBehavior <> cbAvoid then |
begin |
GeneralBaseDir := ExtractFilePath(AZipfile); // Default |
if not IsDirectoryWritable(GeneralBaseDir) or |
IsAtFlobbyDisk(GeneralBaseDir) then |
begin |
zb.ExtractionTarget := etDesktop; |
uz.OnExtractOverwrite := ConfirmOverwrite; |
end; |
end; |
uz.OnProgress := ArcProzess; |
uz.OnTick := ArcTick; |
uz.OnCheckTerminate := ArcCheckTerminate; |
uz.OnPasswordError := ArcPassword; |
uz.PasswordReqCount := MaxTries; |
// TODO: Mehr events? |
uz.OnSkipped := SkipEvent; |
uz.OnSetExtName := ArcExtFNChange; |
if zb.ExtractionTarget = etDesktop then |
begin |
GeneralBaseDir := GetSpecialFolderPath(CSIDL_DESKTOP); |
if not IsDirectoryWritable(GeneralBaseDir) or |
IsAtFlobbyDisk(GeneralBaseDir) then |
begin |
zb.ExtractionTarget := etAsk; |
end; |
end; |
if zb.ExtractionTarget = etAsk then |
begin |
repeat |
GeneralBaseDir := MySelectDirectory(Lng_SelectDir); |
if GeneralBaseDir = '' then Exit; |
ok := IsDirectoryWritable(GeneralBaseDir); |
if not ok then |
begin |
MessageDlg(Lng_WriteProtected, mtWarning, [mbOk], 0); |
end; |
until ok; |
end; |
GeneralBaseDir := IncludeTrailingPathDelimiter(GeneralBaseDir); |
// Semantic scanning of ZIP to determinate the final extraction directory |
l := TStringList.Create; |
try |
// Count the root objects (files OR dirs) in the ZIP |
251,25 → 202,23 |
else if l.Count = 1 then |
begin |
// 1 Object = Extract it right here! |
BaseDir := GeneralBaseDir; |
s := BaseDir + l.Strings[0]; |
RenamingOldPrefix := l.Strings[0]; // = StripBaseDir(S); |
s := ExtractFilePath(AZipfile) + l.Strings[0]; |
BaseDir := ExtractFilePath(AZipfile); |
RenamingOldPrefix := StripBaseDir(S); |
if zb.ConflictBehavior = cbAvoid then |
begin |
s := SearchNextFreeName(s, LooksLikeDir(s)); |
s := SearchNextFreeName(s); |
end; |
RenamingNewPrefix := StripBaseDir(s); |
// TODO: helloworld.exe schlägt fehl! |
RenamingNewPrefix := StripBaseDir(S); // We need to change the name! |
end |
else |
begin |
// 2+ Objects = Extract them in a separate folder |
s := GeneralBaseDir + ExtractFileNameWithoutExt(AZipfile) + PathDelim; |
s := ChangeFileExt(AZipfile, ''); |
if zb.ConflictBehavior = cbAvoid then |
begin |
s := SearchNextFreeName(s, true); |
s := SearchNextFreeName(s); |
MkDir(s); |
end |
else |
280,7 → 229,7 |
end; |
BaseDir := IncludeTrailingPathDelimiter(BaseDir); |
uz.ExtrBaseDir := BaseDir; |
uz.ExtrBaseDir := BaseDir; // TODO: andere ordner erlauben |
// Pre-Extract-Dialog |
309,7 → 258,6 |
if ErrorForm.ErrorsAvailable then |
begin |
Hide; |
ErrorForm.ShowModal; |
end; |
337,9 → 285,8 |
if DirectoryExists(s) then |
begin |
// If it is a folder, open it |
ShellExecute(0, 'open', EXPLORER_EXE, |
PChar(Format(C_Explorer_Open_Param, [s])), '', SW_NORMAL); |
ShellExecute(0, 'open', 'explorer', |
PChar('"'+s+'"'), '', SW_NORMAL); |
end |
else if FileExists(s) then |
begin |
349,27 → 296,23 |
// Im Moment wird bei einem BESTEHENDEN Fenster |
// die Selektion nicht durchgeführt. |
ShellExecute(0, 'open', EXPLORER_EXE, |
PChar(Format(C_Explorer_Select_Param, [s])), '', SW_NORMAL); |
ShellExecute(0, 'open', 'explorer', |
PChar('/n,/select,"'+s+'"'), '', SW_NORMAL); |
end |
else |
begin |
if not AbortUnzip then |
begin |
MessageDlg(Lng_Unknown_Error, mtError, [mbOk], 0); |
end; |
end; |
end; |
finally |
l.Free; |
end; |
finally |
uz.Free; |
ExtractionInProcess := false; |
end; |
end; |
procedure TMainForm.EvProgress(Sender: TObject; details: TZMProgressDetails); |
procedure TMainForm.ArcProzess(Sender: TObject; details: TZMProgressDetails); |
begin |
CurrentFileLabel.Caption := details.ItemName; |
382,26 → 325,27 |
Application.ProcessMessages; |
end; |
procedure TMainForm.EvExtFNChange(Sender: TObject; |
procedure TMainForm.ArcExtFNChange(Sender: TObject; |
var FileName: TZMString; const BaseDir: TZMString; |
var IsChanged: Boolean); |
begin |
if RenamingOldPrefix = RenamingNewPrefix then Exit; |
if RenamingOldPrefix = RenamingOldPrefix then Exit; |
FileName := RenamingNewPrefix + Copy(FileName, 1+Length(RenamingOldPrefix), Length(FileName)-Length(RenamingOldPrefix)); |
IsChanged := true; |
end; |
procedure TMainForm.EvTick(Sender: TObject); |
procedure TMainForm.ArcTick(Sender: TObject); |
begin |
Application.ProcessMessages; |
end; |
procedure TMainForm.EvCheckTerminate(Sender: TObject; var abort: Boolean); |
procedure TMainForm.ArcCheckTerminate(Sender: TObject; var abort: Boolean); |
begin |
abort := AbortUnzip; |
end; |
procedure TMainForm.EvConfirmOverwrite(Sender: TObject; const ForFile: TZMString; |
procedure TMainForm.ConfirmOverwrite(Sender: TObject; const ForFile: TZMString; |
IsOlder: Boolean; var DoOverwrite: Boolean; DirIndex: Integer); |
resourcestring |
Lng_Overwrite = 'Bestehende Datei "%s" überschreiben?'; |
428,31 → 372,27 |
Exit; |
end; |
if CachedOverwriteDecision = odUndefined then |
if OverwriteDecision = odUndefined then |
begin |
res := MessageDlg(Format(Lng_Overwrite, [ForFile]), mtConfirmation, [mbYes, mbNo, mbYesToAll, mbNoToAll], 0); |
DoOverwrite := (res = mrYes) or (res = mrYesToAll); |
if res = mrNoToAll then CachedOverwriteDecision := odOverwriteNothing; |
if res = mrYesToAll then CachedOverwriteDecision := odOverwriteAll; |
if res = mrNoToAll then OverwriteDecision := odOverwriteNothing; |
if res = mrYesToAll then OverwriteDecision := odOverwriteAll; |
end |
else |
begin |
DoOverwrite := CachedOverwriteDecision = odOverwriteAll; |
DoOverwrite := OverwriteDecision = odOverwriteAll; |
end; |
end |
else if zb.ConflictBehavior = cbAvoid then |
begin |
// Nothing to do |
end; |
end; |
procedure TMainForm.EvPasswordEvent(Sender: TObject; IsZipAction: Boolean; |
procedure TMainForm.ArcPassword(Sender: TObject; IsZipAction: Boolean; |
var NewPassword: String; const ForFile: TZMString; var RepeatCount: Longword; |
var Action: TMsgDlgBtn); |
var |
repc: integer; |
begin |
repc := EvPasswordTries - RepeatCount + 1; |
repc := MaxTries - RepeatCount + 1; |
// Eine Passworteingabe wurde abgebrochen. Frage nicht mehr nach. |
if StopAskingPassword then Exit; |
474,7 → 414,7 |
end; |
end; |
if PasswordDlg.ShowModal(StripBaseDir(ForFile), repc, EvPasswordTries) = mrOk then |
if PasswordDlg.ShowModal(StripBaseDir(ForFile), repc, MaxTries) = mrOk then |
begin |
NewPassword := PasswordDlg.Password.Text; |
if NewPassword = '' then NewPassword := ' '; // Neue Eingabe erzwingen. |
491,34 → 431,19 |
resourcestring |
Lng_AbortExtract = 'Extrahieren abbrechen?'; |
begin |
if not ExtractionInProcess then |
begin |
Close; |
Exit; |
end; |
if MessageDlg(Lng_AbortExtract, mtConfirmation, mbYesNoCancel, 0) = mrYes then |
begin |
CancelBtn.Enabled := false; |
uz.AbortDLL; |
AbortUnzip := true; |
// Close wird durch den Timer durchgeführt |
Exit; |
end; |
end; |
procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean); |
begin |
if not ExtractionInProcess then |
begin |
CanClose := true; |
Exit; |
end; |
if not AbortUnzip then |
begin |
CancelBtn.Click; |
CanClose := false; |
CancelBtn.Click; |
end; |
end; |
526,6 → 451,9 |
resourcestring |
Lng_Extracting = 'Extrahiere Dateien. Bitte warten...'; |
begin |
{$IFDEF DEBUG_MODE} |
Caption := Caption + ' (Debug)'; |
{$ENDIF} |
WaitLabel.Caption := Lng_Extracting; |
WaitLabel.Left := progressBar.Width div 2 - WaitLabel.Width div 2; |
CurrentFileLabel.Caption := ''; |
572,10 → 500,6 |
{$ENDIF} |
procedure TMainForm.AutoTimerTimer(Sender: TObject); |
resourcestring |
Lng_NakedSFX = 'Das selbstentpackende Archiv (SFX) beschädigt oder ungültig. Wenn Sie diese Datei aus dem Internet bezogen haben, laden Sie sie bitte erneut herunter.'; |
Lng_FileNotFound = 'Die durch Parameter angegebene Datei "%s" kann nicht gefunden werden!'; |
Lng_TooManyArguments = 'Zu viele Argumente!'; |
begin |
AutoTimer.Enabled := false; |
584,21 → 508,7 |
{$ENDIF} |
try |
if IsExtractable(ParamStr(0)) then |
begin |
ExtractZipHere(ParamStr(0)); |
end |
else |
begin |
// Der Extractor ist "nackt" oder das SFX beschädigt |
if ParamCount = 0 then |
begin |
MessageDlg(Lng_NakedSFX, mtError, [mbOk], 0); |
end |
else if ParamCount = 1 then |
begin |
// In diesem Zustand erlauben wir, fremde SFX zu entpacken (auch für Debugging-Zwecke) |
{$IFDEF DEBUG_MODE} |
if FileExists(ParamStr(1)) then |
begin |
ExtractZipHere(ParamStr(1)); |
605,16 → 515,15 |
end |
else |
begin |
MessageDlg(Lng_FileNotFound, mtError, [mbOk], 0); |
{$ENDIF} |
ExtractZipHere(ParamStr(0)); |
{$IFDEF DEBUG_MODE} |
end; |
end |
else if ParamCount = 2 then |
begin |
// Future: Mehr als nur 1 Parameter erlauben? |
MessageDlg(Lng_TooManyArguments, mtError, [mbOk], 0); |
end; |
end; |
{$ENDIF} |
finally |
AbortUnzip := true; // Damit es zu keiner Abfrage kommt |
Close; |
end; |
end; |
626,7 → 535,7 |
result := Copy(s, Length(BaseDir)+1, Length(s)-Length(BaseDir)); |
end; |
procedure TMainForm.EvSkipEvent(Sender: TObject; const ForFile: TZMString; |
procedure TMainForm.SkipEvent(Sender: TObject; const ForFile: TZMString; |
SkipType: TZMSkipTypes; var ExtError: Integer); |
resourcestring |
Lng_PasswordWrong = 'Das Passwort wurde zu oft falsch eingegeben. Die Datei "%s" wird nicht extrahiert.'; |
636,7 → 545,7 |
MessageDlg(Format(Lng_PasswordWrong, [ForFile]), mtError, [mbOk], 0); |
LastTriedPassword := ''; |
end; |
ErrorForm.NewError(ForFile, SkipType); |
ErrorForm.NewError(StripBaseDir(ForFile)); |
end; |
end. |
/Extractor.res |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/Extractor.cfg |
---|
37,7 → 37,6 |
-O"c:\programme\borland\bds\4.0\lib\Debug;c:\programme\borland\bds\4.0\Lib\Debug\Indy10;zmstr1900102" |
-I"c:\programme\borland\bds\4.0\lib\Debug;c:\programme\borland\bds\4.0\Lib\Debug\Indy10;zmstr1900102" |
-R"c:\programme\borland\bds\4.0\lib\Debug;c:\programme\borland\bds\4.0\Lib\Debug\Indy10;zmstr1900102" |
-w-UNIT_PLATFORM |
-w-UNSAFE_TYPE |
-w-UNSAFE_CODE |
-w-UNSAFE_CAST |
/Icons/Software used.txt |
---|
File deleted |
/Icons/RarSFX.ico |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Deleted: svn:mime-type |
-application/octet-stream |
\ No newline at end of property |
/Icons/RarSFX Source/RarSFX.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Deleted: svn:mime-type |
-application/octet-stream |
\ No newline at end of property |
/Icons/RarSFX Source/RarSFX.psd |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Deleted: svn:mime-type |
-application/octet-stream |
\ No newline at end of property |
/Icons/RarSFX Source/Source.txt |
---|
File deleted |
/Readme.txt |
---|
0,0 → 1,87 |
VIATHINKSOFT AUTOSFX |
==================== |
Benefits |
-------- |
* Compatible with WinRAR and other software (Stub is small enough) |
* Compatible with Linux' UnZip (No Warnings!) |
* Compatible with AuthentiCode |
* Compatible with Windows 7 |
* Compatible with Windows 95 |
Current overhead |
---------------- |
458 KB (Delphi 2006) |
Structure of a ViaThinkSoft AutoSFX Archive |
------------------------------------------- |
1. Extractor [UPX'ed] |
includes DelZip190.dll (B4) as Resource |
2. ZIP (Offset adjusted) |
File comment includes "ViaThinkSoft AutoSFX Archive" |
3. Optional: Authenticode Certificate |
Process |
------- |
1. Extract DelZip DLL into TempDir |
2. Extract contents directly |
3. Open the extracted data and/or execute special AutoRun.inf (see below) |
4. Delete the DLL from TempDir |
Behavior |
-------- |
ZIP has 1 file |
=> Extract in the same directory as the SFX |
Is it a directory? |
=> Open the new directory in Windows Explorer |
is it a file? |
=> Open Windows Explorer and select the new file. |
ZIP has 2+ files |
=> Create a directory with the name of the SFX and extract into it |
=> Open the new created directory in Windows Explorer |
Semantic archive comment |
------------------------ |
The extractor looks into the file comment to determinate the behavior |
while unzipping. YOU can influence the behavior when creating your |
ZIP files. |
Following switches are possible: |
C_ASFX_CB_OVR = 'AutoSFX Conflict Behavior: Overwrite all'; |
C_ASFX_CB_NEW = 'AutoSFX Conflict Behavior: Overwrite older'; |
C_ASFX_CB_ASK = 'AutoSFX Conflict Behavior: Ask'; |
C_ASFX_CB_AVO = 'AutoSFX Conflict Behavior: Avoid'; |
C_ASFX_CP_BEF = 'AutoSFX Comment Presentation: Before extracting'; |
C_ASFX_CP_AFT = 'AutoSFX Comment Presentation: After extracting'; |
C_ASFX_CP_NON = 'AutoSFX Comment Presentation: None'; |
C_ASFX_FC_THS = 'AutoSFX Extraction Target: Extract here'; |
C_ASFX_FC_DSK = 'AutoSFX Extraction Target: Extract to Desktop'; |
C_ASFX_FC_ASK = 'AutoSFX Extraction Target: Choose directory'; |
Special AutoRun.inf |
------------------- |
[AutoSFX] |
Operation=open ; Part of ShellExecute. Usually 'open' or 'runass' (e.g. for admin privilegies) |
FileName=AutoRun.exe ; The filename to be executed |
Parameters= ; Optional parameters |
Directory= ; Optional Working directory |
ShowCmd= ; (See MSDN Reference) Usually WS_NORMAL or WS_HIDE |
OpenUnzippedContent=true ; After we have opened the application, should we still show the extracted data in Windows Explorer? (Default behavior if not AutoRun is set) |
More information about the first 5 values: |
http://msdn.microsoft.com/en-us/library/bb762153(VS.85).aspx |
// It is forbidden that the AutoRun calls its own creator (the SFX again). |
(C) 2010 ViaThinkSoft |
/zmstr1900102/Demos/Demo7/ImageStream.identcache |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/zmstr1900102/Demos/Demo7/ImageStream.bdsproj.local |
---|
0,0 → 1,2 |
<?xml version="1.0" encoding="utf-8"?> |
<BorlandProject/> |
/zmstr1900102/Demos/Demo7/Unit1.dcu |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/MakeSFX.exe |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/MakeSFX.dpr |
---|
10,7 → 10,6 |
Windows, |
Classes, |
ZipMstr19, |
Dialogs, |
Functions in 'Functions.pas', |
SFXBehavior in 'SFXBehavior.pas'; |
20,12 → 19,14 |
ZIP_EXE = 'Tools\zip.exe'; |
RemoveSignature_EXE = 'Tools\RemoveSignature.exe'; |
procedure DoMakeSFX(AFilename: string); |
var |
Dst: string; |
Src, Dst: string; |
i: integer; |
s1, s2: TFileStream; |
x: TZipMaster19; |
resourcestring |
ImportantFileNotFound = 'Error: Important file "%s" not found!'; |
LngErrorWhileCopy = 'Error: Could not copy "%s" to "%s".'; |
LngErrorWhileExecuting = 'Error while executing "%s".'; |
SourceFileNotFound = 'Source file "%s" not found.'; |
37,20 → 38,46 |
Lng_ModifyZIPComment = 'Modify ZIP Comment...'; |
Lng_SignSfx = 'Sign the SFX...'; |
Lng_Finished = 'Finished! :-)'; |
Lng_Title = 'ViaThinkSoft AutoSFX'; |
Lng_Usage1 = 'Usage:'; |
Lng_Usage2 = 'MakeSFX [File1.zip [File2.zip...]]'; |
{$R *.res} |
begin |
if not FileExists(AFilename) then |
WriteLn(Lng_Title); |
WriteLn(''); |
WriteLn(Lng_Usage1); |
WriteLn(Lng_Usage2); |
WriteLn(''); |
if not FileExists(ExtractFilePath(ParamStr(0)) + Extractor_EXE) then |
begin |
WriteLn(Format(SourceFileNotFound, [AFilename])); |
WriteLn(Format(ImportantFileNotFound, [Extractor_EXE])); |
{$IFDEF DELAY_ON_ERROR} |
Sleep(2000); |
{$ENDIF} |
ExitCode := 1; |
ExitCode := 2; |
Exit; |
end; |
Dst := ChangeFileExt(AFilename, '.exe'); |
for i := 1 to ParamCount do |
begin |
Src := ParamStr(i); |
WriteLn(Format(Lng_In+#9+'%s', [AFilename])); |
if not FileExists(Src) then |
begin |
WriteLn(Format(SourceFileNotFound, [Src])); |
{$IFDEF DELAY_ON_ERROR} |
Sleep(2000); |
{$ENDIF} |
ExitCode := 1; |
Continue; |
end; |
Dst := ChangeFileExt(Src, '.exe'); |
WriteLn(Format(Lng_In+#9+'%s', [Src])); |
WriteLn(Format(Lng_Out+#9+'%s', [Dst])); |
WriteLn(''); |
61,7 → 88,7 |
Sleep(2000); |
{$ENDIF} |
ExitCode := 1; |
Exit; |
Continue; |
end; |
// Remove the signature of Extractor first (otherwise signing will fail later) |
77,7 → 104,7 |
Sleep(2000); |
{$ENDIF} |
ExitCode := 1; |
Exit; |
Continue; |
{$ENDIF} |
end; |
87,7 → 114,7 |
try |
s1.Seek(0, soEnd); |
s2 := TFileStream.Create(AFilename, fmOpenRead or fmShareDenyWrite); |
s2 := TFileStream.Create(Src, fmOpenRead or fmShareDenyWrite); |
try |
s1.CopyFrom(s2, s2.Size); |
finally |
107,7 → 134,7 |
Sleep(2000); |
{$ENDIF} |
ExitCode := 1; |
Exit; |
Continue; |
end; |
WriteLn(#9 + Lng_ModifyZIPComment); |
150,7 → 177,7 |
Sleep(2000); |
{$ENDIF} |
ExitCode := 1; |
Exit; |
Continue; |
{$ENDIF} |
end; |
158,59 → 185,5 |
WriteLn(''); |
end; |
{$R *.res} |
var |
i: integer; |
od: TOpenDialog; |
resourcestring |
Lng_Title = 'ViaThinkSoft AutoSFX'; |
Lng_Usage1 = 'Usage:'; |
Lng_Usage2 = 'MakeSFX [File1.zip [File2.zip...]]'; |
ImportantFileNotFound = 'Error: Important file "%s" not found!'; |
begin |
WriteLn(Lng_Title); |
WriteLn(''); |
WriteLn(Lng_Usage1); |
WriteLn(Lng_Usage2); |
WriteLn(''); |
if not FileExists(ExtractFilePath(ParamStr(0)) + Extractor_EXE) then |
begin |
WriteLn(Format(ImportantFileNotFound, [Extractor_EXE])); |
{$IFDEF DELAY_ON_ERROR} |
Sleep(2000); |
{$ENDIF} |
ExitCode := 2; |
Exit; |
end; |
if ParamCount = 0 then |
begin |
od := TOpenDialog.Create(nil); |
try |
od.DefaultExt := '.zip'; |
od.Filter := 'ZIP-Archiv (*.zip)|*.zip|Alle Dateien (*.*)|*.*'; |
od.Options := [ofAllowMultiSelect, ofFileMustExist, ofHideReadOnly, |
ofPathMustExist, ofEnableSizing]; |
if od.Execute then |
begin |
for i := 0 to od.Files.Count - 1 do |
begin |
DoMakeSFX(od.Files.Strings[i]); |
end; |
end; |
finally |
od.Free; |
end; |
end |
else |
begin |
for i := 1 to ParamCount do |
begin |
DoMakeSFX(ParamStr(i)); |
end; |
end; |
// TODO: Es gibt bei Win2000 außerhalb des debuggers eine AV... |
end. |
/td.txt |
---|
0,0 → 1,15 |
Delphi 6: Projekteinstellungen prüfen. Debugging bei Extractor aus |
Versioninfo für alle Projekte |
MakeSFX.ico auch in 16x16 (ref: cdfview.dll) |
BUG: |
- W95 issue |
- Ungültige Resourcendatei... |
Sicherheitslücke |
- Der AutoRun kann eine unendliche Rekursion der Entpacker starten! |
Wie kann man alle Variationen feststellen? |
??? |
- Ist es möglich, dass erst Pwd-Dialog und dann Overwrite-Dialog kommt? |
=> Overwrite dialog soll nicht kommen bei "StopAskingPassword" + Verschlüsselt |
/ExtractorMain.dfm |
---|
67,7 → 67,6 |
Font.Style = [] |
ParentFont = False |
TabOrder = 1 |
TabStop = False |
OnClick = CancelBtnClick |
end |
object itemBar: TProgressBar |
79,6 → 78,7 |
TabOrder = 2 |
end |
object AutoTimer: TTimer |
Interval = 100 |
OnTimer = AutoTimerTimer |
Left = 320 |
Top = 8 |
/Functions.pas |
---|
3,8 → 3,7 |
interface |
uses |
Forms, Windows, Classes, SysUtils, ShellAPI, |
ZipMstr19, ZmUtils19, ShlObj, ActiveX; |
Windows, Classes, SysUtils, ShellAPI; |
type |
TLineBreak = (lbWindows, lbLinux, lbMac); |
16,11 → 15,7 |
function GetTempDirectory: String; |
function NormalizeLineBreaks(s: string; mode: TLineBreak): string; |
function ExtractFileNameWithoutExt(const fil: string): string; |
function SearchNextFreeName(s: string; wantDir: boolean): string; |
function GetSpecialFolderPath(const Folder: integer): string; |
function IsExtractable(AFilename: string): boolean; |
function IsDirectoryWritable(const Dir: String): Boolean; |
function IsAtFlobbyDisk(AFileOrDir: string): boolean; |
function SearchNextFreeName(s: string): string; |
implementation |
155,7 → 150,7 |
result := Copy(ExtractFileName(fil), 1, Length(ExtractFileName(fil))-Length(ExtractFileExt(fil))); |
end; |
function SearchNextFreeName(s: string; wantDir: boolean): string; |
function SearchNextFreeName(s: string): string; |
var |
i: integer; |
begin |
162,87 → 157,27 |
if not FileExists(s) and not DirectoryExists(s) then |
begin |
result := s; |
if wantDir then result := IncludeTrailingPathDelimiter(result); |
Exit; |
end; |
i := 2; |
if wantDir then |
if FileExists(s) then |
begin |
s := ExcludeTrailingPathDelimiter(s); |
repeat |
result := Format('%s (%d)', [s, i]); |
result := Format('%s (%d)%s', [ExtractFileNameWithoutExt(s), i, ExtractFileExt(s)]); |
inc(i); |
until not DirectoryExists(result) and not FileExists(result); |
result := IncludeTrailingPathDelimiter(result); |
until not DirectoryExists(result); |
end |
else |
else if DirectoryExists(s) then |
begin |
s := ExcludeTrailingPathDelimiter(s); |
repeat |
result := Format('%s (%d)%s', [ExtractFilePath(s)+ExtractFileNameWithoutExt(s), i, ExtractFileExt(s)]); |
result := Format('%s (%d)', [s, i]); |
inc(i); |
until not DirectoryExists(result) and not FileExists(result); |
until not DirectoryExists(result); // Todo: Legt man sich hier nun auf einen ordnernamen fest??? |
result := IncludeTrailingPathDelimiter(result); |
end; |
end; |
// GetSpecialFolderPath |
// Ref: http://www.wer-weiss-was.de/theme159/article1058561.html |
function GetSpecialFolderPath(const Folder: integer): string; |
var |
PIDL: PItemIDList; |
Path: array[0..MAX_PATH] of char; |
Malloc: IMalloc; |
begin |
Path := ''; |
if Succeeded((SHGetSpecialFolderLocation(0, Folder, PIDL))) then |
if (SHGetPathFromIDList(PIDL, Path)) then |
if Succeeded(ShGetMalloc(Malloc)) then |
begin |
Malloc.Free(PIDL); |
Malloc := nil; |
end; |
Result := Path; |
end; |
function IsExtractable(AFilename: string): boolean; |
var |
q: integer; |
uz: TZipMaster19; |
begin |
// TODO: Ist die Funktion gut? Fraglich, ob EOC64 ein Teil von EOC ist. |
uz := TZipMaster19.Create(nil); |
try |
q := uz.QueryZip(AFilename); |
result := true; |
if (q and zqbHasLocal) <> zqbHasLocal then result := false; |
if (q and zqbHasCentral) <> zqbHasCentral then result := false; |
if ((q and zqbHasEOC) <> zqbHasEOC) and |
((q and zqbHasEOC64) <> zqbHasEOC64) then result := false; |
finally |
uz.Free; |
end; |
end; |
// Ref: http://www.delphiarea.com/articles/how-to-find-if-a-directory-is-writable/ |
function IsDirectoryWritable(const Dir: String): Boolean; |
var |
TempFile: array[0..MAX_PATH] of Char; |
begin |
if GetTempFileName(PChar(Dir), 'DA', 0, TempFile) <> 0 then |
Result := Windows.DeleteFile(TempFile) |
else |
Result := False; |
end; |
function IsAtFlobbyDisk(AFileOrDir: string): boolean; |
var |
s: string; |
begin |
s := ExtractFileDrive(AFileOrDir); |
s := UpperCase(s); |
result := (s = 'A:') or (s = 'B:'); |
end; |
end. |
/Extractor.exe |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/Extractor.dpr |
---|
14,8 → 14,7 |
ExtractorComment in 'ExtractorComment.pas' {CommentForm}, |
Functions in 'Functions.pas', |
SFXAutoRun in 'SFXAutoRun.pas', |
SFXBehavior in 'SFXBehavior.pas', |
BrowseFolder in 'BrowseFolder.pas'; |
SFXBehavior in 'SFXBehavior.pas'; |
{$R *.res} |
/MakeSFX.bdsproj |
---|
130,7 → 130,7 |
<Directories Name="UsePackages">False</Directories> |
</Directories> |
<Parameters> |
<Parameters Name="RunParams"></Parameters> |
<Parameters Name="RunParams">helloworld.zip</Parameters> |
<Parameters Name="HostApplication"></Parameters> |
<Parameters Name="Launcher"></Parameters> |
<Parameters Name="UseLauncher">False</Parameters> |
/Tools/RC.Exe |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Deleted: svn:mime-type |
-application/octet-stream |
\ No newline at end of property |
/Tools/RcDll.Dll |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Deleted: svn:mime-type |
-application/octet-stream |
\ No newline at end of property |
/Tools/RemoveSignature.exe |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/Tools/Sources.txt |
---|
6,6 → 6,3 |
upx.exe |
http://upx.sourceforge.net/ |
rc.dll, rcdll.dll |
Windows Server 2003 SP1 SDK |
/ExtractorPassword.dfm |
---|
7,11 → 7,7 |
ClientHeight = 140 |
ClientWidth = 290 |
Color = clBtnFace |
Font.Charset = ANSI_CHARSET |
Font.Color = clWindowText |
Font.Height = -11 |
Font.Name = 'MS Sans Serif' |
Font.Style = [] |
ParentFont = True |
OldCreateOrder = True |
Position = poMainFormCenter |
OnShow = FormShow |
20,7 → 16,7 |
object PwEnterLabel: TLabel |
Left = 8 |
Top = 56 |
Width = 117 |
Width = 120 |
Height = 13 |
Caption = 'Bitte Passwort eingeben.' |
end |
27,7 → 23,7 |
object FileLabel: TLabel |
Left = 8 |
Top = 6 |
Width = 28 |
Width = 29 |
Height = 13 |
Caption = 'Datei:' |
end |
/ExtractorComment.dfm |
---|
5,10 → 5,10 |
ClientHeight = 499 |
ClientWidth = 521 |
Color = clBtnFace |
Font.Charset = ANSI_CHARSET |
Font.Charset = DEFAULT_CHARSET |
Font.Color = clWindowText |
Font.Height = -11 |
Font.Name = 'MS Sans Serif' |
Font.Name = 'Tahoma' |
Font.Style = [] |
OldCreateOrder = False |
Position = poMainFormCenter |
38,13 → 38,7 |
Height = 25 |
Caption = 'OK' |
Default = True |
Font.Charset = ANSI_CHARSET |
Font.Color = clWindowText |
Font.Height = -11 |
Font.Name = 'MS Sans Serif' |
Font.Style = [] |
ModalResult = 1 |
ParentFont = False |
TabOrder = 0 |
end |
object CancelBtn: TButton |
54,13 → 48,7 |
Height = 25 |
Cancel = True |
Caption = 'Abbrechen' |
Font.Charset = ANSI_CHARSET |
Font.Color = clWindowText |
Font.Height = -11 |
Font.Name = 'MS Sans Serif' |
Font.Style = [] |
ModalResult = 2 |
ParentFont = False |
TabOrder = 1 |
end |
end |
/ExtractorError.pas |
---|
2,11 → 2,10 |
interface |
// TODO: Richtige Ordnerliste mit Icons anzeigen? |
// TODO: Dialog sizeable |
uses |
Forms, StdCtrls, ExtCtrls, Controls, Graphics, Classes, Dialogs, |
ZipMstr19, SysUtils; |
Forms, StdCtrls, ExtCtrls, Controls, Graphics, Classes; |
type |
TErrorForm = class(TForm) |
14,13 → 13,9 |
ErrorImg: TImage; |
ErrorLabel: TLabel; |
OKBtn: TButton; |
SaveBtn: TButton; |
SaveDialog: TSaveDialog; |
procedure FormResize(Sender: TObject); |
procedure SaveBtnClick(Sender: TObject); |
public |
function ErrorsAvailable: boolean; |
procedure NewError(Filename: string; SkipType: TZMSkipTypes); |
procedure NewError(Filename: string); |
end; |
var |
30,58 → 25,15 |
{$R *.dfm} |
function SkipTypeToStr(SkipType: TZMSkipTypes): string; |
begin |
case SkipType of |
stOnFreshen: result := 'stOnFreshen'; |
stNoOverwrite: result := 'stNoOverwrite'; |
stFileExists: result := 'stFileExists'; |
stBadPassword: result := 'stBadPassword'; |
stBadName: result := 'stBadName'; |
stCompressionUnknown: result := 'stCompressionUnknown'; |
stUnknownZipHost: result := 'stUnknownZipHost'; |
stZipFileFormatWrong: result := 'stZipFileFormatWrong'; |
stGeneralExtractError: result := 'stGeneralExtractError'; |
stUser: result := 'stUser'; |
stCannotDo: result := 'stCannotDo'; |
stNotFound: result := 'stNotFound'; |
stNoShare: result := 'stNoShare'; |
stNoAccess: result := 'stNoAccess'; |
stNoOpen: result := 'stNoOpen'; |
stDupName: result := 'stDupName'; |
stReadError: result := 'stReadError'; |
stSizeChange: result := 'stSizeChange'; |
end; |
end; |
function TErrorForm.ErrorsAvailable: boolean; |
begin |
result := ErrorList.Items.Count > 0; |
end; |
procedure TErrorForm.FormResize(Sender: TObject); |
procedure TErrorForm.NewError(Filename: string); |
begin |
ErrorList.Width := ClientWidth - ErrorList.Left - ErrorImg.Left; |
ErrorList.Height := ClientHeight - ErrorList.Top - (2 * ErrorImg.Left + OkBtn.Height); |
OkBtn.Top := ErrorList.Top + ErrorList.Height + ErrorImg.Left; |
OkBtn.Left := ErrorList.Left + ErrorList.Width - OkBtn.Width; |
SaveBtn.Top := OkBtn.Top; |
end; |
procedure TErrorForm.NewError(Filename: string; SkipType: TZMSkipTypes); |
resourcestring |
Lng_Err_Entry = '%s (Grund: %s)'; |
begin |
// In future: Also add reason into list? |
ErrorList.Items.Add(Format(Lng_Err_Entry, [Filename, SkipTypeToStr(SkipType)])); |
ErrorList.Items.Add(Filename); |
end; |
procedure TErrorForm.SaveBtnClick(Sender: TObject); |
begin |
if SaveDialog.Execute then |
begin |
ErrorList.Items.SaveToFile(SaveDialog.FileName); |
end; |
end; |
end. |
/_PreBuild.bat |
---|
1,10 → 1,4 |
@echo off |
rem brcc32 is not compatible with Vista icons |
Tools\rc Extractor.rc |
Tools\rc MakeSFX.rc |
cd zmstr1900102\DLL\ResDLL-Maker\ |
call MakeResDll.bat |
pause. |
/Extractor.bdsproj |
---|
53,7 → 53,7 |
<Compiler Name="SymbolPlatform">True</Compiler> |
<Compiler Name="SymbolExperimental">True</Compiler> |
<Compiler Name="UnitLibrary">True</Compiler> |
<Compiler Name="UnitPlatform">False</Compiler> |
<Compiler Name="UnitPlatform">True</Compiler> |
<Compiler Name="UnitDeprecated">True</Compiler> |
<Compiler Name="UnitExperimental">True</Compiler> |
<Compiler Name="HResultCompat">True</Compiler> |
130,7 → 130,7 |
<Directories Name="UsePackages">False</Directories> |
</Directories> |
<Parameters> |
<Parameters Name="RunParams">"Tests\128-Bit Enc.zip"</Parameters> |
<Parameters Name="RunParams">helloworld.exe</Parameters> |
<Parameters Name="HostApplication"></Parameters> |
<Parameters Name="Launcher"></Parameters> |
<Parameters Name="UseLauncher">False</Parameters> |