X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/9f8f8b1e1d553774865f2c177191c359c3dc652c..edccf71caebd3979a2eef7993624ccc7dbf0691a:/sbr/base64.c?ds=inline diff --git a/sbr/base64.c b/sbr/base64.c index c3045ab7..3a578c21 100644 --- a/sbr/base64.c +++ b/sbr/base64.c @@ -13,10 +13,11 @@ static char nib2b64[0x40+1] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; int -writeBase64aux (FILE *in, FILE *out) +writeBase64aux (FILE *in, FILE *out, int crlf) { unsigned int cc, n; - char inbuf[3]; + unsigned char inbuf[3]; + int skipnl = 0; n = BPERLIN; while ((cc = fread (inbuf, sizeof(*inbuf), sizeof(inbuf), in)) > 0) { @@ -29,6 +30,47 @@ writeBase64aux (FILE *in, FILE *out) if (cc < sizeof(inbuf) - 1) inbuf[1] = 0; } + + /* + * Convert a LF to a CRLF if desired. That means we need to push + * data back into the input stream. + */ + + if (crlf) { + unsigned int i; + + for (i = 0; i < cc; i++) { + if (inbuf[i] == '\n' && !skipnl) { + inbuf[i] = '\r'; + /* + * If it's the last character in the buffer, we can just + * substitute a \r and push a \n back. Otherwise shuffle + * everything down and push the last character back. + */ + if (i == cc - 1) { + /* + * If we're at the end of the input, there might be + * more room in inbuf; if so, add it there. Otherwise + * push it back to the input. + */ + if (cc < sizeof(inbuf)) + inbuf[cc++] = '\n'; + else + ungetc('\n', in); + skipnl = 1; + } else { + /* This only works as long as sizeof(inbuf) == 3 */ + ungetc(inbuf[cc - 1], in); + if (cc == 3 && i == 0) + inbuf[2] = inbuf[1]; + inbuf[++i] = '\n'; + } + } else { + skipnl = 0; + } + } + } + bits = (inbuf[0] & 0xff) << 16; bits |= (inbuf[1] & 0xff) << 8; bits |= inbuf[2] & 0xff; @@ -41,7 +83,10 @@ writeBase64aux (FILE *in, FILE *out) outbuf[2] = '='; } - fwrite (outbuf, sizeof(*outbuf), sizeof(outbuf), out); + if (fwrite (outbuf, sizeof(*outbuf), sizeof(outbuf), out) < + sizeof outbuf) { + advise ("writeBase64aux", "fwrite"); + } if (cc < sizeof(inbuf)) { putc ('\n', out); @@ -114,3 +159,49 @@ writeBase64 (unsigned char *in, size_t length, unsigned char *out) return OK; } + +/* + * Essentially a duplicate of writeBase64, but without line wrapping or + * newline termination (note: string IS NUL terminated) + */ + +int +writeBase64raw (unsigned char *in, size_t length, unsigned char *out) +{ + while (1) { + unsigned long bits; + unsigned char *bp; + unsigned int cc; + for (cc = 0, bp = in; length > 0 && cc < 3; ++cc, ++bp, --length) + /* empty */ ; + + if (cc == 0) { + break; + } else { + bits = (in[0] & 0xff) << 16; + if (cc > 1) { + bits |= (in[1] & 0xff) << 8; + if (cc > 2) { + bits |= in[2] & 0xff; + } + } + } + + for (bp = out + 4; bp > out; bits >>= 6) + *--bp = nib2b64[bits & 0x3f]; + if (cc < 3) { + out[3] = '='; + if (cc < 2) + out[2] = '='; + out += 4; + break; + } + + in += 3; + out += 4; + } + + *out = '\0'; + + return OK; +}