Subversion Repositories checksum-tools

Rev

Rev 17 | 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;
25 daniel-mar 103
    exit;
6 daniel-mar 104
  end;
105
 
106
  Memo1.Clear;
107
  Memo2.Clear;
108
  Memo3.Clear;
109
  Memo4.Clear;
110
 
111
  if SameText(ExtractFileExt(FileName), '.sfv') then
112
    csman := TCheckSumFileSFV.Create(FileName)
113
  else if SameText(ExtractFileExt(FileName), '.md5') then
114
    csman := TCheckSumFileMD5.Create(FileName)
115
  else
116
    Exception.Create('Unknown file extension. Only supporting MD5 and SFV.');
117
 
118
  slSFV := TStringList.Create;
119
  existingFiles := TStringList.Create;
120
  try
121
    // Read SFV/MD5 file
122
    csman.ToStringList(slSFV);
123
 
124
    // List existing files
7 daniel-mar 125
    IsFound := FindFirst(ADirectory + '*', faAnyFile xor faDirectory, SR) = 0;
6 daniel-mar 126
    while IsFound do
127
    begin
128
      if (SR.Name <> '.') and (SR.Name <> '..') then
129
      begin
8 daniel-mar 130
        existingFiles.Add(SR.Name);
6 daniel-mar 131
      end;
132
      IsFound := FindNext(SR) = 0;
133
    end;
134
    FindClose(SR);
135
 
136
    // Checksum mismatch or missing files
137
    for i := 0 to slSFV.Count-1 do
138
    begin
139
      TestFilename := IncludeTrailingPathDelimiter(ADirectory) + slSFV.Strings[i];
140
      SollChecksum := TCheckSum(slSFV.Objects[i]).checksum;
141
      if not FileExists(TestFilename) then
142
      begin
143
        Memo3.Lines.Add(csman.MergeLine(slSFV.Strings[i], SollChecksum));
144
      end
145
      else
146
      begin
8 daniel-mar 147
        IstChecksum  := csman.SingleFileChecksum(TestFilename);
6 daniel-mar 148
        if SameText(SollChecksum, IstChecksum) then
149
        begin
150
          Memo1.Lines.Add(csman.MergeLine(slSFV.Strings[i], SollChecksum));
151
        end
152
        else
153
        begin
154
          Memo2.Lines.Add('; [CURRENT FILE CHECKSUM] ' + csman.MergeLine(slSFV.Strings[i], IstChecksum));
155
          Memo2.Lines.Add(csman.MergeLine(slSFV.Strings[i], SollChecksum));
156
        end;
157
 
8 daniel-mar 158
        {$IFDEF MSWINDOWS}
159
        existingFiles.CaseSensitive := false;
160
        {$ELSE}
161
        existingFiles.CaseSensitive := true;
162
        {$ENDIF}
163
        j := existingFiles.IndexOf(slSFV.Strings[i]);
6 daniel-mar 164
        if j >= 0 then existingFiles.Delete(j);
165
      end;
166
    end;
167
 
168
    // Check non-indexed files
169
    for i := 0 to existingFiles.Count-1 do
170
    begin
171
      TestFileName := existingFiles[i];
172
      if not SameText(ExtractFileExt(TestFileName), '.sfv') and
173
         not SameText(ExtractFileExt(TestFileName), '.md5') and
174
         not SameText(TestFileName, 'Thumbs.db') then
175
      begin
10 daniel-mar 176
        IstChecksum  := csman.SingleFileChecksum(IncludeTrailingPathDelimiter(ADirectory) + TestFilename);
6 daniel-mar 177
        Memo4.Lines.Add(csman.MergeLine(TestFileName, IstChecksum));
178
      end;
179
    end;
7 daniel-mar 180
 
181
    if (Memo2.Text = '') and (Memo3.Text = '') and (Memo4.Text = '') then
182
      Color := clMoneyGreen
183
    else if (Memo2.Text <> '') then
184
      Color := clRed
185
    else
186
      Color := clYellow;
8 daniel-mar 187
 
188
    Memo1.SelStart := 0;
189
    Memo1.SelLength := 0;
190
    Memo2.SelStart := 0;
191
    Memo2.SelLength := 0;
192
    Memo3.SelStart := 0;
193
    Memo3.SelLength := 0;
194
    Memo4.SelStart := 0;
195
    Memo4.SelLength := 0;
196
 
197
    if Memo2.Text <> '' then Memo2.SetFocus
198
    else if Memo3.Text <> '' then Memo3.SetFocus
199
    else if Memo4.Text <> '' then Memo4.SetFocus
200
    else Memo1.SetFocus;
6 daniel-mar 201
  finally
202
    FreeAndNil(slSFV);
203
    FreeAndNil(existingFiles);
204
    FreeAndNil(csman);
205
  end;
206
end;
207
 
208
function TForm3.ParamChecksumFile: string;
209
begin
210
  if FChecksumFile <> '' then
211
  begin
212
    result := FChecksumFile;
213
  end
214
  else
215
  begin
216
    result := ParamStr(1);
217
    if result = '' then
218
    begin
219
      if not OpenDialog1.Execute then
220
      begin
221
        Close;
222
        Abort;
223
      end;
224
      result := OpenDialog1.FileName;
225
    end;
226
    FChecksumFile := result;
227
  end;
228
end;
229
 
230
procedure TForm3.SaveSFV;
231
var
232
  hFile: THandle;
233
  i: Integer;
8 daniel-mar 234
  slOut: TStringList;
6 daniel-mar 235
begin
236
  MyAssignFile(hFile, ParamChecksumFile);
8 daniel-mar 237
  try
238
    MyRewrite(hFile); // clear File
239
 
240
    slOut := TStringList.Create;
241
    try
242
      // Fill slOut with the Memo contents
243
      for i := 0 to memo1.Lines.Count-1 do
244
      begin
245
        slOut.Add(Memo1.Lines[i]);
246
      end;
247
      for i := 0 to memo2.Lines.Count-1 do
248
      begin
249
        slOut.Add(Memo2.Lines[i]);
250
      end;
251
      for i := 0 to memo3.Lines.Count-1 do
252
      begin
253
        slOut.Add(Memo3.Lines[i]);
254
      end;
255
      for i := 0 to memo4.Lines.Count-1 do
256
      begin
257
        slOut.Add(Memo4.Lines[i]);
258
      end;
259
 
260
      // Sort
261
      slOut.Sort;
262
 
263
      // Write to SFV/MD5 file
264
      for i := 0 to slOut.Count-1 do
265
      begin
266
        if Trim(slOut[i]) <> '' then
267
          MyWriteLn(hFile, AnsiString(utf8encode(slOut[i])));
268
      end;
269
    finally
270
      FreeAndNil(slOut);
271
    end;
272
  finally
273
    MyCloseFile(hFile);
6 daniel-mar 274
  end;
275
end;
276
 
8 daniel-mar 277
procedure TForm3.Timer1Timer(Sender: TObject);
278
begin
279
  Timer1.Enabled := false;
280
  LoadSFV;
281
end;
282
 
6 daniel-mar 283
end.