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/
21 ***************************************************************************/
24 #include "SDI_stdarg.h"
27 /****************************************************************************/
45 B64FLG_SourceFile
= 1<<0,
46 B64FLG_DestFile
= 1<<1,
50 /****************************************************************************/
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,
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
)
126 struct ExamineData
*exd
;
130 if((exd
= ExamineObjectTags(EX_StringNameInput
, name
, TAG_END
)) != NULL
)
134 if((file
= Open(name
, MODE_OLDFILE
)))
135 *size
= exd
->FileSize
;
138 FreeDosObject(DOS_EXAMINEDATA
, exd
);
145 #elif defined(__MORPHOS__)
146 static BPTR
openIn(STRPTR name
, ULONG
*size
)
148 struct FileInfoBlock fib
;
153 if((file
= Open(name
, MODE_OLDFILE
)))
155 if(!ExamineFH(file
, &fib
))
162 *size
= fib
.fib_Size
;
170 static BPTR
openIn(STRPTR name
, ULONG
* size
)
172 struct FileInfoBlock
*fib
;
177 if((fib
= AllocDosObject(DOS_FIB
,NULL
)) != NULL
)
179 if((file
= Open(name
, MODE_OLDFILE
)))
181 if(!ExamineFH(file
, fib
))
188 *size
= fib
->fib_Size
;
192 FreeDosObject(DOS_FIB
, fib
);
202 /****************************************************************************/
204 static int inchar(struct b64
*b64
)
210 if(b64
->flags
& B64FLG_SourceFile
)
212 if((c
= FGetC((BPTR
)b64
->in
)) == EOF
)
215 b64
->error
= CSR_B64_ERROR_DOS
;
220 if(b64
->inAvailable
== 0)
226 c
= ((STRPTR
)b64
->in
)[b64
->inIndex
++];
234 /****************************************************************************/
236 static int ochar(struct b64
*b64
, int c
)
240 if(b64
->flags
& B64FLG_DestFile
)
244 if(b64
->maxLineLen
&& (b64
->lineCounter
>=b64
->maxLineLen
))
246 r
= FPuts((BPTR
)b64
->out
,b64
->eols
);
247 b64
->lineCounter
= 0;
252 r
= FPutC((BPTR
)b64
->out
,c
);
257 b64
->error
= CSR_B64_ERROR_DOS
;
267 ((STRPTR
)b64
->out
)[b64
->outIndex
++] = c
;
274 /****************************************************************************/
276 static int ostring(struct b64
*b64
, UBYTE
* buf
, int s
)
282 if(b64
->flags
& B64FLG_DestFile
)
286 for(r
= i
= 0; (r
!=EOF
) && (i
<s
); i
++)
288 r
= FPutC((BPTR
)b64
->out
,buf
[i
]);
293 b64
->error
= CSR_B64_ERROR_DOS
;
302 ((STRPTR
)b64
->out
)[b64
->outIndex
++] = buf
[i
];
309 /****************************************************************************/
311 static int insig(struct b64
*b64
)
319 if((c
==EOF
) || (c
>' '))
327 /****************************************************************************/
329 LIBPROTO(CodesetsEncodeB64A
, ULONG
, REG(a6
, UNUSED __BASE_OR_IFACE
), REG(a0
, struct TagItem
*attrs
))
335 ULONG totSize
, stop
, flags
;
336 #if defined(__amigaos4__)
341 int sourceLen
= 0, maxLineLen
;
345 if((tag
= FindTagItem(CSA_B64SourceFile
, attrs
)) != NULL
)
347 source
= (STRPTR
)tag
->ti_Data
;
348 flags
|= B64FLG_SourceFile
;
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
;
361 sourceLen
= strlen(source
);
364 if((tag
= FindTagItem(CSA_B64DestFile
, attrs
)) != NULL
)
366 dest
= (APTR
)tag
->ti_Data
;
367 flags
|= B64FLG_DestFile
;
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
;
386 if(flags
& B64FLG_SourceFile
)
388 if(!(in
= (APTR
)openIn(source
,&size
)))
390 RETURN(CSR_B64_ERROR_DOS
);
391 return CSR_B64_ERROR_DOS
;
400 b64
.inAvailable
= size
;
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
;
419 if((out
= allocArbitrateVecPooled(totSize
)) == NULL
)
421 if(flags
& B64FLG_SourceFile
)
424 RETURN(CSR_B64_ERROR_MEM
);
425 return CSR_B64_ERROR_MEM
;
428 *((STRPTR
*)dest
) = out
;
437 b64
.maxLineLen
= maxLineLen
;
439 b64
.eols
= (flags
& B64FLG_Unix
) ? "\n" : "\r\n";
446 UBYTE igroup
[3], ogroup
[4];
449 igroup
[0] = igroup
[1] = igroup
[2] = 0;
460 igroup
[n
] = (UBYTE
) c
;
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];
479 c
= ochar(&b64
,ogroup
[i
]);
489 if(!(b64
.flags
& B64FLG_DestFile
))
490 ((STRPTR
)out
)[b64
.outIndex
] = 0;
493 if(flags
& B64FLG_SourceFile
)
496 /* flush and close dest */
497 if(flags
& B64FLG_DestFile
)
501 if(FPuts((BPTR
)out
,b64
.eols
)==EOF
)
502 b64
.error
= CSR_B64_ERROR_DOS
;
504 #if defined(__amigaos4__)
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
), ...)
529 VA_START(args
, ICodesets
);
530 res
= CodesetsEncodeB64A(VA_ARG(args
, struct TagItem
*));
537 /****************************************************************************/
539 LIBPROTO(CodesetsDecodeB64A
, ULONG
, REG(a6
, UNUSED __BASE_OR_IFACE
), REG(a0
, struct TagItem
*attrs
))
545 ULONG totSize
, flags
, errcheck
;
546 #if defined(__amigaos4__)
557 if((tag
= FindTagItem(CSA_B64SourceFile
, attrs
)) != NULL
)
559 source
= (STRPTR
)tag
->ti_Data
;
560 flags
|= B64FLG_SourceFile
;
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
;
573 sourceLen
= strlen(source
);
576 if((tag
= FindTagItem(CSA_B64DestFile
, attrs
)) != NULL
)
578 dest
= (APTR
)tag
->ti_Data
;
579 flags
|= B64FLG_DestFile
;
583 if((dest
= (APTR
)GetTagData(CSA_B64DestPtr
, 0, attrs
)) == NULL
)
585 RETURN(CSR_B64_ERROR_MEM
);
586 return CSR_B64_ERROR_MEM
;
591 if(flags
& B64FLG_SourceFile
)
593 if(!(in
= (APTR
)openIn(source
, &size
)))
595 RETURN(CSR_B64_ERROR_DOS
);
596 return CSR_B64_ERROR_DOS
;
605 b64
.inAvailable
= size
;
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
;
624 if(!(out
= allocArbitrateVecPooled(totSize
)))
626 if(flags
& B64FLG_SourceFile
)
629 RETURN(CSR_B64_ERROR_MEM
);
630 return CSR_B64_ERROR_MEM
;
633 *((STRPTR
*)dest
) = out
;
646 /* parse error check */
647 errcheck
= !GetTagData(CSA_B64FLG_NtCheckErr
, FALSE
, attrs
);
652 UBYTE a
[4], b
[4], o
[3];
657 int c
= insig (&b64
);
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
;
674 b64
.error
= CSR_B64_ERROR_ILLEGAL
;
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)
700 if(flags
& B64FLG_SourceFile
)
703 /* flush and close dest */
704 if(flags
& B64FLG_DestFile
)
708 if(FPuts((BPTR
)out
,b64
.eols
)==EOF
)
709 b64
.error
= CSR_B64_ERROR_DOS
;
711 #if defined(__amigaos4__)
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
), ...)
736 VA_START(args
, ICodesets
);
737 res
= CodesetsDecodeB64A(VA_ARG(args
, struct TagItem
*));
744 /****************************************************************************/