-/* $Id: Base64.xs,v 1.36 2003/05/13 16:21:25 gisle Exp $
+/* $Id: Base64.xs,v 3.5 2005/11/26 10:44:14 gisle Exp $
-Copyright 1997-2003 Gisle Aas
+Copyright 1997-2004 Gisle Aas
This library is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
#ifdef __cplusplus
extern "C" {
#endif
+#define PERL_NO_GET_CONTEXT /* we want efficiency */
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#define MAX_LINE 76 /* size of encoded lines */
-static char basis_64[] =
+static const char basis_64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#define XX 255 /* illegal base64 char */
#define EQ 254 /* padding */
#define INVALID XX
-static unsigned char index_64[256] = {
+static const unsigned char index_64[256] = {
XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,62, XX,XX,XX,63,
# define SvPVbyte SvPV
#endif
+#ifndef isXDIGIT
+# define isXDIGIT isxdigit
+#endif
+
#ifndef NATIVE_TO_ASCII
# define NATIVE_TO_ASCII(ch) (ch)
#endif
chunk = 0;
}
c1 = *str++;
- c2 = *str++;
+ c2 = len > 1 ? *str++ : '\0';
*r++ = basis_64[c1>>2];
*r++ = basis_64[((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)];
if (len > 2) {
MODULE = MIME::Base64 PACKAGE = MIME::QuotedPrint
-#define qp_isplain(c) ((c) == '\t' || ((c) >= ' ' && (c) <= '~') && (c) != '=')
+#ifdef EBCDIC
+#define qp_isplain(c) ((c) == '\t' || ((!isprint(c) && (c) != '=')))
+#else
+#define qp_isplain(c) ((c) == '\t' || (((c) >= ' ' && (c) <= '~') && (c) != '='))
+#endif
SV*
encode_qp(sv,...)
SV* sv
- PROTOTYPE: $;$
+ PROTOTYPE: $;$$
PREINIT:
char *eol;
STRLEN eol_len;
+ int binary;
STRLEN sv_len;
STRLEN linelen;
char *beg;
eol_len = 1;
}
+ binary = (items > 2 && SvTRUE(ST(2)));
+
beg = SvPV(sv, sv_len);
end = beg + sv_len;
while (p < end && qp_isplain(*p)) {
p++;
}
- if (*p == '\n' || p == end) {
+ if (p == end || *p == '\n') {
/* whitespace at end of line must be encoded */
while (p > p_beg && (*(p - 1) == '\t' || *(p - 1) == ' '))
p--;
if (p_len) {
/* output plain text (with line breaks) */
if (eol_len) {
- STRLEN max_last_line = (*p == '\n' || p == end)
+ STRLEN max_last_line = (p == end || *p == '\n')
? MAX_LINE /* .......\n */
- : (*(p + 1) == '\n' || (p + 1) == end)
+ : ((p + 1) == end || *(p + 1) == '\n')
? MAX_LINE - 3 /* ....=XX\n */
: MAX_LINE - 4; /* ...=XX=\n */
while (p_len + linelen > max_last_line) {
}
}
- if (*p == '\n' && eol_len) {
+ if (p == end) {
+ break;
+ }
+ else if (*p == '\n' && eol_len && !binary) {
sv_catpvn(RETVAL, eol, eol_len);
p++;
linelen = 0;
}
- else if (p < end) {
+ else {
/* output escaped char (with line breaks) */
+ assert(p < end);
if (eol_len && linelen > MAX_LINE - 4) {
sv_catpvn(RETVAL, "=", 1);
sv_catpvn(RETVAL, eol, eol_len);
p++;
linelen += 3;
}
- else {
- assert(p == end);
- break;
- }
/* optimize reallocs a bit */
if (SvLEN(RETVAL) > 80 && SvLEN(RETVAL) - SvCUR(RETVAL) < 3) {
}
}
+ if (SvCUR(RETVAL) && eol_len && linelen) {
+ sv_catpvn(RETVAL, "=", 1);
+ sv_catpvn(RETVAL, eol, eol_len);
+ }
+
OUTPUT:
RETVAL
}
whitespace = 0;
}
- if (*str == '=' && (str + 2) < end && isxdigit(str[1]) && isxdigit(str[2])) {
- char buf[3];
- str++;
- buf[0] = *str++;
- buf[1] = *str++;
- buf[2] = '\0';
- *r++ = (char)strtol(buf, 0, 16);
- }
- else if (*str == '=' && (str + 1) < end && str[1] == '\n') {
- str += 2;
+ if (*str == '=') {
+ if ((str + 2) < end && isXDIGIT(str[1]) && isXDIGIT(str[2])) {
+ char buf[3];
+ str++;
+ buf[0] = *str++;
+ buf[1] = *str++;
+ buf[2] = '\0';
+ *r++ = (char)strtol(buf, 0, 16);
+ }
+ else {
+ /* look for soft line break */
+ char *p = str + 1;
+ while (p < end && (*p == ' ' || *p == '\t'))
+ p++;
+ if (p < end && *p == '\n')
+ str = p + 1;
+ else if ((p + 1) < end && *p == '\r' && *(p + 1) == '\n')
+ str = p + 2;
+ else
+ *r++ = *str++; /* give up */
+ }
}
- else if (*str == '=' && (str + 2) < end && str[1] == '\r' && str[2] == '\n') {
- str += 3;
+ else {
+ *r++ = *str++;
}
- else {
- *r++ = *str++;
- }
}
}
if (whitespace) {