3 Copyright 1997-2004 Gisle Aas
5 This library is free software; you can redistribute it and/or
6 modify it under the same terms as Perl itself.
9 The tables and some of the code that used to be here was borrowed from
10 metamail, which comes with this message:
12 Copyright (c) 1991 Bell Communications Research, Inc. (Bellcore)
14 Permission to use, copy, modify, and distribute this material
15 for any purpose and without fee is hereby granted, provided
16 that the above copyright notice and this permission notice
17 appear in all copies, and that the name of Bellcore not be
18 used in advertising or publicity pertaining to this
19 material without the specific, prior written permission
20 of an authorized representative of Bellcore. BELLCORE
21 MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY
22 OF THIS MATERIAL FOR ANY PURPOSE. IT IS PROVIDED "AS IS",
23 WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
31 #define PERL_NO_GET_CONTEXT /* we want efficiency */
39 #define MAX_LINE 76 /* size of encoded lines */
41 static const char basis_64[] =
42 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
44 #define XX 255 /* illegal base64 char */
45 #define EQ 254 /* padding */
48 static const unsigned char index_64[256] = {
49 XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
50 XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
51 XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,62, XX,XX,XX,63,
52 52,53,54,55, 56,57,58,59, 60,61,XX,XX, XX,EQ,XX,XX,
53 XX, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
54 15,16,17,18, 19,20,21,22, 23,24,25,XX, XX,XX,XX,XX,
55 XX,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
56 41,42,43,44, 45,46,47,48, 49,50,51,XX, XX,XX,XX,XX,
58 XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
59 XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
60 XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
61 XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
62 XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
63 XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
64 XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
65 XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
69 # if PERL_REVISION == 5 && PERL_VERSION < 7
70 /* SvPVbyte does not work in perl-5.6.1, borrowed version for 5.7.3 */
72 # define SvPVbyte(sv, lp) \
73 ((SvFLAGS(sv) & (SVf_POK|SVf_UTF8)) == (SVf_POK) \
74 ? ((lp = SvCUR(sv)), SvPVX(sv)) : my_sv_2pvbyte(aTHX_ sv, &lp))
76 my_sv_2pvbyte(pTHX_ register SV *sv, STRLEN *lp)
78 sv_utf8_downgrade(sv,0);
83 # define SvPVbyte SvPV
87 # define isXDIGIT isxdigit
90 #ifndef NATIVE_TO_ASCII
91 # define NATIVE_TO_ASCII(ch) (ch)
94 MODULE = MIME::Base64 PACKAGE = MIME::Base64
102 char *str; /* string to encode */
103 SSize_t len; /* length of the string */
104 const char*eol;/* the end-of-line sequence to use */
105 STRLEN eollen; /* length of the EOL sequence */
106 char *r; /* result string */
107 STRLEN rlen; /* length of result string */
108 unsigned char c1, c2, c3;
113 #if PERL_REVISION == 5 && PERL_VERSION >= 6
114 had_utf8 = SvUTF8(sv);
115 sv_utf8_downgrade(sv, FALSE);
117 str = SvPV(sv, rlen); /* SvPV(sv, len) gives warning for signed len */
120 /* set up EOL from the second argument if present, default to "\n" */
121 if (items > 1 && SvOK(ST(1))) {
122 eol = SvPV(ST(1), eollen);
128 /* calculate the length of the result */
129 rlen = (len+2) / 3 * 4; /* encoded bytes */
131 /* add space for EOL */
132 rlen += ((rlen-1) / MAX_LINE + 1) * eollen;
135 /* allocate a result buffer */
136 RETVAL = newSV(rlen ? rlen : 1);
138 SvCUR_set(RETVAL, rlen);
142 for (chunk=0; len > 0; len -= 3, chunk++) {
143 if (chunk == (MAX_LINE/4)) {
145 const char *e = eol + eollen;
151 c2 = len > 1 ? *str++ : '\0';
152 *r++ = basis_64[c1>>2];
153 *r++ = basis_64[((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)];
156 *r++ = basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)];
157 *r++ = basis_64[c3 & 0x3F];
158 } else if (len == 2) {
159 *r++ = basis_64[(c2 & 0xF) << 2];
161 } else { /* len == 1 */
167 /* append eol to the result string */
169 const char *e = eol + eollen;
173 *r = '\0'; /* every SV in perl should be NUL-terminated */
174 #if PERL_REVISION == 5 && PERL_VERSION >= 6
189 register unsigned char *str = (unsigned char*)SvPV(sv, len);
190 unsigned char const* end = str + len;
196 /* always enough, but might be too much */
197 STRLEN rlen = len * 3 / 4;
198 RETVAL = newSV(rlen ? rlen : 1);
206 unsigned char uc = index_64[NATIVE_TO_ASCII(*str++)];
212 if (i < 2) goto thats_it;
213 if (i == 2) c[2] = EQ;
220 if (c[0] == EQ || c[1] == EQ) {
223 /* printf("c0=%d,c1=%d,c2=%d,c3=%d\n", c[0],c[1],c[2],c[3]);*/
225 *r++ = (c[0] << 2) | ((c[1] & 0x30) >> 4);
229 *r++ = ((c[1] & 0x0F) << 4) | ((c[2] & 0x3C) >> 2);
233 *r++ = ((c[2] & 0x03) << 6) | c[3];
237 SvCUR_set(RETVAL, r - SvPVX(RETVAL));
244 encoded_base64_length(sv,...)
249 SSize_t len; /* length of the string */
250 STRLEN eollen; /* length of the EOL sequence */
254 #if PERL_REVISION == 5 && PERL_VERSION >= 6
255 had_utf8 = SvUTF8(sv);
256 sv_utf8_downgrade(sv, FALSE);
259 #if PERL_REVISION == 5 && PERL_VERSION >= 6
264 if (items > 1 && SvOK(ST(1))) {
265 eollen = SvCUR(ST(1));
270 RETVAL = (len+2) / 3 * 4; /* encoded bytes */
272 RETVAL += ((RETVAL-1) / MAX_LINE + 1) * eollen;
279 decoded_base64_length(sv)
285 register unsigned char *str = (unsigned char*)SvPV(sv, len);
286 unsigned char const* end = str + len;
292 unsigned char uc = index_64[NATIVE_TO_ASCII(*str++)];
308 MODULE = MIME::Base64 PACKAGE = MIME::QuotedPrint
311 #define qp_isplain(c) ((c) == '\t' || ((!isprint(c) && (c) != '=')))
313 #define qp_isplain(c) ((c) == '\t' || (((c) >= ' ' && (c) <= '~') && (c) != '='))
335 #if PERL_REVISION == 5 && PERL_VERSION >= 6
336 had_utf8 = SvUTF8(sv);
337 sv_utf8_downgrade(sv, FALSE);
339 /* set up EOL from the second argument if present, default to "\n" */
340 if (items > 1 && SvOK(ST(1))) {
341 eol = SvPV(ST(1), eol_len);
347 binary = (items > 2 && SvTRUE(ST(2)));
349 beg = SvPV(sv, sv_len);
352 RETVAL = newSV(sv_len + 1);
353 sv_setpv(RETVAL, "");
360 /* skip past as much plain text as possible */
361 while (p < end && qp_isplain(*p)) {
364 if (p == end || *p == '\n') {
365 /* whitespace at end of line must be encoded */
366 while (p > p_beg && (*(p - 1) == '\t' || *(p - 1) == ' '))
372 /* output plain text (with line breaks) */
374 while (p_len > MAX_LINE - 1 - linelen) {
375 STRLEN len = MAX_LINE - 1 - linelen;
376 sv_catpvn(RETVAL, p_beg, len);
379 sv_catpvn(RETVAL, "=", 1);
380 sv_catpvn(RETVAL, eol, eol_len);
385 sv_catpvn(RETVAL, p_beg, p_len);
393 else if (*p == '\n' && eol_len && !binary) {
394 if (linelen == 1 && SvCUR(RETVAL) > eol_len + 1 && SvEND(RETVAL)[-eol_len - 2] == '=') {
395 /* fixup useless soft linebreak */
396 SvEND(RETVAL)[-eol_len - 2] = SvEND(RETVAL)[-1];
397 SvCUR_set(RETVAL, SvCUR(RETVAL) - 1);
400 sv_catpvn(RETVAL, eol, eol_len);
406 /* output escaped char (with line breaks) */
408 if (eol_len && linelen > MAX_LINE - 4 && !(linelen == MAX_LINE - 3 && p + 1 < end && p[1] == '\n' && !binary)) {
409 sv_catpvn(RETVAL, "=", 1);
410 sv_catpvn(RETVAL, eol, eol_len);
413 sv_catpvf(RETVAL, "=%02X", (unsigned char)*p);
418 /* optimize reallocs a bit */
419 if (SvLEN(RETVAL) > 80 && SvLEN(RETVAL) - SvCUR(RETVAL) < 3) {
420 STRLEN expected_len = (SvCUR(RETVAL) * sv_len) / (p - beg);
421 SvGROW(RETVAL, expected_len);
425 if (SvCUR(RETVAL) && eol_len && linelen) {
426 sv_catpvn(RETVAL, "=", 1);
427 sv_catpvn(RETVAL, eol, eol_len);
429 #if PERL_REVISION == 5 && PERL_VERSION >= 6
444 char *str = SvPVbyte(sv, len);
445 char const* end = str + len;
447 char *whitespace = 0;
450 RETVAL = newSV(len ? len : 1);
454 if (*str == ' ' || *str == '\t') {
459 else if (*str == '\r' && (str + 1) < end && str[1] == '\n') {
462 else if (*str == '\n') {
468 while (whitespace < str) {
469 *r++ = *whitespace++;
474 if ((str + 2) < end && isXDIGIT(str[1]) && isXDIGIT(str[2])) {
480 *r++ = (char)strtol(buf, 0, 16);
483 /* look for soft line break */
485 while (p < end && (*p == ' ' || *p == '\t'))
487 if (p < end && *p == '\n')
489 else if ((p + 1) < end && *p == '\r' && *(p + 1) == '\n')
492 *r++ = *str++; /* give up */
501 while (whitespace < str) {
502 *r++ = *whitespace++;
506 SvCUR_set(RETVAL, r - SvPVX(RETVAL));
512 MODULE = MIME::Base64 PACKAGE = MIME::Base64