1 unit rfs_utils;
2 {
3  DESCRIPTION     :  Unit providing UI-neutral routines to be used in Raw File
4                     Split and Raw File Join
5 
6  REQUIREMENTS    :  FPC
7 
8  EXTERNAL DATA   :  ---
9 
10  MEMORY USAGE    :  ---
11 
12  DISPLAY MODE    :  ---
13 
14  REFERENCES      :  ---
15 
16  REMARK          :  ---
17 
18  Version  Date      Author      Modification
19  -------  --------  -------     ------------------------------------------
20  0.10     20060816  G.Tani      Initial version
21  0.11     20060917  G.Tani      removed *_VER; P_RELEASE constant in pea_utils
22                                 is used to keep track of release level;
23  0.12     20080704  G.Tani      Enabled utf8
24  0.13     20200508  G.Tani      Added SHA3_256, SHA3_512, BLAKE2S, BLAKE2B algorithms
25 
26 (C) Copyright 2006 Giorgio Tani giorgio.tani.software@gmail.com
27 The program is released under GNU LGPL http://www.gnu.org/licenses/lgpl.txt
28 
29     This library is free software; you can redistribute it and/or
30     modify it under the terms of the GNU Lesser General Public
31     License as published by the Free Software Foundation; either
32     version 3 of the License, or (at your option) any later version.
33 
34     This library is distributed in the hope that it will be useful,
35     but WITHOUT ANY WARRANTY; without even the implied warranty of
36     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
37     Lesser General Public License for more details.
38 
39     You should have received a copy of the GNU Lesser General Public
40     License along with this library; if not, write to the Free Software
41     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
42 }
43 
44 {$mode objfpc}{$H+}
45 {$INLINE ON}
46 
47 interface
48 
49 uses SysUtils;
50 
51 const
52 SUCCESS = 0;
53 INCOMPLETE_FUNCTION = 1;
54 UNKNOWN_VOLUME_CONTROL_ALGORITHM = 2;
55 NOT_RFS_HEADER = 3;
56 
57 {
58 generate RFS 4 byte .check file header
59 }
rfs_create_checkfile_hdrnull60 function rfs_create_checkfile_hdr ( volume_control_algorithm:ansistring;        //algorithm to error check each volume
61                                     var hdr_data:array of byte                  //buffer for header data
62                                     ):integer;
63 
64 {
65 read RFS 4 byte .check file header
66 }
rfs_parse_archive_headernull67 function rfs_parse_archive_header ( read_data:array of byte;                    //buffer containig the header matherial
68                                     var volume_algo:ansistring                  //control algorithm for volumes
willnull69                                     ):integer;                                  //note that the function will exit at all error condition (excluded INCOMPLETE_FUNCTION); in this way it will always be returned the code of the first error encountered
70 
71 {
72 decode volume control algorithm
73 }
decode_rfs_volume_control_algonull74 function decode_rfs_volume_control_algo ( volume_algo:ansistring;               //control algorithm
75                                           var authsize:byte                     //authentication tag size
76                                           ):integer;
77 
78 {
79 update volume name following RFS volume naming convention
80 }
81 procedure update_rfs_filename ( fname:ansistring;                               //name to update
82                                 i:integer;                                      //counter (updated externally)
83                                 var newname:ansistring);                        //updated name: input name + 3 digit human readable counter
84 
85 implementation
86 
rfs_create_checkfile_hdrnull87 function rfs_create_checkfile_hdr ( volume_control_algorithm:ansistring;        //algorithm to error check each volume
88                                     var hdr_data:array of byte                  //buffer for header data
89                                     ):integer;
90 begin
91 rfs_create_checkfile_hdr:=INCOMPLETE_FUNCTION; //generic error code: the subroutine is jet not completed (useful if the function somehow cannot complete)
92 hdr_data[0]:=114; //r
93 hdr_data[1]:=102; //f
94 hdr_data[2]:=115; //s
95 //byte 3: control model for each single volume, to allow identification of corrupted chunks (i.e. to request resending, or to not trust to try to open them)
96 if (upcase(volume_control_algorithm)='NOALGO') then hdr_data[3]:=$00
97 else
98 if (upcase(volume_control_algorithm)='ADLER32') then hdr_data[3]:=$01
99 else
100 if (upcase(volume_control_algorithm)='CRC32') then hdr_data[3]:=$02
101 else
102 if (upcase(volume_control_algorithm)='CRC64') then hdr_data[3]:=$03
103 else
104 if (upcase(volume_control_algorithm)='MD5') then hdr_data[3]:=$10
105 else
106 if (upcase(volume_control_algorithm)='RIPEMD160') then hdr_data[3]:=$11
107 else
108 if (upcase(volume_control_algorithm)='SHA1') then hdr_data[3]:=$12
109 else
110 if (upcase(volume_control_algorithm)='SHA256') then hdr_data[3]:=$13
111 else
112 if (upcase(volume_control_algorithm)='SHA512') then hdr_data[3]:=$14
113 else
114 if (upcase(volume_control_algorithm)='WHIRLPOOL') then hdr_data[3]:=$15
115 else
116 if (upcase(volume_control_algorithm)='SHA3_256') then hdr_data[3]:=$16
117 else
118 if (upcase(volume_control_algorithm)='SHA3_512') then hdr_data[3]:=$17
119 else
120 if (upcase(volume_control_algorithm)='BLAKE2S') then hdr_data[3]:=$18
121 else
122 if (upcase(volume_control_algorithm)='BLAKE2B') then hdr_data[3]:=$19
123 else rfs_create_checkfile_hdr:=UNKNOWN_VOLUME_CONTROL_ALGORITHM;
124 rfs_create_checkfile_hdr:=SUCCESS;
125 end;
126 
rfs_parse_archive_headernull127 function rfs_parse_archive_header ( read_data:array of byte;                    //buffer containig the header matherial
128                                     var volume_algo:ansistring                  //control algorithm for volumes
willnull129                                     ):integer;                                  //note that the function will exit at all error condition (excluded INCOMPLETE_FUNCTION); in this way it will always be returned the code of the first error encountered
130 begin
131 rfs_parse_archive_header:=INCOMPLETE_FUNCTION;
ifnull132 if ((read_data[0]=114) and (read_data[1]=102) and (read_data[2]=115)) then
133    begin
134    case read_data[3] of
135       0: volume_algo:='NOALGO'; //hex 00
136       1: volume_algo:='ADLER32'; //hex 01
137       2: volume_algo:='CRC32';  //hex 02
138       3: volume_algo:='CRC64';  //hex 03
139      16: volume_algo:='MD5'; //hex 10
140      17: volume_algo:='RIPEMD160'; //hex 11
141      18: volume_algo:='SHA1'; //hex 12
142      19: volume_algo:='SHA256'; //hex 13
143      20: volume_algo:='SHA512'; //hex 14
144      21: volume_algo:='WHIRLPOOL'; //hex 15
145      22: volume_algo:='SHA3_256'; //hex 16
146      23: volume_algo:='SHA3_512'; //hex 17
147      24: volume_algo:='BLAKE2S'; //hex 18
148      25: volume_algo:='BLAKE2B'; //hex 19
149       else
150          begin
151          rfs_parse_archive_header:=UNKNOWN_VOLUME_CONTROL_ALGORITHM;
152          exit;
153          end;
154       end;
155    end
156 else rfs_parse_archive_header:=NOT_RFS_HEADER;
thennull157 if rfs_parse_archive_header=INCOMPLETE_FUNCTION then rfs_parse_archive_header:=SUCCESS;
158 end;
159 
decode_rfs_volume_control_algonull160 function decode_rfs_volume_control_algo ( volume_algo:ansistring;               //control algorithm
161                                           var authsize:byte                     //authentication tag size
162                                           ):integer;
163 begin
164 decode_rfs_volume_control_algo:=INCOMPLETE_FUNCTION;
authsizenull165 authsize:=255;
166 if upcase(volume_algo)='NOALGO' then authsize:=0;
167 if upcase(volume_algo)='ADLER32' then authsize:=4;
168 if upcase(volume_algo)='CRC32' then authsize:=4;
169 if upcase(volume_algo)='CRC64' then authsize:=8;
170 if upcase(volume_algo)='MD5' then authsize:=16;
171 if upcase(volume_algo)='RIPEMD160' then authsize:=20;
172 if upcase(volume_algo)='SHA1' then authsize:=20;
173 if upcase(volume_algo)='SHA256' then authsize:=32;
174 if upcase(volume_algo)='SHA512' then authsize:=64;
175 if upcase(volume_algo)='WHIRLPOOL' then authsize:=64;
176 if upcase(volume_algo)='SHA3_256' then authsize:=32;
177 if upcase(volume_algo)='SHA3_512' then authsize:=64;
178 if upcase(volume_algo)='BLAKE2S' then authsize:=32;
179 if upcase(volume_algo)='BLAKE2B' then authsize:=64;
180 if authsize=255 then decode_rfs_volume_control_algo:=UNKNOWN_VOLUME_CONTROL_ALGORITHM;
thennull181 if decode_rfs_volume_control_algo=INCOMPLETE_FUNCTION then decode_rfs_volume_control_algo:=SUCCESS;
182 end;
183 
184 procedure update_rfs_filename ( fname:ansistring;                               //name to update
185                                 i:integer;                                      //counter (updated externally)
186                                 var newname:ansistring);                        //updated name: input name + 3 digit human readable counter
187 begin
188 if i <10 then newname:=fname+'.00'+inttostr(i)
189 else
190    if i<100 then newname:=fname+'.0'+inttostr(i)
191    else newname:=fname+'.'+inttostr(i);
192 end;
193 
194 end.
195