Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | daniel-mar | 1 | {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | * |
||
3 | * Unit Name : uBase64Codec |
||
4 | * Author : Daniel Wischnewski |
||
5 | * Copyright : Copyright © 2001-2003 by gate(n)etwork GmbH. All Rights Reserved. |
||
6 | * Creator : Daniel Wischnewski |
||
7 | * Contact : Daniel Wischnewski (e-mail: delphi3000(at)wischnewski.tv); |
||
8 | * |
||
9 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} |
||
10 | |||
11 | // * * * License * * * |
||
12 | // |
||
13 | // The contents of this file are used with permission, subject to the Mozilla |
||
14 | // Public License Version 1.1 (the "License"); you may not use this file except |
||
15 | // in compliance with the License. You may obtain a copy of the License at |
||
16 | // |
||
17 | // http://www.mozilla.org/MPL/MPL-1.1.html |
||
18 | // |
||
19 | // Software distributed under the License is distributed on an "AS IS" basis, |
||
20 | // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for |
||
21 | // the specific language governing rights and limitations under the License. |
||
22 | // |
||
23 | |||
24 | // * * * My Wish * * * |
||
25 | // |
||
26 | // If you come to use this unit for your work, I would like to know about it. |
||
27 | // Drop me an e-mail and let me know how it worked out for you. If you wish, you |
||
28 | // can send me a copy of your work. No obligations! |
||
29 | // My e-mail address: delphi3000(at)wischnewski.tv |
||
30 | // |
||
31 | |||
32 | // * * * History * * * |
||
33 | // |
||
34 | // Version 1.0 (Oct-10 2002) |
||
35 | // first published on Delphi-PRAXiS (www.delphipraxis.net) |
||
36 | // |
||
37 | // Version 1.1 (May-13 2003) |
||
38 | // introduced a compiler switch (SpeedDecode) to switch between a faster |
||
39 | // decoding variant (prior version) and a litte less fast, but secure variant |
||
40 | // to work around bad formatted data (decoding only!) |
||
41 | // |
||
42 | // Version 1.2 (Juni-09 2004) |
||
43 | // included compiler switch {$0+}. In Delphi 6 and 7 projects using this code |
||
44 | // with compiler optimizations turned off will raise an access violation |
||
45 | // {$O+} will ensure that this unit runs with compiler optimizations. |
||
46 | // This option does *not* influence other parts of the project including this |
||
47 | // unit. |
||
48 | // Thanks to Ralf Manschewski for pointing out this problem. |
||
49 | // |
||
50 | |||
51 | unit Base64; |
||
52 | |||
53 | {$O+} |
||
54 | |||
55 | interface |
||
56 | |||
57 | // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
||
58 | // !! THE COMPILER SWITCH MAY BE USED TO ADJUST THE BEHAVIOR !! |
||
59 | // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
||
60 | |||
61 | // enable "SpeedDecode" |
||
62 | // the switch to gain speed while decoding the message, however, the codec |
||
63 | // will raise different exceptions/access violations or invalid output if |
||
64 | // the incoming data is invalid or missized. |
||
65 | |||
66 | // disable "SpeedDecode" |
||
67 | // the switch to enable a data check, that will scan the data to decode to |
||
68 | // be valid. This method is to be used if you cannot guarantee to validity |
||
69 | // of the data to be decoded. |
||
70 | |||
71 | {.DEFINE SpeedDecode} |
||
72 | |||
73 | {$IFNDEF SpeedDecode} |
||
74 | {$DEFINE ValidityCheck} |
||
75 | {$ENDIF} |
||
76 | |||
77 | |||
78 | uses SysUtils; |
||
79 | |||
80 | // codiert einen String in die zugehörige Base64-Darstellung |
||
81 | function Base64Encode(const InText: AnsiString): AnsiString; overload; |
||
82 | // decodiert die Base64-Darstellung eines Strings in den zugehörigen String |
||
83 | function Base64Decode(const InText: AnsiString): AnsiString; overload; |
||
84 | |||
85 | // bestimmt die Größe der Base64-Darstellung |
||
86 | function CalcEncodedSize(InSize: Cardinal): Cardinal; |
||
87 | // bestimmt die Größe der binären Darstellung |
||
88 | function CalcDecodedSize(const InBuffer; InSize: Cardinal): Cardinal; |
||
89 | |||
90 | // codiert einen Buffer in die zugehörige Base64-Darstellung |
||
91 | procedure Base64Encode(const InBuffer; InSize: Cardinal; var OutBuffer); overload; register; |
||
92 | // decodiert die Base64-Darstellung in einen Buffer |
||
93 | {$IFDEF SpeedDecode} |
||
94 | procedure Base64Decode(const InBuffer; InSize: Cardinal; var OutBuffer); overload; register; |
||
95 | {$ENDIF} |
||
96 | {$IFDEF ValidityCheck} |
||
97 | function Base64Decode(const InBuffer; InSize: Cardinal; var OutBuffer): Boolean; overload; register; |
||
98 | {$ENDIF} |
||
99 | |||
100 | // codiert einen String in die zugehörige Base64-Darstellung |
||
101 | procedure Base64Encode(const InText: PAnsiChar; var OutText: PAnsiChar); overload; |
||
102 | // decodiert die Base64-Darstellung eines Strings in den zugehörigen String |
||
103 | procedure Base64Decode(const InText: PAnsiChar; var OutText: PAnsiChar); overload; |
||
104 | |||
105 | // codiert einen String in die zugehörige Base64-Darstellung |
||
106 | procedure Base64Encode(const InText: AnsiString; var OutText: AnsiString); overload; |
||
107 | // decodiert die Base64-Darstellung eines Strings in den zugehörigen String |
||
108 | procedure Base64Decode(const InText: AnsiString; var OutText: AnsiString); overload; |
||
109 | |||
110 | |||
111 | implementation |
||
112 | |||
113 | const |
||
114 | cBase64Codec: array[0..63] of AnsiChar = |
||
115 | 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; |
||
116 | Base64Filler = '='; |
||
117 | |||
118 | function Base64Encode(const InText: string): string; overload; |
||
119 | begin |
||
120 | Base64Encode(InText, Result); |
||
121 | end; |
||
122 | |||
123 | function Base64Decode(const InText: string): string; overload; |
||
124 | begin |
||
125 | Base64Decode(InText, Result); |
||
126 | end; |
||
127 | |||
128 | function CalcEncodedSize(InSize: Cardinal): Cardinal; |
||
129 | begin |
||
130 | // no buffers passed along, calculate outbuffer size needed |
||
131 | Result := (InSize div 3) shl 2; |
||
132 | if ((InSize mod 3) > 0) |
||
133 | then Inc(Result, 4); |
||
134 | end; |
||
135 | |||
136 | function CalcDecodedSize(const InBuffer; InSize: Cardinal): Cardinal; |
||
137 | type |
||
138 | BA = array of Byte; |
||
139 | begin |
||
140 | Result := 0; |
||
141 | if InSize = 0 then |
||
142 | Exit; |
||
143 | if InSize mod 4 <> 0 then |
||
144 | Exit; |
||
145 | Result := InSize div 4 * 3; |
||
146 | if (BA(InBuffer)[InSize - 2] = Ord(Base64Filler)) |
||
147 | then Dec(Result, 2) |
||
148 | else if BA(InBuffer)[InSize - 1] = Ord(Base64Filler) |
||
149 | then Dec(Result); |
||
150 | end; |
||
151 | |||
152 | procedure Base64Encode(const InBuffer; InSize: Cardinal; var OutBuffer |
||
153 | ); register; |
||
154 | var |
||
155 | ByThrees, LeftOver: Cardinal; |
||
156 | // reset in- and outbytes positions |
||
157 | asm |
||
158 | // load addresses for source and destination |
||
159 | // PBYTE(InBuffer); |
||
160 | mov ESI, [EAX] |
||
161 | // PBYTE(OutBuffer); |
||
162 | mov EDI, [ECX] |
||
163 | // ByThrees := InSize div 3; |
||
164 | // LeftOver := InSize mod 3; |
||
165 | // load InSize (stored in EBX) |
||
166 | mov EAX, EBX |
||
167 | // load 3 |
||
168 | mov ECX, $03 |
||
169 | // clear upper 32 bits |
||
170 | xor EDX, EDX |
||
171 | // divide by ECX |
||
172 | div ECX |
||
173 | // save result |
||
174 | mov ByThrees, EAX |
||
175 | // save remainder |
||
176 | mov LeftOver, EDX |
||
177 | // load addresses |
||
178 | lea ECX, cBase64Codec[0] |
||
179 | // while I < ByThrees do |
||
180 | // begin |
||
181 | xor EAX, EAX |
||
182 | xor EBX, EBX |
||
183 | xor EDX, EDX |
||
184 | cmp ByThrees, 0 |
||
185 | jz @@LeftOver |
||
186 | @@LoopStart: |
||
187 | // load the first two bytes of the source triplet |
||
188 | LODSW |
||
189 | // write Bits 0..5 to destination |
||
190 | mov BL, AL |
||
191 | shr BL, 2 |
||
192 | mov DL, BYTE PTR [ECX + EBX] |
||
193 | // save the Bits 12..15 for later use [1] |
||
194 | mov BH, AH |
||
195 | and BH, $0F |
||
196 | // save Bits 6..11 |
||
197 | rol AX, 4 |
||
198 | and AX, $3F |
||
199 | mov DH, BYTE PTR [ECX + EAX] |
||
200 | mov AX, DX |
||
201 | // store the first two bytes of the destination quadruple |
||
202 | STOSW |
||
203 | // laod last byte (Bits 16..23) of the source triplet |
||
204 | LODSB |
||
205 | // extend bits 12..15 [1] with Bits 16..17 and save them |
||
206 | mov BL, AL |
||
207 | shr BX, 6 |
||
208 | mov DL, BYTE PTR [ECX + EBX] |
||
209 | // save bits 18..23 |
||
210 | and AL, $3F |
||
211 | xor AH, AH |
||
212 | mov DH, BYTE PTR [ECX + EAX] |
||
213 | mov AX, DX |
||
214 | // store the last two bytes of the destination quadruple |
||
215 | STOSW |
||
216 | dec ByThrees |
||
217 | jnz @@LoopStart |
||
218 | @@LeftOver: |
||
219 | // there are up to two more bytes to encode |
||
220 | cmp LeftOver, 0 |
||
221 | jz @@Done |
||
222 | // clear result |
||
223 | xor EAX, EAX |
||
224 | xor EBX, EBX |
||
225 | xor EDX, EDX |
||
226 | // get left over 1 |
||
227 | LODSB |
||
228 | // load the first six bits |
||
229 | shl AX, 6 |
||
230 | mov BL, AH |
||
231 | // save them |
||
232 | mov DL, BYTE PTR [ECX + EBX] |
||
233 | // another byte ? |
||
234 | dec LeftOver |
||
235 | jz @@SaveOne |
||
236 | // save remaining two bits |
||
237 | shl AX, 2 |
||
238 | and AH, $03 |
||
239 | // get left over 2 |
||
240 | LODSB |
||
241 | // load next 4 bits |
||
242 | shl AX, 4 |
||
243 | mov BL, AH |
||
244 | // save all 6 bits |
||
245 | mov DH, BYTE PTR [ECX + EBX] |
||
246 | shl EDX, 16 |
||
247 | // save last 4 bits |
||
248 | shr AL, 2 |
||
249 | mov BL, AL |
||
250 | // save them |
||
251 | mov DL, BYTE PTR [ECX + EBX] |
||
252 | // load base 64 'no more data flag' |
||
253 | mov DH, Base64Filler |
||
254 | jmp @@WriteLast4 |
||
255 | @@SaveOne: |
||
256 | // adjust the last two bits |
||
257 | shr AL, 2 |
||
258 | mov BL, AL |
||
259 | // save them |
||
260 | mov DH, BYTE PTR [ECX + EBX] |
||
261 | shl EDX, 16 |
||
262 | // load base 64 'no more data flags' |
||
263 | mov DH, Base64Filler |
||
264 | mov DL, Base64Filler |
||
265 | // ignore jump, as jump reference is next line ! |
||
266 | // jmp @@WriteLast4 |
||
267 | @@WriteLast4: |
||
268 | // load and adjust result |
||
269 | mov EAX, EDX |
||
270 | ror EAX, 16 |
||
271 | // save it to destination |
||
272 | STOSD |
||
273 | @@Done: |
||
274 | end; |
||
275 | |||
276 | {$IFDEF SpeedDecode} |
||
277 | procedure Base64Decode(const InBuffer; InSize: Cardinal; var OutBuffer); |
||
278 | overload; register; |
||
279 | {$ENDIF} |
||
280 | {$IFDEF ValidityCheck} |
||
281 | function Base64Decode(const InBuffer; InSize: Cardinal; var OutBuffer): |
||
282 | Boolean; overload; register; |
||
283 | {$ENDIF} |
||
284 | const |
||
285 | {$IFDEF SpeedDecode} |
||
286 | cBase64Codec: array[0..127] of Byte = |
||
287 | {$ENDIF} |
||
288 | {$IFDEF ValidityCheck} |
||
289 | cBase64Codec: array[0..255] of Byte = |
||
290 | {$ENDIF} |
||
291 | ( |
||
292 | $FF, $FF, $FF, $FF, $FF, {005>} $FF, $FF, $FF, $FF, $FF, // 000..009 |
||
293 | $FF, $FF, $FF, $FF, $FF, {015>} $FF, $FF, $FF, $FF, $FF, // 010..019 |
||
294 | $FF, $FF, $FF, $FF, $FF, {025>} $FF, $FF, $FF, $FF, $FF, // 020..029 |
||
295 | $FF, $FF, $FF, $FF, $FF, {035>} $FF, $FF, $FF, $FF, $FF, // 030..039 |
||
296 | $FF, $FF, $FF, $3E, $FF, {045>} $FF, $FF, $3F, $34, $35, // 040..049 |
||
297 | $36, $37, $38, $39, $3A, {055>} $3B, $3C, $3D, $FF, $FF, // 050..059 |
||
298 | $FF, $FF, $FF, $FF, $FF, {065>} $00, $01, $02, $03, $04, // 060..069 |
||
299 | $05, $06, $07, $08, $09, {075>} $0A, $0B, $0C, $0D, $0E, // 070..079 |
||
300 | $0F, $10, $11, $12, $13, {085>} $14, $15, $16, $17, $18, // 080..089 |
||
301 | $19, $FF, $FF, $FF, $FF, {095>} $FF, $FF, $1A, $1B, $1C, // 090..099 |
||
302 | $1D, $1E, $1F, $20, $21, {105>} $22, $23, $24, $25, $26, // 100..109 |
||
303 | $27, $28, $29, $2A, $2B, {115>} $2C, $2D, $2E, $2F, $30, // 110..119 |
||
304 | $31, $32, $33, $FF, $FF, {125>} $FF, $FF, $FF // 120..127 |
||
305 | |||
306 | {$IFDEF ValidityCheck} |
||
307 | {125>} , $FF, $FF, // 128..129 |
||
308 | $FF, $FF, $FF, $FF, $FF, {135>} $FF, $FF, $FF, $FF, $FF, // 130..139 |
||
309 | $FF, $FF, $FF, $FF, $FF, {145>} $FF, $FF, $FF, $FF, $FF, // 140..149 |
||
310 | $FF, $FF, $FF, $FF, $FF, {155>} $FF, $FF, $FF, $FF, $FF, // 150..159 |
||
311 | $FF, $FF, $FF, $FF, $FF, {165>} $FF, $FF, $FF, $FF, $FF, // 160..169 |
||
312 | $FF, $FF, $FF, $FF, $FF, {175>} $FF, $FF, $FF, $FF, $FF, // 170..179 |
||
313 | $FF, $FF, $FF, $FF, $FF, {185>} $FF, $FF, $FF, $FF, $FF, // 180..189 |
||
314 | $FF, $FF, $FF, $FF, $FF, {195>} $FF, $FF, $FF, $FF, $FF, // 190..199 |
||
315 | $FF, $FF, $FF, $FF, $FF, {205>} $FF, $FF, $FF, $FF, $FF, // 200..209 |
||
316 | $FF, $FF, $FF, $FF, $FF, {215>} $FF, $FF, $FF, $FF, $FF, // 210..219 |
||
317 | $FF, $FF, $FF, $FF, $FF, {225>} $FF, $FF, $FF, $FF, $FF, // 220..229 |
||
318 | $FF, $FF, $FF, $FF, $FF, {235>} $FF, $FF, $FF, $FF, $FF, // 230..239 |
||
319 | $FF, $FF, $FF, $FF, $FF, {245>} $FF, $FF, $FF, $FF, $FF, // 240..249 |
||
320 | $FF, $FF, $FF, $FF, $FF, {255>} $FF // 250..255 |
||
321 | {$ENDIF} |
||
322 | ); |
||
323 | asm |
||
324 | push EBX |
||
325 | mov ESI, [EAX] |
||
326 | mov EDI, [ECX] |
||
327 | {$IFDEF ValidityCheck} |
||
328 | mov EAX, InSize |
||
329 | and EAX, $03 |
||
330 | cmp EAX, $00 |
||
331 | jz @@DecodeStart |
||
332 | jmp @@ErrorDone |
||
333 | @@DecodeStart: |
||
334 | {$ENDIF} |
||
335 | mov EAX, InSize |
||
336 | shr EAX, 2 |
||
337 | jz @@Done |
||
338 | lea ECX, cBase64Codec[0] |
||
339 | xor EBX, EBX |
||
340 | dec EAX |
||
341 | jz @@LeftOver |
||
342 | push EBP |
||
343 | mov EBP, EAX |
||
344 | @@LoopStart: |
||
345 | // load four bytes into EAX |
||
346 | LODSD |
||
347 | // save them to EDX as AX is used to store results |
||
348 | mov EDX, EAX |
||
349 | // get bits 0..5 |
||
350 | mov BL, DL |
||
351 | // decode |
||
352 | mov AH, BYTE PTR [ECX + EBX] |
||
353 | {$IFDEF ValidityCheck} |
||
354 | // check valid code |
||
355 | cmp AH, $FF |
||
356 | jz @@ErrorDoneAndPopEBP |
||
357 | {$ENDIF} |
||
358 | // get bits 6..11 |
||
359 | mov BL, DH |
||
360 | // decode |
||
361 | mov AL, BYTE PTR [ECX + EBX] |
||
362 | {$IFDEF ValidityCheck} |
||
363 | // check valid code |
||
364 | cmp AL, $FF |
||
365 | jz @@ErrorDoneAndPopEBP |
||
366 | {$ENDIF} |
||
367 | // align last 6 bits |
||
368 | shl AL, 2 |
||
369 | // get first 8 bits |
||
370 | ror AX, 6 |
||
371 | // store first byte |
||
372 | STOSB |
||
373 | // align remaining 4 bits |
||
374 | shr AX, 12 |
||
375 | // get next two bytes from source quad |
||
376 | shr EDX, 16 |
||
377 | // load bits 12..17 |
||
378 | mov BL, DL |
||
379 | // decode |
||
380 | mov AH, BYTE PTR [ECX + EBX] |
||
381 | {$IFDEF ValidityCheck} |
||
382 | // check valid code |
||
383 | cmp AH, $FF |
||
384 | jz @@ErrorDoneAndPopEBP |
||
385 | {$ENDIF} |
||
386 | // align ... |
||
387 | shl AH, 2 |
||
388 | // ... and adjust |
||
389 | rol AX, 4 |
||
390 | // get last bits 18..23 |
||
391 | mov BL, DH |
||
392 | // decord |
||
393 | mov BL, BYTE PTR [ECX + EBX] |
||
394 | {$IFDEF ValidityCheck} |
||
395 | // check valid code |
||
396 | cmp BL, $FF |
||
397 | jz @@ErrorDoneAndPopEBP |
||
398 | {$ENDIF} |
||
399 | // enter in destination word |
||
400 | or AH, BL |
||
401 | // and store to destination |
||
402 | STOSW |
||
403 | // more coming ? |
||
404 | dec EBP |
||
405 | jnz @@LoopStart |
||
406 | pop EBP |
||
407 | // no |
||
408 | // last four bytes are handled separately, as special checking is needed |
||
409 | // on the last two bytes (may be end of data signals '=' or '==') |
||
410 | @@LeftOver: |
||
411 | // get the last four bytes |
||
412 | LODSD |
||
413 | // save them to EDX as AX is used to store results |
||
414 | mov EDX, EAX |
||
415 | // get bits 0..5 |
||
416 | mov BL, DL |
||
417 | // decode |
||
418 | mov AH, BYTE PTR [ECX + EBX] |
||
419 | {$IFDEF ValidityCheck} |
||
420 | // check valid code |
||
421 | cmp AH, $FF |
||
422 | jz @@ErrorDone |
||
423 | {$ENDIF} |
||
424 | // get bits 6..11 |
||
425 | mov BL, DH |
||
426 | // decode |
||
427 | mov AL, BYTE PTR [ECX + EBX] |
||
428 | {$IFDEF ValidityCheck} |
||
429 | // check valid code |
||
430 | cmp AL, $FF |
||
431 | jz @@ErrorDone |
||
432 | {$ENDIF} |
||
433 | // align last 6 bits |
||
434 | shl AL, 2 |
||
435 | // get first 8 bits |
||
436 | ror AX, 6 |
||
437 | // store first byte |
||
438 | STOSB |
||
439 | // get next two bytes from source quad |
||
440 | shr EDX, 16 |
||
441 | // check DL for "end of data signal" |
||
442 | cmp DL, Base64Filler |
||
443 | jz @@SuccessDone |
||
444 | // align remaining 4 bits |
||
445 | shr AX, 12 |
||
446 | // load bits 12..17 |
||
447 | mov BL, DL |
||
448 | // decode |
||
449 | mov AH, BYTE PTR [ECX + EBX] |
||
450 | {$IFDEF ValidityCheck} |
||
451 | // check valid code |
||
452 | cmp AH, $FF |
||
453 | jz @@ErrorDone |
||
454 | {$ENDIF} |
||
455 | // align ... |
||
456 | shl AH, 2 |
||
457 | // ... and adjust |
||
458 | rol AX, 4 |
||
459 | // store second byte |
||
460 | STOSB |
||
461 | // check DH for "end of data signal" |
||
462 | cmp DH, Base64Filler |
||
463 | jz @@SuccessDone |
||
464 | // get last bits 18..23 |
||
465 | mov BL, DH |
||
466 | // decord |
||
467 | mov BL, BYTE PTR [ECX + EBX] |
||
468 | {$IFDEF ValidityCheck} |
||
469 | // check valid code |
||
470 | cmp BL, $FF |
||
471 | jz @@ErrorDone |
||
472 | {$ENDIF} |
||
473 | // enter in destination word |
||
474 | or AH, BL |
||
475 | // AH - AL for saving last byte |
||
476 | mov AL, AH |
||
477 | // store third byte |
||
478 | STOSB |
||
479 | @@SuccessDone: |
||
480 | {$IFDEF ValidityCheck} |
||
481 | mov Result, $01 |
||
482 | jmp @@Done |
||
483 | @@ErrorDoneAndPopEBP: |
||
484 | pop EBP |
||
485 | @@ErrorDone: |
||
486 | mov Result, $00 |
||
487 | {$ENDIF} |
||
488 | @@Done: |
||
489 | pop EBX |
||
490 | end; |
||
491 | |||
492 | procedure Base64Encode(const InText: PAnsiChar; var OutText: PAnsiChar); |
||
493 | var |
||
494 | InSize, OutSize: Cardinal; |
||
495 | begin |
||
496 | // get size of source |
||
497 | InSize := Length(InText); |
||
498 | // calculate size for destination |
||
499 | OutSize := CalcEncodedSize(InSize); |
||
500 | // reserve memory |
||
501 | OutText := StrAlloc(Succ(OutSize)); |
||
502 | OutText[OutSize] := #0; |
||
503 | // encode ! |
||
504 | Base64Encode(InText, InSize, OutText); |
||
505 | end; |
||
506 | |||
507 | procedure Base64Encode(const InText: AnsiString; var OutText: AnsiString); |
||
508 | overload; |
||
509 | var |
||
510 | InSize, OutSize: Cardinal; |
||
511 | PIn, POut: Pointer; |
||
512 | begin |
||
513 | // get size of source |
||
514 | InSize := Length(InText); |
||
515 | // calculate size for destination |
||
516 | OutSize := CalcEncodedSize(InSize); |
||
517 | // prepare string length to fit result data |
||
518 | SetLength(OutText, OutSize); |
||
519 | PIn := @InText[1]; |
||
520 | POut := @OutText[1]; |
||
521 | // encode ! |
||
522 | Base64Encode(PIn, InSize, POut); |
||
523 | end; |
||
524 | |||
525 | procedure Base64Decode(const InText: PAnsiChar; var OutText: PAnsiChar); |
||
526 | overload; |
||
527 | var |
||
528 | InSize, OutSize: Cardinal; |
||
529 | begin |
||
530 | // get size of source |
||
531 | InSize := Length(InText); |
||
532 | // calculate size for destination |
||
533 | OutSize := CalcDecodedSize(InText, InSize); |
||
534 | // reserve memory |
||
535 | OutText := StrAlloc(Succ(OutSize)); |
||
536 | OutText[OutSize] := #0; |
||
537 | // encode ! |
||
538 | {$IFDEF SpeedDecode} |
||
539 | Base64Decode(InText, InSize, OutText); |
||
540 | {$ENDIF} |
||
541 | {$IFDEF ValidityCheck} |
||
542 | if not Base64Decode(InText, InSize, OutText) then |
||
543 | OutText[0] := #0; |
||
544 | {$ENDIF} |
||
545 | end; |
||
546 | |||
547 | procedure Base64Decode(const InText: AnsiString; var OutText: AnsiString); |
||
548 | overload; |
||
549 | var |
||
550 | InSize, OutSize: Cardinal; |
||
551 | PIn, POut: Pointer; |
||
552 | begin |
||
553 | // get size of source |
||
554 | InSize := Length(InText); |
||
555 | // calculate size for destination |
||
556 | PIn := @InText[1]; |
||
557 | OutSize := CalcDecodedSize(PIn, InSize); |
||
558 | // prepare string length to fit result data |
||
559 | SetLength(OutText, OutSize); |
||
560 | FillChar(OutText[1], OutSize, '.'); |
||
561 | POut := @OutText[1]; |
||
562 | // encode ! |
||
563 | {$IFDEF SpeedDecode} |
||
564 | Base64Decode(PIn, InSize, POut); |
||
565 | {$ENDIF} |
||
566 | {$IFDEF ValidityCheck} |
||
567 | if not Base64Decode(PIn, InSize, POut) then |
||
568 | SetLength(OutText, 0); |
||
569 | {$ENDIF} |
||
570 | end; |
||
571 | |||
572 | end. |