Version:
~ [ 10.0 ] ~
** Warning: Cannot open xref database.
1
2 /* $Id: base64.c,v 1.4 2005/01/24 02:22:13 terry_teague Exp $ */
3
4 /******************************************************************************
5
6 UserLand Frontier(tm) -- High performance Web content management,
7 object database, system-level and Internet scripting environment,
8 including source code editing and debugging.
9
10 Copyright (C) 1992-2004 UserLand Software, Inc.
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
26 ******************************************************************************/
27
28 #include "frontier.h"
29 #include "standard.h"
30
31 #include "memory.h"
32 #include "lang.h"
33 #include "BASE64.H"
34
35
36 static char encodingTable [64] = {
37
38 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
39
40 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
41
42 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
43
44 'w','x','y','z','','1','2','3','4','5','6','7','8','9','+','/'
45 };
46
47
48 static unsigned char gethandlechar (Handle h, unsigned long ix) {
49
50 return ((*h) [ix]);
51 } /*gethandlechar*/
52
53
54 static void sethandlechar (Handle h, unsigned long ix, unsigned char ch) {
55
56 (*h) [ix] = ch;
57 } /*sethandlechar*/
58
59
60 #define new_base64 1
61
62 #ifdef new_base64
63
64 boolean base64encodehandle (Handle htext, Handle h64, short linelength) {
65
66 /*
67 encode the handle. some funny stuff about linelength -- it only makes
68 sense to make it a multiple of 4. if it's not a multiple of 4, we make it
69 so (by only checking it every 4 characters.
70
71 further, if it's 0, we don't add any line breaks at all.
72
73 5.0a18 dmb: line breaks are /r, not /n
74
75 6.1d4 AR: updated to grow h64 in one go instead of once for every
76 three bytes of htext.
77 */
78
79 unsigned long ixtext;
80 unsigned long lentext;
81 unsigned long len64;
82 unsigned long pos64 = 0;
83 long ctremaining;
84 unsigned char inbuf [3], outbuf [4];
85 short i;
86 short charsonline = 0, ctcopy;
87
88 ixtext = 0;
89
90 lentext = gethandlesize (htext);
91
92 len64 = (lentext / 3) * 4;
93
94 if (lentext % 3 > 0)
95 len64 += 4;
96
97 if (linelength > 0) { /* add room for linebreaks */
98
99 unsigned long ctquadruplets = linelength / 4;
100
101 if (linelength % 4 > 0)
102 ++ctquadruplets;
103
104 linelength = ctquadruplets * 4;
105
106 len64 += (len64 / linelength);
107 }
108
109 if (!sethandlesize (h64, len64))
110 return (false);
111
112 while (true) {
113
114 ctremaining = lentext - ixtext;
115
116 if (ctremaining <= 0)
117 break;
118
119 for (i = 0; i < 3; i++) {
120
121 unsigned long ix = ixtext + i;
122
123 if (ix < lentext)
124 inbuf [i] = gethandlechar (htext, ix);
125 else
126 inbuf [i] = 0;
127 } /*for*/
128
129 outbuf [0] = (inbuf [0] & 0xFC) >> 2;
130
131 outbuf [1] = ((inbuf [0] & 0x03) << 4) | ((inbuf [1] & 0xF0) >> 4);
132
133 outbuf [2] = ((inbuf [1] & 0x0F) << 2) | ((inbuf [2] & 0xC0) >> 6);
134
135 outbuf [3] = inbuf [2] & 0x3F;
136
137 ctcopy = 4;
138
139 switch (ctremaining) {
140
141 case 1:
142 ctcopy = 2;
143
144 break;
145
146 case 2:
147 ctcopy = 3;
148
149 break;
150 } /*switch*/
151
152 for (i = 0; i < ctcopy; i++)
153 sethandlechar (h64, pos64 + i, encodingTable [outbuf [i]]);
154
155 for (i = ctcopy; i < 4; i++)
156 sethandlechar (h64, pos64 + i, '=');
157
158 ixtext += 3;
159
160 charsonline += 4;
161
162 pos64 += 4;
163
164 if (linelength > 0) { /*DW 4/8/97 -- 0 means no line breaks*/
165
166 if (charsonline >= linelength) {
167
168 charsonline = 0;
169
170 sethandlechar (h64, pos64++, '\r');
171 }
172 }
173 } /*while*/
174
175 assert (pos64 == len64); /*there's a bug in here if this assertion doesn't hold*/
176
177 return (true);
178 } /*encodehandle*/
179
180 #elif
181
182 boolean base64encodehandle (Handle htext, Handle h64, short linelength) {
183
184 /*
185 encode the handle. some funny stuff about linelength -- it only makes
186 sense to make it a multiple of 4. if it's not a multiple of 4, we make it
187 so (by only checking it every 4 characters.
188
189 further, if it's 0, we don't add any line breaks at all.
190
191 5.0a18 dmb: line breaks are /r, not /n
192 */
193
194 unsigned long ixtext;
195 unsigned long lentext;
196 unsigned long origsize;
197 long ctremaining;
198 unsigned char inbuf [3], outbuf [4];
199 short i;
200 short charsonline = 0, ctcopy;
201
202 ixtext = 0;
203
204 lentext = gethandlesize (htext);
205
206 while (true) {
207
208 ctremaining = lentext - ixtext;
209
210 if (ctremaining <= 0)
211 break;
212
213 for (i = 0; i < 3; i++) {
214
215 unsigned long ix = ixtext + i;
216
217 if (ix < lentext)
218 inbuf [i] = gethandlechar (htext, ix);
219 else
220 inbuf [i] = 0;
221 } /*for*/
222
223 outbuf [0] = (inbuf [0] & 0xFC) >> 2;
224
225 outbuf [1] = ((inbuf [0] & 0x03) << 4) | ((inbuf [1] & 0xF0) >> 4);
226
227 outbuf [2] = ((inbuf [1] & 0x0F) << 2) | ((inbuf [2] & 0xC0) >> 6);
228
229 outbuf [3] = inbuf [2] & 0x3F;
230
231 origsize = gethandlesize (h64);
232
233 if (!sethandlesize (h64, origsize + 4))
234 return (false);
235
236 ctcopy = 4;
237
238 switch (ctremaining) {
239
240 case 1:
241 ctcopy = 2;
242
243 break;
244
245 case 2:
246 ctcopy = 3;
247
248 break;
249 } /*switch*/
250
251 for (i = 0; i < ctcopy; i++)
252 sethandlechar (h64, origsize + i, encodingTable [outbuf [i]]);
253
254 for (i = ctcopy; i < 4; i++)
255 sethandlechar (h64, origsize + i, '=');
256
257 ixtext += 3;
258
259 charsonline += 4;
260
261 if (linelength > 0) { /*DW 4/8/97 -- 0 means no line breaks*/
262
263 if (charsonline >= linelength) {
264
265 charsonline = 0;
266
267 origsize = gethandlesize (h64);
268
269 if (!sethandlesize (h64, origsize + 1))
270 return (false);
271
272 sethandlechar (h64, origsize, '\r');
273 }
274 }
275 } /*while*/
276
277 return (true);
278 } /*encodehandle*/
279
280 #endif
281
282
283 #ifdef new_base64
284
285 boolean base64decodehandle (Handle h64, Handle htext) {
286
287 unsigned long ixtext;
288 unsigned long lentext;
289 unsigned char ch;
290 unsigned char inbuf [4], outbuf [3];
291 short ixinbuf;
292 boolean flendtext = false;
293 handlestream s;
294
295 ixtext = 0;
296
297 lentext = gethandlesize (h64);
298
299 ixinbuf = 0;
300
301 openhandlestream (htext, &s);
302
303 while (true) {
304 short ctcharsinbuf = 3;
305
306 if (ixtext >= lentext)
307 break;
308
309 ch = gethandlechar (h64, ixtext++);
310
311 if ((ch >= 'A') && (ch <= 'Z'))
312 ch = ch - 'A';
313
314 else if ((ch >= 'a') && (ch <= 'z'))
315 ch = ch - 'a' + 26;
316
317 else if ((ch >= '') && (ch <= '9'))
318 ch = ch - '' + 52;
319
320 else if (ch == '+')
321 ch = 62;
322
323 else if (ch == '/')
324 ch = 63;
325
326 else if (ch == '=') /*no op -- can't ignore this one*/
327 flendtext = true;
328
329 else
330 continue;
331
332 if (flendtext) {
333
334 if (ixinbuf == 0)
335 break;
336
337 if ((ixinbuf == 1) || (ixinbuf == 2))
338 ctcharsinbuf = 1;
339 else
340 ctcharsinbuf = 2;
341
342 ixinbuf = 3;
343 }
344
345 inbuf [ixinbuf++] = ch;
346
347 if (ixinbuf == 4) {
348
349 ixinbuf = 0;
350
351 outbuf [0] = (inbuf [0] << 2) | ((inbuf [1] & 0x30) >> 4);
352
353 outbuf [1] = ((inbuf [1] & 0x0F) << 4) | ((inbuf [2] & 0x3C) >> 2);
354
355 outbuf [2] = ((inbuf [2] & 0x03) << 6) | (inbuf [3] & 0x3F);
356
357 if (!writehandlestream (&s, outbuf, ctcharsinbuf))
358 return (false);
359 }
360
361 if (flendtext)
362 break;
363 } /*while*/
364
365 closehandlestream (&s);
366
367 return (true);
368 } /*decodehandle*/
369
370 #elif
371
372 boolean base64decodehandle (Handle h64, Handle htext) {
373
374 unsigned long ixtext;
375 unsigned long lentext;
376 unsigned long origsize;
377 unsigned char ch;
378 unsigned char inbuf [4], outbuf [3];
379 short i, ixinbuf;
380 boolean flignore;
381 boolean flendtext = false;
382
383 ixtext = 0;
384
385 lentext = gethandlesize (h64);
386
387 ixinbuf = 0;
388
389 while (true) {
390
391 if (ixtext >= lentext)
392 break;
393
394 ch = gethandlechar (h64, ixtext++);
395
396 flignore = false;
397
398 if ((ch >= 'A') && (ch <= 'Z'))
399 ch = ch - 'A';
400
401 else if ((ch >= 'a') && (ch <= 'z'))
402 ch = ch - 'a' + 26;
403
404 else if ((ch >= '') && (ch <= '9'))
405 ch = ch - '' + 52;
406
407 else if (ch == '+')
408 ch = 62;
409
410 else if (ch == '=') /*no op -- can't ignore this one*/
411 flendtext = true;
412
413 else if (ch == '/')
414 ch = 63;
415
416 else
417 flignore = true;
418
419 if (!flignore) {
420
421 short ctcharsinbuf = 3;
422 boolean flbreak = false;
423
424 if (flendtext) {
425
426 if (ixinbuf == 0)
427 break;
428
429 if ((ixinbuf == 1) || (ixinbuf == 2))
430 ctcharsinbuf = 1;
431 else
432 ctcharsinbuf = 2;
433
434 ixinbuf = 3;
435
436 flbreak = true;
437 }
438
439 inbuf [ixinbuf++] = ch;
440
441 if (ixinbuf == 4) {
442
443 ixinbuf = 0;
444
445 outbuf [0] = (inbuf [0] << 2) | ((inbuf [1] & 0x30) >> 4);
446
447 outbuf [1] = ((inbuf [1] & 0x0F) << 4) | ((inbuf [2] & 0x3C) >> 2);
448
449 outbuf [2] = ((inbuf [2] & 0x03) << 6) | (inbuf [3] & 0x3F);
450
451 origsize = gethandlesize (htext);
452
453 if (!sethandlesize (htext, origsize + ctcharsinbuf))
454 return (false);
455
456 for (i = 0; i < ctcharsinbuf; i++)
457 sethandlechar (htext, origsize + i, outbuf [i]);
458 }
459
460 if (flbreak)
461 break;
462 }
463 } /*while*/
464
465 return (true);
466 } /*decodehandle*/
467
468 #endif
469
470
471 boolean base64encodeverb (hdltreenode hparam1, tyvaluerecord *vreturned) {
472
473 Handle h64, htext;
474 short linelength;
475
476 if (!gettextvalue (hparam1, 1, &htext))
477 return (false);
478
479 flnextparamislast = true;
480
481 if (!getintvalue (hparam1, 2, &linelength))
482 return (false);
483
484 if (!newemptyhandle (&h64))
485 return (false);
486
487 if (!base64encodehandle (htext, h64, linelength)) {
488
489 disposehandle (h64);
490
491 return (false);
492 }
493
494 return (setheapvalue (h64, stringvaluetype, vreturned));
495 } /*base64encodeverb*/
496
497
498 boolean base64decodeverb (hdltreenode hparam1, tyvaluerecord *vreturned) {
499
500 /*
501 5.0.1 dmb: return a string, not an unknown binary type
502 */
503
504 Handle h64, htext;
505
506 flnextparamislast = true;
507
508 if (!gettextvalue (hparam1, 1, &h64))
509 return (false);
510
511 if (!newemptyhandle (&htext))
512 return (false);
513
514 if (!base64decodehandle (h64, htext)) {
515
516 disposehandle (htext);
517
518 return (false);
519 }
520
521 return (setheapvalue (htext, stringvaluetype, vreturned));
522 } /*base64decodeverb*/
523
524
525
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.