From: markus schnalke Date: Wed, 21 Oct 2015 15:35:14 +0000 (+0200) Subject: Coding style adjustments for nmh-imported code X-Git-Tag: mmh-0.2-RC1~14^2~1 X-Git-Url: http://git.marmaro.de/?a=commitdiff_plain;h=5d690daafbcd4ed26d19610fcc017999ee5af892;p=mmh Coding style adjustments for nmh-imported code - No documentation in h/prototypes.h, but rather in the sbr/*.c files - Convert coding style from nmh to mmh: + indent with tabs only not with a tab-spaces-mixture + no space between function name and opening parenthesis + no space on the inner side of parens + no trailing space + different comment style - Variable definition at the beginning of the block only (ANSI C) - Choose meaningful identifier name rather than add a comment to a meaningless name --- diff --git a/h/prototypes.h b/h/prototypes.h index e6e7dc1..8575b22 100644 --- a/h/prototypes.h +++ b/h/prototypes.h @@ -39,6 +39,7 @@ void cpydata(int, int, char *, char *); void cpydgst(int, int, char *, char *); int decode_rfc2047(char *, char *, size_t); int default_done(int); +int encode_rfc2047(const char *name, char **value, const char *charset); int execprog(char *, char **); int execprogl(char *, char *, ...); char *expandfol(char *); @@ -73,6 +74,7 @@ char *m_mktemp(const char *, int *, FILE **); char *m_mktemp2(const char *, const char *, int *, FILE **); void thisisanmbox(FILE *); int makedir(char *); +int mh_strcasecmp(const char *s1, const char *s2); char *norm_charmap(char *); char *new_fs(char *, char *); int pidwait(pid_t, int); @@ -108,28 +110,12 @@ char *toabsdir(char *); char *trim(unsigned char *); char *trimcpy(unsigned char *); int unputenv(char *); +void unquote_string(const char *input, char *output); int uprf(char *, char *); int vfgets(FILE *, char **); char *write_charset_8bit(void); -/* - * Remove quotes and quoted-pair sequences from RFC-5322 atoms. - * - * Currently the actual algorithm is simpler than it technically should - * be: any quotes are simply eaten, unless they're preceded by the escape - * character (\). This seems to be sufficient for our needs for now. - * - * Arguments: - * - * input - The input string - * output - The output string; is assumed to have at least as much - * room as the input string. At worst the output string will - * be the same size as the input string; it might be smaller. - * - */ -void unquote_string(const char *input, char *output); -int mh_strcasecmp(const char *s1, const char *s2); /* @@ -178,19 +164,3 @@ void set_readonly(struct msgs *); int other_files(struct msgs *); void set_other_files(struct msgs *); -/* - * Encode a message header using RFC 2047 encoding. If the message contains - * no non-ASCII characters, then leave the header as-is. - * - * Arguments include: - * - * name - Message header name - * value - Message header content; must point to allocated memory - * (may be changed if encoding is necessary) - * charset - Charset used for encoding. If NULL, obtain from system - * locale. - * - * Returns 0 on success, any other value on failure. - */ - -int encode_rfc2047(const char *name, char **value, const char *charset); diff --git a/sbr/encode_rfc2047.c b/sbr/encode_rfc2047.c index b4027d8..852c261 100644 --- a/sbr/encode_rfc2047.c +++ b/sbr/encode_rfc2047.c @@ -1,10 +1,10 @@ /* - * Routines to encode message headers using RFC 2047-encoding. - * - * This code is Copyright (c) 2002, by the authors of nmh. See the - * COPYRIGHT file in the root directory of the nmh distribution for - * complete copyright information. - */ +** Routines to encode message headers using RFC 2047-encoding. +** +** This code is Copyright (c) 2002, by the authors of nmh. See the +** COPYRIGHT file in the root directory of the nmh distribution for +** complete copyright information. +*/ #include #include @@ -14,107 +14,110 @@ #include /* - * List of headers that contain addresses and as a result require special - * handling - */ +** List of headers that contain addresses and as a result require special +** handling +*/ static char *address_headers[] = { - "To", - "From", - "cc", - "Bcc", - "Reply-To", - "Sender", - "Resent-To", - "Resent-From", - "Resent-cc", - "Resent-Bcc", - "Resent-Reply-To", - "Resent-Sender", - NULL, + "To", + "From", + "cc", + "Bcc", + "Reply-To", + "Sender", + "Resent-To", + "Resent-From", + "Resent-cc", + "Resent-Bcc", + "Resent-Reply-To", + "Resent-Sender", + NULL, }; /* - * Macros we use for parsing headers - */ +** Macros we use for parsing headers +** +** Todo: convert the macros to functions +*/ #define is_fws(c) (c == '\t' || c == ' ' || c == '\n') #define qphrasevalid(c) ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || \ - (c >= 'a' && c <= 'z') || \ - c == '!' || c == '*' || c == '+' || c == '-' || \ - c == '/' || c == '=' || c == '_') + (c >= 'a' && c <= 'z') || \ + c == '!' || c == '*' || c == '+' || c == '-' || \ + c == '/' || c == '=' || c == '_') #define qpspecial(c) (c < ' ' || c == '=' || c == '?' || c == '_') -#define base64len(n) ((((n) + 2) / 3 ) * 4) /* String len to base64 len */ -#define strbase64(n) ((n) / 4 * 3) /* Chars that fit in base64 */ +#define base64len(n) ((((n) + 2) / 3) * 4) /* String len to base64 len */ +#define strbase64(n) ((n) / 4 * 3) /* Chars that fit in base64 */ #define ENCODELINELIMIT 76 static void unfold_header(char **, int); static int field_encode_address(const char *, char **, const char *); static int field_encode_quoted(const char *, char **, const char *, int, - int, int); + int, int); static int scanstring(const char *, int *, int *, int *); static int utf8len(const char *); /*static int pref_encoding(int, int, int);*/ /* - * Encode a message header using RFC 2047 encoding. We make the assumption - * that all characters < 128 are ASCII and as a consequence don't need any - * encoding. - */ - +** Encode a message header using RFC 2047 encoding. We make the assumption +** that all characters < 128 are ASCII and as a consequence don't need any +** encoding. +*/ int encode_rfc2047(const char *name, char **value, const char *charset) { - int i, asciicount = 0, eightbitcount = 0, qpspecialcount = 0; - char *p; - - /* - * First, check to see if we even need to encode the header - */ - - for (p = *value; *p != '\0'; p++) { - if (isascii((unsigned char) *p)) { - asciicount++; - if (qpspecial((unsigned char) *p)) - qpspecialcount++; - } else - eightbitcount++; - } - - if (eightbitcount == 0) - return 0; - - /* - * Some rules from RFC 2047: - * - * - Encoded words cannot be more than 75 characters long - * - Multiple "long" encoded words must be on new lines. - * - * Also, we're not permitted to encode email addresses, so - * we need to actually _parse_ email addresses and only encode - * the right bits. - */ - - /* - * If charset was NULL, then get the value from the locale. But - * we reject it if it returns US-ASCII - */ - - if (charset == NULL) - charset = write_charset_8bit(); + int i, asciicount = 0, eightbitcount = 0, qpspecialcount = 0; + char *p; + + /* First, check to see if we even need to encode the header */ + + for (p = *value; *p != '\0'; p++) { + if (isascii((unsigned char) *p)) { + asciicount++; + if (qpspecial((unsigned char) *p)) { + qpspecialcount++; + } + } else { + eightbitcount++; + } + } + + if (eightbitcount == 0) { + return 0; + } + /* + ** Some rules from RFC 2047: + ** + ** - Encoded words cannot be more than 75 characters long + ** - Multiple "long" encoded words must be on new lines. + ** + ** Also, we're not permitted to encode email addresses, so + ** we need to actually _parse_ email addresses and only encode + ** the right bits. + */ + + /* + ** If charset was NULL, then get the value from the locale. But + ** we reject it if it returns US-ASCII + */ + + if (charset == NULL) { + charset = write_charset_8bit(); + } if (strcasecmp(charset, "US-ASCII") == 0) { advise(NULL, "Cannot use US-ASCII with 8 bit characters in header"); return 1; } - /* - * If we have an address header, then we need to parse the addresses - * and only encode the names or comments. Otherwise, handle it normally. - */ + /* + ** If we have an address header, then we need to parse the addresses + ** and only encode the names or comments. Otherwise, handle it + ** normally. + */ for (i = 0; address_headers[i]; i++) { if (strcasecmp(name, address_headers[i]) == 0) { @@ -122,525 +125,548 @@ encode_rfc2047(const char *name, char **value, const char *charset) } } - /* - * On the encoding we choose, and the specifics of encoding: - * - * - If a specified encoding is passed in, we use that. - * - Otherwise, pick which encoding is shorter. - * - * We don't quite handle continuation right here, but it should be - * pretty close. - */ + /* + ** On the encoding we choose, and the specifics of encoding: + ** + ** - If a specified encoding is passed in, we use that. + ** - Otherwise, pick which encoding is shorter. + ** + ** We don't quite handle continuation right here, but it should be + ** pretty close. + */ - unfold_header(value, asciicount + eightbitcount); + unfold_header(value, asciicount + eightbitcount); return field_encode_quoted(name, value, charset, asciicount, - eightbitcount + qpspecialcount, 0); + eightbitcount + qpspecialcount, 0); } /* - * Encode our specified header (or field) using quoted-printable - */ +** Encode our specified header (or field) using quoted-printable +*/ static int field_encode_quoted(const char *name, char **value, const char *charset, - int ascii, int encoded, int phraserules) + int ascii, int encoded, int phraserules) { - int prefixlen = name ? strlen(name) + 2: 0, outlen = 0, column, newline = 1; - int charsetlen = strlen(charset), utf8; - char *output = NULL, *p, *q = NULL; - - /* - * Right now we just encode the whole thing. Maybe later on we'll - * only encode things on a per-atom basis. - */ - - p = *value; - - column = prefixlen + 2; /* Header name plus ": " */ - - utf8 = strcasecmp(charset, "UTF-8") == 0; - - while (*p != '\0') { - /* - * Start a new line, if it's time - */ - if (newline) { - /* - * If it's the start of the header, we don't need to pad it - * - * The length of the output string is ... - * =?charset?Q?...?= so that's 7+strlen(charset) + 2 for \n NUL - * - * plus 1 for every ASCII character and 3 for every eight bit - * or special character (eight bit characters are written as =XX). - * - */ - - int tokenlen; - - outlen += 9 + charsetlen + ascii + 3 * encoded; - - /* - * If output is set, then we're continuing the header. Otherwise - * do the initial allocation. - */ - - if (output) { - int curlen = q - output, i; - outlen += prefixlen + 1; /* Header plus \n ": " */ - output = mh_xrealloc(output, outlen); - q = output + curlen; - *q++ = '?'; - *q++ = '='; - *q++ = '\n'; - for (i = 0; i < prefixlen; i++) - *q++ = ' '; - } else { - /* - * A bit of a hack here; the header can contain multiple - * spaces (probably at least one) until we get to the - * actual text. Copy until we get to a non-space. - */ - output = mh_xmalloc(outlen); - q = output; - while (is_fws(*p)) - *q++ = *p++; - } - - tokenlen = snprintf(q, outlen - (q - output), "=?%s?Q?", charset); - q += tokenlen; - column = prefixlen + tokenlen; - newline = 0; - } + int prefixlen = name ? strlen(name) + 2: 0; + int outlen = 0, column, newline = 1, utf8; + int charsetlen = strlen(charset); + char *output = NULL, *p, *q = NULL; /* - * Process each character, encoding if necessary - * - * Note that we have a different set of rules if we're processing - * RFC 5322 'phrase' (something you'd see in an address header). - */ - - column++; - - if (*p == ' ') { - *q++ = '_'; - ascii--; - } else if (isascii((unsigned char) *p) && - (phraserules ? qphrasevalid((unsigned char) *p) : - !qpspecial((unsigned char) *p))) { - *q++ = *p; - ascii--; - } else { - snprintf(q, outlen - (q - output), "=%02X", (unsigned char) *p); - q += 3; - column += 2; /* column already incremented by 1 above */ - encoded--; - } - - p++; + ** Right now we just encode the whole thing. Maybe later on we'll + ** only encode things on a per-atom basis. + */ + + p = *value; + + column = prefixlen + 2; /* Header name plus ": " */ + + utf8 = strcasecmp(charset, "UTF-8") == 0; + + while (*p != '\0') { + /* Start a new line, if it's time */ + if (newline) { + int tokenlen; + + /* + ** If it's the start of the header, we don't need + ** to pad it + ** + ** The length of the output string is ... + ** =?charset?Q?...?= so that's + ** 7+strlen(charset) + 2 for \n NUL + ** + ** plus 1 for every ASCII character and 3 for + ** every eight bit or special character (eight + ** bit characters are written as =XX). + */ + outlen += 9 + charsetlen + ascii + 3 * encoded; + + if (output) { + /* continue the header */ + int curlen = q - output, i; + outlen += prefixlen + 1; /* Header plus \n ": " */ + output = mh_xrealloc(output, outlen); + q = output + curlen; + *q++ = '?'; + *q++ = '='; + *q++ = '\n'; + for (i = 0; i < prefixlen; i++) { + *q++ = ' '; + } + } else { + /* do the initial allocation */ + /* + ** A bit of a hack here; the header can + ** contain multiple spaces (probably at + ** least one) until we get to the actual + ** text. Copy until we get to a non-space. + */ + output = mh_xmalloc(outlen); + q = output; + while (is_fws(*p)) { + *q++ = *p++; + } + } + + tokenlen = snprintf(q, outlen - (q - output), + "=?%s?Q?", charset); + q += tokenlen; + column = prefixlen + tokenlen; + newline = 0; + } - /* - * We're not allowed more than ENCODELINELIMIT characters per line, - * so reserve some room for the final ?=. - * - * If prefixlen == 0, we haven't been passed in a header name, so - * don't ever wrap the field (we're likely doing an address). - */ - - if (prefixlen == 0) - continue; - - if (column >= ENCODELINELIMIT - 2) { - newline = 1; - } else if (utf8) { - /* - * Okay, this is a bit weird, but to explain a bit more ... - * - * RFC 2047 prohibits the splitting of multibyte characters - * across encoded words. Right now we only handle the case - * of UTF-8, the most common multibyte encoding. - * - * p is now pointing at the next input character. If we're - * using UTF-8 _and_ we'd go over ENCODELINELIMIT given the - * length of the complete character, then trigger a newline - * now. Note that we check the length * 3 since we have to - * allow for the encoded output. - */ - if (column + (utf8len(p) * 3) > ENCODELINELIMIT - 2) { - newline = 1; - } - } - } + /* + ** Process each character, encoding if necessary + ** + ** Note that we have a different set of rules if we're + ** processing RFC 5322 'phrase' (something you'd see in + ** an address header). + */ + + column++; + + if (*p == ' ') { + *q++ = '_'; + ascii--; + } else if (isascii((unsigned char) *p) && (phraserules ? + qphrasevalid((unsigned char) *p) + : !qpspecial((unsigned char) *p))) { + *q++ = *p; + ascii--; + } else { + snprintf(q, outlen - (q - output), "=%02X", + (unsigned char) *p); + q += 3; + column += 2; /* column already incremented by 1 above */ + encoded--; + } - if (q == NULL) { - /* This should never happen, but just in case. Found by - clang static analyzer. */ - admonish (NULL, "null output encoding for %s", *value); - return 1; - } - *q++ = '?'; - *q++ = '='; + p++; - if (prefixlen) - *q++ = '\n'; + if (prefixlen == 0) { + /* + ** We haven't been passed in a header name, + ** so don't ever wrap the field (we're likely + ** doing an address). + */ + continue; + } + /* + ** We're not allowed more than ENCODELINELIMIT characters + ** per line, so reserve some room for the final ?=. + */ + if (column >= ENCODELINELIMIT - 2) { + newline = 1; + } else if (utf8) { + /* + ** Okay, this is a bit weird, but to explain a + ** bit more ... + ** + ** RFC 2047 prohibits the splitting of multibyte + ** characters across encoded words. Right now + ** we only handle the case of UTF-8, the most + ** common multibyte encoding. + ** + ** p is now pointing at the next input character. + ** If we're using UTF-8 _and_ we'd go over + ** ENCODELINELIMIT given the length of the + ** complete character, then trigger a newline now. + ** Note that we check the length * 3 since we + ** have to allow for the encoded output. + */ + if (column + (utf8len(p)*3) > ENCODELINELIMIT - 2) { + newline = 1; + } + } + } - *q = '\0'; + if (q == NULL) { + /* + ** This should never happen, but just in case. + ** Found by clang static analyzer. + */ + admonish (NULL, "null output encoding for %s", *value); + return 1; + } + *q++ = '?'; + *q++ = '='; - free(*value); + if (prefixlen) { + *q++ = '\n'; + } + *q = '\0'; - *value = output; + free(*value); + *value = output; - return 0; + return 0; } /* - * Calculate the length of a UTF-8 character. - * - * If it's not a UTF-8 character (or we're in the middle of a multibyte - * character) then simply return 0. - */ - +** Calculate the length of a UTF-8 character. +** +** If it's not a UTF-8 character (or we're in the middle of a multibyte +** character) then simply return 0. +*/ static int utf8len(const char *p) { - int len = 1; - - if (*p == '\0') - return 0; + int len = 1; - if (isascii((unsigned char) *p) || (((unsigned char) *p) & 0xc0) == 0x80) - return 0; - - p++; - while ((((unsigned char) *p++) & 0xc0) == 0x80) - len++; + if (*p == '\0') { + return 0; + } + if (isascii((unsigned char) *p) || + (((unsigned char) *p) & 0xc0) == 0x80) { + return 0; + } + p++; + while ((((unsigned char) *p++) & 0xc0) == 0x80) { + len++; + } - return len; + return len; } /* - * "Unfold" a header, making it a single line (without continuation) - * - * We cheat a bit here; we never make the string longer, so using the - * original length here is fine. - */ - +** "Unfold" a header, making it a single line (without continuation) +** +** We cheat a bit here; we never make the string longer, so using the +** original length here is fine. +*/ static void unfold_header(char **value, int len) { - char *str = mh_xmalloc(len + 1); - char *p = str, *q = *value; - - while (*q != '\0') { - if (*q == '\n') { - /* - * When we get a newline, skip to the next non-whitespace - * character and add a space to replace all of the whitespace - * - * This has the side effect of stripping off the final newline - * for the header; we put it back in the encoding routine. - */ - while (is_fws(*q)) - q++; - if (*q == '\0') - break; - - *p++ = ' '; - } else { - *p++ = *q++; + char *str = mh_xmalloc(len + 1); + char *p = str, *q = *value; + + while (*q != '\0') { + if (*q == '\n') { + /* + ** When we get a newline, skip to the next + ** non-whitespace character and add a space to + ** replace all of the whitespace + ** + ** This has the side effect of stripping off the + ** final newline for the header; we put it back + ** in the encoding routine. + */ + while (is_fws(*q)) { + q++; + } + if (*q == '\0') { + break; + } + *p++ = ' '; + } else { + *p++ = *q++; + } } - } - - *p = '\0'; + *p = '\0'; - free(*value); - *value = str; + free(*value); + *value = str; } /* - * Decode a header containing addresses. This means we have to parse - * each address and only encode the display-name or comment field. - */ - +** Decode a header containing addresses. This means we have to parse +** each address and only encode the display-name or comment field. +*/ static int field_encode_address(const char *name, char **value, const char *charset) { - int prefixlen = strlen(name) + 2, column = prefixlen, groupflag; - int asciichars, specialchars, eightbitchars, reformat = 0, errflag = 0; - size_t len; - char *mp, *cp = NULL, *output = NULL; - char *tmpbuf = NULL; - size_t tmpbufsize = 0; - struct mailname *mn; - char errbuf[BUFSIZ]; - - /* - * Because these are addresses, we need to handle them individually. - * - * Break them down and process them one by one. This means we have to - * rewrite the whole header, but that's unavoidable. - */ - - /* - * The output headers always have to start with a space first; this - * is just the way the API works right now. - */ - - output = add(" ", output); - - for (groupflag = 0; (mp = getname(*value)); ) { - if ((mn = getm(mp, NULL, 0, AD_HOST, errbuf)) == NULL) { - advise(NULL, "%s: %s", errbuf, mp); - errflag++; - continue; - } + int prefixlen = strlen(name) + 2; + int column = prefixlen, groupflag; + int asciichars, specialchars, eightbitchars; + int reformat = 0, errflag = 0; + size_t len; + char *mp, *cp = NULL, *output = NULL; + char *tmpbuf = NULL; + size_t tmpbufsize = 0; + struct mailname *mn; + char errbuf[BUFSIZ]; - reformat = 0; + /* + ** Because these are addresses, we need to handle them individually. + ** + ** Break them down and process them one by one. This means we + ** have to rewrite the whole header, but that's unavoidable. + */ /* - * We only care if the phrase (m_pers) or any trailing comment - * (m_note) have 8-bit characters. If doing q-p, we also need - * to encode anything marked as qspecial(). Unquote it first - * so the specialchars count is right. - */ + ** The output headers always have to start with a space first; + ** this is just the way the API works right now. + */ - if (! mn->m_pers) - goto check_note; + output = add(" ", output); - if ((len = strlen(mn->m_pers)) + 1 > tmpbufsize) { - tmpbuf = mh_xrealloc(tmpbuf, tmpbufsize = len + 1); - } + for (groupflag = 0; (mp = getname(*value)); ) { + if ((mn = getm(mp, NULL, 0, AD_HOST, errbuf)) == NULL) { + advise(NULL, "%s: %s", errbuf, mp); + errflag++; + continue; + } - unquote_string(mn->m_pers, tmpbuf); + reformat = 0; - if (scanstring(tmpbuf, &asciichars, &eightbitchars, - &specialchars)) { - /* - * If we have 8-bit characters, encode it. - */ + /* + ** We only care if the phrase (m_pers) or any trailing + ** comment (m_note) have 8-bit characters. If doing q-p, + ** we also need to encode anything marked as qspecial(). + ** Unquote it first so the specialchars count is right. + */ - /* - * This is okay, because the output of unquote_string will be either - * equal or shorter than the original. - */ + if (! mn->m_pers) { + goto check_note; + } + + if ((len = strlen(mn->m_pers)) + 1 > tmpbufsize) { + tmpbuf = mh_xrealloc(tmpbuf, tmpbufsize = len + 1); + } - strcpy(mn->m_pers, tmpbuf); + unquote_string(mn->m_pers, tmpbuf); - if (field_encode_quoted(NULL, &mn->m_pers, charset, asciichars, + if (scanstring(tmpbuf, &asciichars, &eightbitchars, + &specialchars)) { + /* + ** If we have 8-bit characters, encode it. + */ + + /* + ** This is okay, because the output of + ** unquote_string will be either equal or shorter + ** than the original. + */ + strcpy(mn->m_pers, tmpbuf); + + if (field_encode_quoted(NULL, &mn->m_pers, charset, + asciichars, eightbitchars + specialchars, 1)) { - errflag++; - goto out; + errflag++; + goto out; + } + + reformat++; } - reformat++; - } + check_note: - check_note: + /* + ** The "note" field is generally a comment at the end + ** of the address, at least as how it's implemented here. + ** Notes are always surrounded by parenthesis (since they're + ** comments). Strip them out and then put them back when + ** we format the final field, but they do not get encoded. + */ - /* - * The "note" field is generally a comment at the end of the address, - * at least as how it's implemented here. Notes are always surrounded - * by parenthesis (since they're comments). Strip them out and - * then put them back when we format the final field, but they do - * not get encoded. - */ - - if (! mn->m_note) - goto do_reformat; - - if ((len = strlen(mn->m_note)) + 1 > tmpbufsize) { - tmpbuf = mh_xrealloc(tmpbuf, tmpbufsize = len + 1); - } + if (! mn->m_note) { + goto do_reformat; + } - if (mn->m_note[0] != '(' || mn->m_note[len - 1] != ')') { - advise(NULL, "Internal error: Invalid note field \"%s\"", - mn->m_note); - errflag++; - goto out; - } + if ((len = strlen(mn->m_note)) + 1 > tmpbufsize) { + tmpbuf = mh_xrealloc(tmpbuf, tmpbufsize = len + 1); + } + + if (mn->m_note[0] != '(' || mn->m_note[len - 1] != ')') { + advise(NULL, "Internal error: Invalid note field \"%s\"", + mn->m_note); + errflag++; + goto out; + } - strncpy(tmpbuf, mn->m_note + 1, len - 1); - tmpbuf[len - 2] = '\0'; + strncpy(tmpbuf, mn->m_note + 1, len - 1); + tmpbuf[len - 2] = '\0'; - if (scanstring(tmpbuf, &asciichars, &eightbitchars, - &specialchars)) { - /* - * If we have 8-bit characters, encode it. - */ + if (scanstring(tmpbuf, &asciichars, &eightbitchars, + &specialchars)) { + /* + ** If we have 8-bit characters, encode it. + */ - if (field_encode_quoted(NULL, &tmpbuf, charset, asciichars, + if (field_encode_quoted(NULL, &tmpbuf, charset, + asciichars, eightbitchars + specialchars, 1)) { - errflag++; - goto out; - } + errflag++; + goto out; + } - reformat++; + reformat++; - /* - * Make sure the size of tmpbuf is correct (it always gets - * reallocated in the above functions). - */ + /* + ** Make sure the size of tmpbuf is correct (it + ** always gets reallocated in the above functions). + */ - tmpbufsize = strlen(tmpbuf) + 1; + tmpbufsize = strlen(tmpbuf) + 1; - /* - * Put the note field back surrounded by parenthesis. - */ + /* + ** Put the note field back surrounded by + ** parenthesis. + */ - mn->m_note = mh_xrealloc(mn->m_note, tmpbufsize + 2); + mn->m_note = mh_xrealloc(mn->m_note, tmpbufsize + 2); - snprintf(mn->m_note, tmpbufsize + 2, "(%s)", tmpbuf); - } + snprintf(mn->m_note, tmpbufsize + 2, "(%s)", tmpbuf); + } do_reformat: - /* - * So, some explanation is in order. - * - * We know we need to rewrite at least one address in the header, - * otherwise we wouldn't be here. If we had to reformat this - * particular address, then run it through adrformat(). Otherwise - * we can use m_text directly. - */ + /* + ** So, some explanation is in order. + ** + ** We know we need to rewrite at least one address in the + ** header, otherwise we wouldn't be here. If we had to + ** reformat this particular address, then run it through + ** adrformat(). Otherwise we can use m_text directly. + */ + + /* + ** If we were in a group but are no longer, make sure we + ** add a semicolon (which needs to be FIRST, as it needs + ** to be at the end of the last address). + */ + + if (groupflag && ! mn->m_ingrp) { + output = add(";", output); + column += 1; + } - /* - * If we were in a group but are no longer, make sure we add a - * semicolon (which needs to be FIRST, as it needs to be at the end - * of the last address). - */ - - if (groupflag && ! mn->m_ingrp) { - output = add(";", output); - column += 1; - } + groupflag = mn->m_ingrp; - groupflag = mn->m_ingrp; + if (mn->m_gname) { + cp = add(mn->m_gname, NULL); + } - if (mn->m_gname) { - cp = add(mn->m_gname, NULL); - } + if (reformat) { + cp = add(adrformat(mn), cp); + } else { + cp = add(mn->m_text, cp); + } - if (reformat) { - cp = add(adrformat(mn), cp); - } else { - cp = add(mn->m_text, cp); - } + len = strlen(cp); - len = strlen(cp); + /* + ** If we're not at the beginning of the line, add a + ** command and either a space or a newline. + */ - /* - * If we're not at the beginning of the line, add a command and - * either a space or a newline. - */ - - if (column != prefixlen) { - if (len + column + 2 > OUTPUTLINELEN) { - - if ((size_t) (prefixlen + 3) < tmpbufsize) - tmpbuf = mh_xrealloc(tmpbuf, tmpbufsize = prefixlen + 3); - - snprintf(tmpbuf, tmpbufsize, ",\n%*s", column = prefixlen, ""); - output = add(tmpbuf, output); - } else { - output = add(", ", output); - column += 2; - } - } + if (column != prefixlen) { + if (len + column + 2 > OUTPUTLINELEN) { - /* - * Finally add the address - */ + if ((size_t) (prefixlen + 3) < tmpbufsize) { + tmpbuf = mh_xrealloc(tmpbuf, tmpbufsize = prefixlen + 3); + } + + snprintf(tmpbuf, tmpbufsize, ",\n%*s", column = prefixlen, ""); + output = add(tmpbuf, output); + } else { + output = add(", ", output); + column += 2; + } + } - output = add(cp, output); - column += len; - free(cp); - cp = NULL; - } + /* + ** Finally add the address + */ - /* - * Just in case we're at the end of a list - */ + output = add(cp, output); + column += len; + free(cp); + cp = NULL; + } - if (groupflag) { - output = add(";", output); - } + /* + ** Just in case we're at the end of a list + */ - output = add("\n", output); + if (groupflag) { + output = add(";", output); + } - free(*value); - *value = output; - output = NULL; + output = add("\n", output); + + free(*value); + *value = output; + output = NULL; out: - if (tmpbuf) - free(tmpbuf); - if (output) - free(output); + if (tmpbuf) { + free(tmpbuf); + } + if (output) { + free(output); + } - return errflag > 0; + return errflag > 0; } /* - * Scan a string, check for characters that need to be encoded - */ +** Scan a string, check for characters that need to be encoded +*/ static int scanstring(const char *string, int *asciilen, int *eightbitchars, - int *specialchars) + int *specialchars) { - *asciilen = 0; - *eightbitchars = 0; - *specialchars = 0; - - for (; *string != '\0'; string++) { - if ((isascii((unsigned char) *string))) { - (*asciilen)++; - /* - * So, a space is not a valid phrase character, but we're counting - * an exception here, because in q-p a space can be directly - * encoded as an underscore. - */ - if (!qphrasevalid((unsigned char) *string) && *string != ' ') - (*specialchars)++; - } else { - (*eightbitchars)++; + *asciilen = 0; + *eightbitchars = 0; + *specialchars = 0; + + for (; *string != '\0'; string++) { + if ((isascii((unsigned char) *string))) { + (*asciilen)++; + /* + ** So, a space is not a valid phrase character, but + ** we're counting an exception here, because in q-p + ** a space can be directly encoded as an underscore. + */ + if (!qphrasevalid((unsigned char) *string) && + *string != ' ') { + (*specialchars)++; + } + } else { + (*eightbitchars)++; + } } - } - return *eightbitchars > 0; + return *eightbitchars > 0; } +#if 0 + /* - * This function is to be used to decide which encoding algorithm we should - * use if one is not given. Basically, we pick whichever one is the shorter - * of the two. - * - * Arguments are: - * - * ascii - Number of ASCII characters in to-be-encoded string. - * specials - Number of ASCII characters in to-be-encoded string that - * still require encoding under quoted-printable. Note that - * these are included in the "ascii" total. - * eightbit - Eight-bit characters in the to-be-encoded string. - * - * Returns one of CE_BASE64 or CE_QUOTED. - */ -/* +** This function is to be used to decide which encoding algorithm we should +** use if one is not given. Basically, we pick whichever one is the shorter +** of the two. +** +** Arguments are: +** +** ascii - Number of ASCII characters in to-be-encoded string. +** specials - Number of ASCII characters in to-be-encoded string that +** still require encoding under quoted-printable. Note that +** these are included in the "ascii" total. +** eightbit - Eight-bit characters in the to-be-encoded string. +** +** Returns one of CE_BASE64 or CE_QUOTED. +**/ static int pref_encoding(int ascii, int specials, int eightbits) -{ */ - /* - * The length of the q-p encoding is: - * - * ascii - specials + (specials + eightbits) * 3. - * - * The length of the base64 encoding is: - * - * base64len(ascii + eightbits) (See macro for details) - */ -/* - return base64len(ascii + eightbits) < (ascii - specials + - (specials + eightbits) * 3) ? CE_BASE64 : CE_QUOTED; -}*/ +{ + /* + ** The length of the q-p encoding is: + ** + ** ascii - specials + (specials + eightbits) * 3. + ** + ** The length of the base64 encoding is: + ** + ** base64len(ascii + eightbits) (See macro for details) + */ + return base64len(ascii + eightbits) < (ascii - specials + + (specials + eightbits) * 3) ? CE_BASE64 : CE_QUOTED; +} + +#endif diff --git a/sbr/unquote.c b/sbr/unquote.c index f9fa911..aa40a0c 100644 --- a/sbr/unquote.c +++ b/sbr/unquote.c @@ -1,45 +1,48 @@ /* - * unquote.c: Handle quote removal and quoted-pair strings on - * RFC 2822-5322 atoms. - * - * This code is Copyright (c) 2013, by the authors of nmh. See the - * COPYRIGHT file in the root directory of the nmh distribution for - * complete copyright information. - */ +** unquote.c: Handle quote removal and quoted-pair strings on +** RFC 2822-5322 atoms. +** +** This code is Copyright (c) 2013, by the authors of nmh. See the +** COPYRIGHT file in the root directory of the nmh distribution for +** complete copyright information. +*/ #include /* - * Remove quotes (and handle escape strings) from RFC 5322 quoted-strings. - * - * Since we never add characters to the string, the output buffer is assumed - * to have at least as many characters as the input string. - * - */ - +** Remove quotes and quoted-pair sequences from RFC-5322 atoms. +** +** Currently the actual algorithm is simpler than it technically should +** be: any quotes are simply eaten, unless they're preceded by the escape +** character (\). This seems to be sufficient for our needs for now. +** +** Arguments: +** +** input - The input string +** output - The output string; is assumed to have at least as much +** room as the input string. At worst the output string will +** be the same size as the input string; it might be smaller. +*/ void unquote_string(const char *input, char *output) { - int n = 0; /* n is the position in the input buffer */ - int m = 0; /* m is the position in the output buffer */ + int inpos = 0; + int outpos = 0; - while ( input[n] != '\0') { - switch ( input[n] ) { - case '\\': - n++; - if ( input[n] != '\0') - output[m++] = input[n++]; - break; - case '"': - n++; - break; - default: - output[m++] = input[n++]; - break; + while (input[inpos] != '\0') { + switch (input[inpos]) { + case '\\': + inpos++; + if (input[inpos] != '\0') + output[outpos++] = input[inpos++]; + break; + case '"': + inpos++; + break; + default: + output[outpos++] = input[inpos++]; + break; + } } - } - - output[m] = '\0'; - - return; + output[outpos] = '\0'; } diff --git a/uip/mhbuild.c b/uip/mhbuild.c index d636cf7..1fdedb6 100644 --- a/uip/mhbuild.c +++ b/uip/mhbuild.c @@ -319,6 +319,7 @@ build_mime(char *infile) struct part **pp; CT ct; FILE *in; + HF hp; umask(~m_gmprot()); @@ -411,11 +412,9 @@ finish_field: } /* - * Iterate through the list of headers and call the function to MIME-ify - * them if required. - */ - - HF hp; + ** Iterate through the list of headers and call the function to + ** MIME-ify them if required. + */ for (hp = ct->c_first_hf; hp != NULL; hp = hp->next) { if (encode_rfc2047(hp->name, &hp->value, NULL)) { adios(EX_DATAERR, NULL, "Unable to encode header \"%s\"", hp->name); diff --git a/uip/pick.c b/uip/pick.c index 8448d96..8ae58a4 100644 --- a/uip/pick.c +++ b/uip/pick.c @@ -1017,15 +1017,17 @@ plist p1 = linebuf; p2 = n->n_expbuf; - /* Attempt to decode as a MIME header. If it's the last header, - * body will be 1 and lf will be at least 1. */ - if ((body == 0 || lf > 0) && - decode_rfc2047 (linebuf, decoded_linebuf, sizeof decoded_linebuf)) { - p1 = decoded_linebuf; + /* + ** Attempt to decode as a MIME header. If it's the + ** last header, body will be 1 and lf will be at least 1. + */ + if ((body == 0 || lf > 0) && decode_rfc2047(linebuf, + decoded_linebuf, sizeof decoded_linebuf)) { + p1 = decoded_linebuf; } if (n->n_circf) { - if (advance(p1, p2)) + if (advance(p1, p2)) return 1; continue; }