Example #1
0
char *
formataddr (char *orig, char *str)
{
    register int len;
    register int isgroup;
    register char *dst;
    register char *cp;
    register char *sp;
    register struct mailname *mp = NULL;

    /* if we don't have a buffer yet, get one */
    if (bufsiz == 0) {
	buf = mh_xmalloc (BUFINCR);
	last_dst = buf;		/* XXX */
	bufsiz = BUFINCR - 6;  /* leave some slop */
	bufend = buf + bufsiz;
    }
    /*
     * If "orig" points to our buffer we can just pick up where we
     * left off.  Otherwise we have to copy orig into our buffer.
     */
    if (orig == buf)
	dst = last_dst;
    else if (!orig || !*orig) {
	dst = buf;
	*dst = '\0';
    } else {
	dst = last_dst;		/* XXX */
	CHECKMEM (orig);
	CPY (orig);
    }

    /* concatenate all the new addresses onto 'buf' */
    for (isgroup = 0; (cp = getname (str)); ) {
	if ((mp = getm (cp, NULL, 0, fmt_norm, NULL)) == NULL)
	    continue;

	if (isgroup && (mp->m_gname || !mp->m_ingrp)) {
	    *dst++ = ';';
	    isgroup = 0;
	}
	/* if we get here we're going to add an address */
	if (dst != buf) {
	    *dst++ = ',';
	    *dst++ = ' ';
	}
	if (mp->m_gname) {
	    CHECKMEM (mp->m_gname);
	    CPY (mp->m_gname);
	    isgroup++;
	}
	sp = adrformat (mp);
	CHECKMEM (sp);
	CPY (sp);
	mnfree (mp);
    }

    if (isgroup)
	*dst++ = ';';

    *dst = '\0';
    last_dst = dst;
    return (buf);
}
Example #2
0
static int
field_encode_address(const char *name, char **value, int encoding,
		     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, errbuf, sizeof(errbuf))) == NULL) {
	    advise(NULL, "%s: %s", errbuf, mp);
	    errflag++;
	    continue;
	}

	reformat = 0;

	/*
	 * 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.
	 */

	if (! mn->m_pers)
	    goto check_note;

	if ((len = strlen(mn->m_pers)) + 1 > tmpbufsize) {
	    tmpbuf = mh_xrealloc(tmpbuf, tmpbufsize = len + 1);
	}

	unquote_string(mn->m_pers, tmpbuf);

	if (scanstring(tmpbuf, &asciichars, &eightbitchars,
		       &specialchars)) {
	    /*
	     * If we have 8-bit characters, encode it.
	     */

	    if (encoding == CE_UNKNOWN)
	    	encoding = pref_encoding(asciichars, specialchars,
					 eightbitchars);

	    /*
	     * This is okay, because the output of unquote_string will be either
	     * equal or shorter than the original.
	     */

	    strcpy(mn->m_pers, tmpbuf);

	    switch (encoding) {

	    case CE_BASE64:
	    	if (field_encode_base64(NULL, &mn->m_pers, charset)) {
		    errflag++;
		    goto out;
		}
		break;

	    case CE_QUOTED:
	    	if (field_encode_quoted(NULL, &mn->m_pers, charset, asciichars,
					eightbitchars + specialchars, 1)) {
		    errflag++;
		    goto out;
		}
		break;

	    default:
		advise(NULL, "Internal error: unknown RFC-2047 encoding type");
		errflag++;
		goto out;
	    }

	    reformat++;
	}

	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.
	 */

	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[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';

	if (scanstring(tmpbuf, &asciichars, &eightbitchars,
		       &specialchars)) {
	    /*
	     * If we have 8-bit characters, encode it.
	     */

	    if (encoding == CE_UNKNOWN)
	    	encoding = pref_encoding(asciichars, specialchars,
					 eightbitchars);

	    switch (encoding) {

	    case CE_BASE64:
	    	if (field_encode_base64(NULL, &tmpbuf, charset)) {
		    errflag++;
		    goto out;
		}
		break;

	    case CE_QUOTED:
	    	if (field_encode_quoted(NULL, &tmpbuf, charset, asciichars,
					eightbitchars + specialchars, 1)) {
		    errflag++;
		    goto out;
		}
		break;

	    default:
		advise(NULL, "Internal error: unknown RFC-2047 encoding type");
		errflag++;
		goto out;
	    }

	    reformat++;

	    /*
	     * Make sure the size of tmpbuf is correct (it always gets
	     * reallocated in the above functions).
	     */

	    tmpbufsize = strlen(tmpbuf) + 1;

	    /*
	     * Put the note field back surrounded by parenthesis.
	     */

	    mn->m_note = mh_xrealloc(mn->m_note, tmpbufsize + 2);

	    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.
	 */

	/*
	 * 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;

	if (mn->m_gname) {
	    cp = add(mn->m_gname, NULL);
	}

	if (reformat) {
	    cp = add(adrformat(mn), cp);
	} else {
	    cp = add(mn->m_text, 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 (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;
	    }
	}

	/*
	 * Finally add the address
	 */

	output = add(cp, output);
	column += len;
	free(cp);
	cp = NULL;
    }

    /*
     * Just in case we're at the end of a list
     */

    if (groupflag) {
	output = add(";", output);
    }

    output = add("\n", output);

    free(*value);
    *value = output;
    output = NULL;

out:

    if (tmpbuf)
    	free(tmpbuf);
    if (output)
    	free(output);

    return errflag > 0;
}