Subversion Repositories checksum-tools

Rev

Rev 10 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
6 daniel-mar 1
unit Unit3;
2
 
3
interface
4
 
5
uses
6
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
8 daniel-mar 7
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls;
6 daniel-mar 8
 
9
type
10
  TForm3 = class(TForm)
11
    Memo1: TMemo;
12
    Label1: TLabel;
13
    Memo2: TMemo;
14
    Label2: TLabel;
15
    Memo3: TMemo;
16
    Label3: TLabel;
17
    Memo4: TMemo;
18
    Label4: TLabel;
19
    Button1: TButton;
20
    OpenDialog1: TOpenDialog;
8 daniel-mar 21
    Timer1: TTimer;
6 daniel-mar 22
    procedure Button1Click(Sender: TObject);
23
    procedure FormShow(Sender: TObject);
8 daniel-mar 24
    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
25
    procedure Timer1Timer(Sender: TObject);
6 daniel-mar 26
  private
27
    FChecksumFile: string;
28
  public
29
    function ParamChecksumFile: string;
30
    procedure LoadSFV;
31
    procedure SaveSFV;
32
  end;
33
 
34
var
35
  Form3: TForm3;
36
 
37
implementation
38
 
39
{$R *.dfm}
40
 
41
uses
42
  Common, SFV, MD5, LongFilenameOperations;
43
 
44
procedure TForm3.Button1Click(Sender: TObject);
45
begin
46
  SaveSFV;
47
  LoadSFV;
48
end;
49
 
8 daniel-mar 50
procedure TForm3.FormKeyDown(Sender: TObject; var Key: Word;
51
  Shift: TShiftState);
7 daniel-mar 52
begin
8 daniel-mar 53
  if (Shift = []) and (Key = VK_F6) then
54
  begin
55
    Key := 0;
56
    SaveSFV;
57
    LoadSFV;
58
  end
59
  else if (Shift = []) and (Key = VK_ESCAPE) then
60
  begin
61
    Key := 0;
62
    Close;
63
  end
64
  else if (Shift = []) and (Key = VK_F5) then
65
  begin
66
    Key := 0;
67
    LoadSFV;
68
  end;
7 daniel-mar 69
end;
70
 
6 daniel-mar 71
procedure TForm3.FormShow(Sender: TObject);
72
begin
73
  Caption := ParamChecksumFile;
8 daniel-mar 74
  Timer1.Enabled := true;
6 daniel-mar 75
end;
76
 
77
procedure TForm3.LoadSFV;
78
var
79
  FileName: string;
80
  ADirectory: string;
81
  slSFV: TStringList;
82
  SR: TSearchRec;
83
  IsFound: Boolean;
84
  i: Integer;
85
  TestFilename: string;
86
  SollChecksum: string;
87
  IstChecksum: string;
88
  existingFiles: TStringList;
89
  j: Integer;
90
  csman: TCheckSumFile;
91
begin
8 daniel-mar 92
  Color := clGray;
93
  Refresh;
94
 
6 daniel-mar 95
  FileName := ParamChecksumFile;
17 daniel-mar 96
  if Copy(FileName, 2, 1) = ':' then FileName := '\\?\' + FileName; // To allow long filenames
6 daniel-mar 97
  ADirectory := ExtractFilePath(FileName);
98
 
99
  if not FileExists(FileName) then
100
  begin
101
    ShowMessageFmt('File not found: %s', [FileName]);
102
    Close;
103
  end;
104
 
105
  Memo1.Clear;
106
  Memo2.Clear;
107
  Memo3.Clear;
108
  Memo4.Clear;
109
 
110
  if SameText(ExtractFileExt(FileName), '.sfv') then
111
    csman := TCheckSumFileSFV.Create(FileName)
112
  else if SameText(ExtractFileExt(FileName), '.md5') then
113
    csman := TCheckSumFileMD5.Create(FileName)
114
  else
115
    Exception.Create('Unknown file extension. Only supporting MD5 and SFV.');
116
 
117
  slSFV := TStringList.Create;
118
  existingFiles := TStringList.Create;
119
  try
120
    // Read SFV/MD5 file
121
    csman.ToStringList(slSFV);
122
 
123
    // List existing files
7 daniel-mar 124
    IsFound := FindFirst(ADirectory + '*', faAnyFile xor faDirectory, SR) = 0;
6 daniel-mar 125
    while IsFound do
126
    begin
127
      if (SR.Name <> '.') and (SR.Name <> '..') then
128
      begin
8 daniel-mar 129
        existingFiles.Add(SR.Name);
6 daniel-mar 130
      end;
131
      IsFound := FindNext(SR) = 0;
132
    end;
133
    FindClose(SR);
134
 
135
    // Checksum mismatch or missing files
136
    for i := 0 to slSFV.Count-1 do
137
    begin
138
      TestFilename := IncludeTrailingPathDelimiter(ADirectory) + slSFV.Strings[i];
139
      SollChecksum := TCheckSum(slSFV.Objects[i]).checksum;
140
      if not FileExists(TestFilename) then
141
      begin
142
        Memo3.Lines.Add(csman.MergeLine(slSFV.Strings[i], SollChecksum));
143
      end
144
      else
145
      begin
8 daniel-mar 146
        IstChecksum  := csman.SingleFileChecksum(TestFilename);
6 daniel-mar 147
        if SameText(SollChecksum, IstChecksum) then
148
        begin
149
          Memo1.Lines.Add(csman.MergeLine(slSFV.Strings[i], SollChecksum));
150
        end
151
        else
152
        begin
153
          Memo2.Lines.Add('; [CURRENT FILE CHECKSUM] ' + csman.MergeLine(slSFV.Strings[i], IstChecksum));
154
          Memo2.Lines.Add(csman.MergeLine(slSFV.Strings[i], SollChecksum));
155
        end;
156
 
8 daniel-mar 157
        {$IFDEF MSWINDOWS}
158
        existingFiles.CaseSensitive := false;
159
        {$ELSE}
160
        existingFiles.CaseSensitive := true;
161
        {$ENDIF}
162
        j := existingFiles.IndexOf(slSFV.Strings[i]);
6 daniel-mar 163
        if j >= 0 then existingFiles.Delete(j);
164
      end;
165
    end;
166
 
167
    // Check non-indexed files
168
    for i := 0 to existingFiles.Count-1 do
169
    begin
170
      TestFileName := existingFiles[i];
171
      if not SameText(ExtractFileExt(TestFileName), '.sfv') and
172
         not SameText(ExtractFileExt(TestFileName), '.md5') and
173
         not SameText(TestFileName, 'Thumbs.db') then
174
      begin
10 daniel-mar 175
        IstChecksum  := csman.SingleFileChecksum(IncludeTrailingPathDelimiter(ADirectory) + TestFilename);
6 daniel-mar 176
        Memo4.Lines.Add(csman.MergeLine(TestFileName, IstChecksum));
177
      end;
178
    end;
7 daniel-mar 179
 
180
    if (Memo2.Text = '') and (Memo3.Text = '') and (Memo4.Text = '') then
181
      Color := clMoneyGreen
182
    else if (Memo2.Text <> '') then
183
      Color := clRed
184
    else
185
      Color := clYellow;
8 daniel-mar 186
 
187
    Memo1.SelStart := 0;
188
    Memo1.SelLength := 0;
189
    Memo2.SelStart := 0;
190
    Memo2.SelLength := 0;
191
    Memo3.SelStart := 0;
192
    Memo3.SelLength := 0;
193
    Memo4.SelStart := 0;
194
    Memo4.SelLength := 0;
195
 
196
    if Memo2.Text <> '' then Memo2.SetFocus
197
    else if Memo3.Text <> '' then Memo3.SetFocus
198
    else if Memo4.Text <> '' then Memo4.SetFocus
199
    else Memo1.SetFocus;
6 daniel-mar 200
  finally
201
    FreeAndNil(slSFV);
202
    FreeAndNil(existingFiles);
203
    FreeAndNil(csman);
204
  end;
205
end;
206
 
207
function TForm3.ParamChecksumFile: string;
208
begin
209
  if FChecksumFile <> '' then
210
  begin
211
    result := FChecksumFile;
212
  end
213
  else
214
  begin
215
    result := ParamStr(1);
216
    if result = '' then
217
    begin
218
      if not OpenDialog1.Execute then
219
      begin
220
        Close;
221
        Abort;
222
      end;
223
      result := OpenDialog1.FileName;
224
    end;
225
    FChecksumFile := result;
226
  end;
227
end;
228
 
229
procedure TForm3.SaveSFV;
230
var
231
  hFile: THandle;
232
  i: Integer;
8 daniel-mar 233
  slOut: TStringList;
6 daniel-mar 234
begin
235
  MyAssignFile(hFile, ParamChecksumFile);
8 daniel-mar 236
  try
237
    MyRewrite(hFile); // clear File
238
 
239
    slOut := TStringList.Create;
240
    try
241
      // Fill slOut with the Memo contents
242
      for i := 0 to memo1.Lines.Count-1 do
243
      begin
244
        slOut.Add(Memo1.Lines[i]);
245
      end;
246
      for i := 0 to memo2.Lines.Count-1 do
247
      begin
248
        slOut.Add(Memo2.Lines[i]);
249
      end;
250
      for i := 0 to memo3.Lines.Count-1 do
251
      begin
252
        slOut.Add(Memo3.Lines[i]);
253
      end;
254
      for i := 0 to memo4.Lines.Count-1 do
255
      begin
256
        slOut.Add(Memo4.Lines[i]);
257
      end;
258
 
259
      // Sort
260
      slOut.Sort;
261
 
262
      // Write to SFV/MD5 file
263
      for i := 0 to slOut.Count-1 do
264
      begin
265
        if Trim(slOut[i]) <> '' then
266
          MyWriteLn(hFile, AnsiString(utf8encode(slOut[i])));
267
      end;
268
    finally
269
      FreeAndNil(slOut);
270
    end;
271
  finally
272
    MyCloseFile(hFile);
6 daniel-mar 273
  end;
274
end;
275
 
8 daniel-mar 276
procedure TForm3.Timer1Timer(Sender: TObject);
277
begin
278
  Timer1.Enabled := false;
279
  LoadSFV;
280
end;
281
 
6 daniel-mar 282
end.