Subversion Repositories checksum-tools

Rev

Rev 17 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. unit Unit3;
  2.  
  3. interface
  4.  
  5. uses
  6.   Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  7.   Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls;
  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;
  21.     Timer1: TTimer;
  22.     procedure Button1Click(Sender: TObject);
  23.     procedure FormShow(Sender: TObject);
  24.     procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  25.     procedure Timer1Timer(Sender: TObject);
  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.  
  50. procedure TForm3.FormKeyDown(Sender: TObject; var Key: Word;
  51.   Shift: TShiftState);
  52. begin
  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;
  69. end;
  70.  
  71. procedure TForm3.FormShow(Sender: TObject);
  72. begin
  73.   Caption := ParamChecksumFile;
  74.   Timer1.Enabled := true;
  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
  92.   Color := clGray;
  93.   Refresh;
  94.  
  95.   FileName := ParamChecksumFile;
  96.   if Copy(FileName, 2, 1) = ':' then FileName := '\\?\' + FileName; // To allow long filenames
  97.   ADirectory := ExtractFilePath(FileName);
  98.  
  99.   if not FileExists(FileName) then
  100.   begin
  101.     ShowMessageFmt('File not found: %s', [FileName]);
  102.     Close;
  103.     exit;
  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
  125.     IsFound := FindFirst(ADirectory + '*', faAnyFile xor faDirectory, SR) = 0;
  126.     while IsFound do
  127.     begin
  128.       if (SR.Name <> '.') and (SR.Name <> '..') then
  129.       begin
  130.         existingFiles.Add(SR.Name);
  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
  147.         IstChecksum  := csman.SingleFileChecksum(TestFilename);
  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.  
  158.         {$IFDEF MSWINDOWS}
  159.         existingFiles.CaseSensitive := false;
  160.         {$ELSE}
  161.         existingFiles.CaseSensitive := true;
  162.         {$ENDIF}
  163.         j := existingFiles.IndexOf(slSFV.Strings[i]);
  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
  176.         IstChecksum  := csman.SingleFileChecksum(IncludeTrailingPathDelimiter(ADirectory) + TestFilename);
  177.         Memo4.Lines.Add(csman.MergeLine(TestFileName, IstChecksum));
  178.       end;
  179.     end;
  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;
  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;
  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;
  234.   slOut: TStringList;
  235. begin
  236.   MyAssignFile(hFile, ParamChecksumFile);
  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);
  274.   end;
  275. end;
  276.  
  277. procedure TForm3.Timer1Timer(Sender: TObject);
  278. begin
  279.   Timer1.Enabled := false;
  280.   LoadSFV;
  281. end;
  282.  
  283. end.
  284.