Test initialisation of MUIA_List_AdjustWidth and MUIA_List_AdjustHeight, and
[AROS.git] / workbench / libs / codesets / src / base64.c
blobf0193bcfced87617539b4ff1744c53d46c84cf29
1 /***************************************************************************
3 codesets.library - Amiga shared library for handling different codesets
4 Copyright (C) 2001-2005 by Alfonso [alfie] Ranieri <alforan@tin.it>.
5 Copyright (C) 2005-2014 codesets.library Open Source Team
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 codesets.library project: http://sourceforge.net/projects/codesetslib/
19 $Id$
21 ***************************************************************************/
23 #include "lib.h"
24 #include "SDI_stdarg.h"
25 #include "debug.h"
27 /****************************************************************************/
29 struct b64
31 APTR in;
32 APTR out;
33 ULONG flags;
34 int inIndex;
35 int inAvailable;
36 int outIndex;
37 int maxLineLen;
38 int lineCounter;
39 const char *eols;
40 LONG error;
43 enum
45 B64FLG_SourceFile = 1<<0,
46 B64FLG_DestFile = 1<<1,
47 B64FLG_Unix = 1<<2,
50 /****************************************************************************/
52 #define MAXLINELEN 72
54 #ifndef EOF
55 #define EOF (-1)
56 #endif
58 /****************************************************************************/
60 static const UBYTE etable[] =
62 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
63 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
64 85, 86, 87, 88, 89, 90, 97, 98, 99, 100,
65 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
66 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
67 121, 122, 48, 49, 50, 51, 52, 53, 54, 55,
68 56, 57, 43, 47, 0, 0, 0, 0, 0, 0,
69 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
70 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
71 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
72 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
73 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
74 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
75 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
76 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
77 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
78 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
79 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
80 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
81 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
82 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
83 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
84 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
85 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
86 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
87 0, 0, 0, 0, 0, 0
90 static const UBYTE dtable[] =
92 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
93 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
94 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
95 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
96 128, 128, 128, 62, 128, 128, 128, 63, 52, 53,
97 54, 55, 56, 57, 58, 59, 60, 61, 128, 128,
98 128, 0, 128, 128, 128, 0, 1, 2, 3, 4,
99 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
100 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
101 25, 128, 128, 128, 128, 128, 128, 26, 27, 28,
102 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
103 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
104 49, 50, 51, 128, 128, 128, 128, 128, 128, 128,
105 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
106 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
107 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
108 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
109 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
110 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
111 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
112 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
113 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
114 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
115 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
116 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
117 128, 128, 128, 128, 128, 0
120 /****************************************************************************/
122 #if defined(__amigaos4__)
123 static BPTR openIn(STRPTR name, int64 *size)
125 BPTR file = 0;
126 struct ExamineData *exd;
128 ENTER();
130 if((exd = ExamineObjectTags(EX_StringNameInput, name, TAG_END)) != NULL)
132 if(EXD_IS_FILE(exd))
134 if((file = Open(name, MODE_OLDFILE)))
135 *size = exd->FileSize;
138 FreeDosObject(DOS_EXAMINEDATA, exd);
141 RETURN(file);
142 return file;
145 #elif defined(__MORPHOS__)
146 static BPTR openIn(STRPTR name, ULONG *size)
148 struct FileInfoBlock fib;
149 BPTR file;
151 ENTER();
153 if((file = Open(name, MODE_OLDFILE)))
155 if(!ExamineFH(file, &fib))
157 Close(file);
158 file = 0;
160 else
162 *size = fib.fib_Size;
166 RETURN(file);
167 return file;
169 #else
170 static BPTR openIn(STRPTR name, ULONG * size)
172 struct FileInfoBlock *fib;
173 BPTR file;
175 ENTER();
177 if((fib = AllocDosObject(DOS_FIB,NULL)) != NULL)
179 if((file = Open(name, MODE_OLDFILE)))
181 if(!ExamineFH(file, fib))
183 Close(file);
184 file = 0;
186 else
188 *size = fib->fib_Size;
192 FreeDosObject(DOS_FIB, fib);
194 else
195 file = 0;
197 RETURN(file);
198 return file;
200 #endif
202 /****************************************************************************/
204 static int inchar(struct b64 *b64)
206 int c;
208 ENTER();
210 if(b64->flags & B64FLG_SourceFile)
212 if((c = FGetC((BPTR)b64->in)) == EOF)
214 if(IoErr() != 0)
215 b64->error = CSR_B64_ERROR_DOS;
218 else
220 if(b64->inAvailable == 0)
222 RETURN(EOF);
223 return EOF;
226 c = ((STRPTR)b64->in)[b64->inIndex++];
227 b64->inAvailable--;
230 RETURN(c);
231 return c;
234 /****************************************************************************/
236 static int ochar(struct b64 *b64, int c)
238 ENTER();
240 if(b64->flags & B64FLG_DestFile)
242 int r = 0;
244 if(b64->maxLineLen && (b64->lineCounter>=b64->maxLineLen))
246 r = FPuts((BPTR)b64->out,b64->eols);
247 b64->lineCounter = 0;
250 if(!r)
252 r = FPutC((BPTR)b64->out,c);
255 if(r==EOF)
257 b64->error = CSR_B64_ERROR_DOS;
259 RETURN(EOF);
260 return EOF;
263 b64->lineCounter++;
265 else
267 ((STRPTR)b64->out)[b64->outIndex++] = c;
270 RETURN(0);
271 return 0;
274 /****************************************************************************/
276 static int ostring(struct b64 *b64, UBYTE * buf, int s)
278 int i;
280 ENTER();
282 if(b64->flags & B64FLG_DestFile)
284 int r;
286 for(r = i = 0; (r!=EOF) && (i<s); i++)
288 r = FPutC((BPTR)b64->out,buf[i]);
291 if(r==EOF)
293 b64->error = CSR_B64_ERROR_DOS;
295 RETURN(EOF);
296 return EOF;
299 else
301 for(i = 0; i<s; i++)
302 ((STRPTR)b64->out)[b64->outIndex++] = buf[i];
305 RETURN(0);
306 return 0;
309 /****************************************************************************/
311 static int insig(struct b64 *b64)
313 int c;
315 for(;;)
317 c = inchar(b64);
319 if((c==EOF) || (c>' '))
321 RETURN(c);
322 return c;
327 /****************************************************************************/
329 LIBPROTO(CodesetsEncodeB64A, ULONG, REG(a6, UNUSED __BASE_OR_IFACE), REG(a0, struct TagItem *attrs))
331 struct b64 b64;
332 struct TagItem *tag;
333 STRPTR source;
334 APTR dest, in, out;
335 ULONG totSize, stop, flags;
336 #if defined(__amigaos4__)
337 int64 size;
338 #else
339 ULONG size;
340 #endif
341 int sourceLen = 0, maxLineLen;
343 flags = 0;
345 if((tag = FindTagItem(CSA_B64SourceFile, attrs)) != NULL)
347 source = (STRPTR)tag->ti_Data;
348 flags |= B64FLG_SourceFile;
350 else
352 if((source = (STRPTR)GetTagData(CSA_B64SourceString, 0, attrs)) == NULL)
354 RETURN(CSR_B64_ERROR_MEM);
355 return CSR_B64_ERROR_MEM;
358 if((tag = FindTagItem(CSA_B64SourceLen, attrs)) != NULL)
359 sourceLen = tag->ti_Data;
360 else
361 sourceLen = strlen(source);
364 if((tag = FindTagItem(CSA_B64DestFile, attrs)) != NULL)
366 dest = (APTR)tag->ti_Data;
367 flags |= B64FLG_DestFile;
369 else
371 if((dest = (APTR)GetTagData(CSA_B64DestPtr, 0, attrs)) == NULL)
373 RETURN(CSR_B64_ERROR_MEM);
374 return CSR_B64_ERROR_MEM;
378 maxLineLen = GetTagData(CSA_B64MaxLineLen,0,attrs);
379 if(maxLineLen<=0 || maxLineLen>=256)
380 maxLineLen = MAXLINELEN;
382 if(GetTagData(CSA_B64Unix,TRUE,attrs))
383 flags |= B64FLG_Unix;
385 /* source */
386 if(flags & B64FLG_SourceFile)
388 if(!(in = (APTR)openIn(source,&size)))
390 RETURN(CSR_B64_ERROR_DOS);
391 return CSR_B64_ERROR_DOS;
394 b64.inAvailable = 0;
396 else
398 in = source;
399 size = sourceLen;
400 b64.inAvailable = size;
403 totSize = size<<1;
405 /* dest */
406 if(flags & B64FLG_DestFile)
408 if(!(out = (APTR)Open(dest,MODE_NEWFILE)))
410 RETURN(CSR_B64_ERROR_DOS);
411 return CSR_B64_ERROR_DOS;
414 else
416 if(!totSize)
417 totSize = 8;
419 if((out = allocArbitrateVecPooled(totSize)) == NULL)
421 if(flags & B64FLG_SourceFile)
422 Close((BPTR)in);
424 RETURN(CSR_B64_ERROR_MEM);
425 return CSR_B64_ERROR_MEM;
428 *((STRPTR *)dest) = out;
431 /* set globals */
432 b64.in = in;
433 b64.out = out;
434 b64.flags = flags;
435 b64.inIndex = 0;
436 b64.outIndex = 0;
437 b64.maxLineLen = maxLineLen;
438 b64.lineCounter = 0;
439 b64.eols = (flags & B64FLG_Unix) ? "\n" : "\r\n";
440 b64.error = 0;
442 /* encode */
443 stop = FALSE;
444 while(stop == FALSE)
446 UBYTE igroup[3], ogroup[4];
447 int i, c, n;
449 igroup[0] = igroup[1] = igroup[2] = 0;
451 for(n = 0; n<3; n++)
453 c = inchar(&b64);
454 if(c==EOF)
456 stop = TRUE;
457 break;
460 igroup[n] = (UBYTE) c;
463 if(n>0)
465 ogroup[0] = etable[igroup[0]>>2];
466 ogroup[1] = etable[((igroup[0] & 3)<<4) | (igroup[1]>>4)];
467 ogroup[2] = etable[((igroup[1] & 0xF)<<2) | (igroup[2]>>6)];
468 ogroup[3] = etable[igroup[2] & 0x3F];
470 if(n<3)
472 ogroup[3] = '=';
473 if(n<2)
474 ogroup[2] = '=';
477 for(i=0; i<4; i++)
479 c = ochar(&b64,ogroup[i]);
480 if(c==EOF)
482 stop = TRUE;
483 break;
489 if(!(b64.flags & B64FLG_DestFile))
490 ((STRPTR)out)[b64.outIndex] = 0;
492 /* close source */
493 if(flags & B64FLG_SourceFile)
494 Close((BPTR)in);
496 /* flush and close dest */
497 if(flags & B64FLG_DestFile)
499 if(!b64.error)
501 if(FPuts((BPTR)out,b64.eols)==EOF)
502 b64.error = CSR_B64_ERROR_DOS;
504 #if defined(__amigaos4__)
505 FFlush((BPTR)out);
506 #else
507 Flush((BPTR)out);
508 #endif
511 Close((BPTR)out);
513 else
515 if(b64.error)
516 freeArbitrateVecPooled(out);
519 RETURN((ULONG)b64.error);
520 return (ULONG)b64.error;
523 #if defined(__amigaos4__)
524 LIBPROTOVA(CodesetsEncodeB64, ULONG, REG(a6, UNUSED __BASE_OR_IFACE), ...)
526 ULONG res;
527 VA_LIST args;
529 VA_START(args, ICodesets);
530 res = CodesetsEncodeB64A(VA_ARG(args, struct TagItem *));
531 VA_END(args);
533 return res;
535 #endif
537 /****************************************************************************/
539 LIBPROTO(CodesetsDecodeB64A, ULONG, REG(a6, UNUSED __BASE_OR_IFACE), REG(a0, struct TagItem *attrs))
541 struct b64 b64;
542 struct TagItem *tag;
543 STRPTR source;
544 APTR dest, in, out;
545 ULONG totSize, flags, errcheck;
546 #if defined(__amigaos4__)
547 int64 size;
548 #else
549 ULONG size;
550 #endif
551 int sourceLen = 0;
553 ENTER();
555 flags = 0;
557 if((tag = FindTagItem(CSA_B64SourceFile, attrs)) != NULL)
559 source = (STRPTR)tag->ti_Data;
560 flags |= B64FLG_SourceFile;
562 else
564 if ((source = (STRPTR)GetTagData(CSA_B64SourceString, 0, attrs)) == NULL)
566 RETURN(CSR_B64_ERROR_MEM);
567 return CSR_B64_ERROR_MEM;
570 if((tag = FindTagItem(CSA_B64SourceLen, attrs)) != NULL)
571 sourceLen = tag->ti_Data;
572 else
573 sourceLen = strlen(source);
576 if((tag = FindTagItem(CSA_B64DestFile, attrs)) != NULL)
578 dest = (APTR)tag->ti_Data;
579 flags |= B64FLG_DestFile;
581 else
583 if((dest = (APTR)GetTagData(CSA_B64DestPtr, 0, attrs)) == NULL)
585 RETURN(CSR_B64_ERROR_MEM);
586 return CSR_B64_ERROR_MEM;
590 /* source */
591 if(flags & B64FLG_SourceFile)
593 if(!(in = (APTR)openIn(source, &size)))
595 RETURN(CSR_B64_ERROR_DOS);
596 return CSR_B64_ERROR_DOS;
599 b64.inAvailable = 0;
601 else
603 in = source;
604 size = sourceLen;
605 b64.inAvailable = size;
608 totSize = size<<1;
610 /* dest */
611 if(flags & B64FLG_DestFile)
613 if(!(out = (APTR)Open(dest, MODE_NEWFILE)))
615 RETURN(CSR_B64_ERROR_DOS);
616 return CSR_B64_ERROR_DOS;
619 else
621 if(!totSize)
622 totSize = 8;
624 if(!(out = allocArbitrateVecPooled(totSize)))
626 if(flags & B64FLG_SourceFile)
627 Close((BPTR)in);
629 RETURN(CSR_B64_ERROR_MEM);
630 return CSR_B64_ERROR_MEM;
633 *((STRPTR *)dest) = out;
636 b64.in = in;
637 b64.out = out;
638 b64.flags = flags;
639 b64.inIndex = 0;
640 b64.outIndex = 0;
641 b64.maxLineLen = 0;
642 b64.lineCounter = 0;
643 b64.eols = NULL;
644 b64.error = 0;
646 /* parse error check */
647 errcheck = !GetTagData(CSA_B64FLG_NtCheckErr, FALSE, attrs);
649 /* decode */
650 for(;;)
652 UBYTE a[4], b[4], o[3];
653 int i;
655 for(i = 0; i<4; i++)
657 int c = insig (&b64);
659 if(c==EOF)
661 if(!(b64.flags & B64FLG_DestFile))
662 ((STRPTR)out)[b64.outIndex] = 0;
664 if(!b64.error && errcheck && (i>0))
665 b64.error = CSR_B64_ERROR_INCOMPLETE;
667 goto end;
670 if(dtable[c] & 0x80)
672 if(errcheck)
674 b64.error = CSR_B64_ERROR_ILLEGAL;
676 goto end;
679 i--;
680 continue;
683 a[i] = (UBYTE) c;
684 b[i] = (UBYTE) dtable[c];
687 o[0] = (b[0]<<2) | (b[1]>>4);
688 o[1] = (b[1]<<4) | (b[2]>>2);
689 o[2] = (b[2]<<6) | b[3];
691 i = a[2]=='=' ? 1 : (a[3]=='=' ? 2 : 3);
693 if(ostring(&b64,o,i)==EOF || i < 3)
694 goto end;
697 end:
699 /* close source */
700 if(flags & B64FLG_SourceFile)
701 Close((BPTR)in);
703 /* flush and close dest */
704 if(flags & B64FLG_DestFile)
706 if(!b64.error)
708 if(FPuts((BPTR)out,b64.eols)==EOF)
709 b64.error = CSR_B64_ERROR_DOS;
711 #if defined(__amigaos4__)
712 FFlush((BPTR)out);
713 #else
714 Flush((BPTR)out);
715 #endif
718 Close((BPTR)out);
720 else
722 if(b64.error)
723 freeArbitrateVecPooled(out);
726 RETURN((ULONG)b64.error);
727 return (ULONG)b64.error;
730 #if defined(__amigaos4__)
731 LIBPROTOVA(CodesetsDecodeB64, ULONG, REG(a6, UNUSED __BASE_OR_IFACE), ...)
733 ULONG res;
734 VA_LIST args;
736 VA_START(args, ICodesets);
737 res = CodesetsDecodeB64A(VA_ARG(args, struct TagItem *));
738 VA_END(args);
740 return res;
742 #endif
744 /****************************************************************************/