and I'm not sure why yet.
int what_now (char *, int, int, char *, char *,
int, struct msgs *, char *, int, char *, int);
int WhatNow(int, char **);
-int writeBase64aux(FILE *, FILE *);
+
+/*
+ * Copy data from one file to another, converting to base64-encoding.
+ *
+ * Arguments include:
+ *
+ * in - Input filehandle (unencoded data)
+ * out - Output filename (base64-encoded data)
+ * crlf - If set, output encoded CRLF for every LF on input.
+ *
+ * Returns OK on success, NOTOK otherwise.
+ */
+int writeBase64aux(FILE *in, FILE *out, int crlf);
+
int writeBase64 (unsigned char *, size_t, unsigned char *);
int writeBase64raw (unsigned char *, size_t, unsigned char *);
"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];
n = BPERLIN;
while ((cc = fread (inbuf, sizeof(*inbuf), sizeof(inbuf), in)) > 0) {
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') {
+ 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) {
+ ungetc('\n', in);
+ } 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';
+ }
+ }
+ }
+ }
+
bits = (inbuf[0] & 0xff) << 16;
bits |= (inbuf[1] & 0xff) << 8;
bits |= inbuf[2] & 0xff;
if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
return NOTOK;
- result = writeBase64aux (ce->ce_fp, out);
+ result = writeBase64aux (ce->ce_fp, out, (ct->c_type == CT_TEXT));
(*ct->c_ceclosefnx) (ct);
return result;
}
openBase64 (CT ct, char **file)
{
int bitno, cc, digested;
- int fd, len, skip, own_ct_fp = 0;
+ int fd, len, skip, own_ct_fp = 0, text = ct->c_type == CT_TEXT;
uint32_t bits;
unsigned char value, b;
char *cp, *ep, buffer[BUFSIZ];
test_end:
if ((bitno -= 6) < 0) {
b = (bits >> 16) & 0xff;
- putc ((char) b, ce->ce_fp);
+ if (!text || b != '\r')
+ putc ((char) b, ce->ce_fp);
if (digested)
MD5Update (&mdContext, &b, 1);
if (skip < 2) {
b = (bits >> 8) & 0xff;
- putc ((char) b, ce->ce_fp);
+ if (! text || b != '\r')
+ putc ((char) b, ce->ce_fp);
if (digested)
MD5Update (&mdContext, &b, 1);
if (skip < 1) {
b = bits & 0xff;
- putc ((char) b, ce->ce_fp);
+ if (! text || b != '\r')
+ putc ((char) b, ce->ce_fp);
if (digested)
MD5Update (&mdContext, &b, 1);
}
if (fflush (fp))
adios (tmpfil, "error writing to");
- writeBase64aux (stdin, fp);
+ writeBase64aux (stdin, fp, 0);
if (fflush (fp))
adios (tmpfil, "error writing to");