--- msg.c 2001/08/23 09:12:30 1.9
+++ msg.c 2001/08/27 13:45:53 1.10
@@ -39,7 +39,7 @@
{
if (msg == NULL)
return;
- /*FIXME what about non-graceful aborts? */
+
if (msg->azEnvgroups != NULL)
free(msg->azEnvgroups);
if (msg->cpMsg != NULL)
@@ -99,7 +99,7 @@
/* split message into header and body */
if (str_parse(msg->cpMsg, "m/((?:.*?)\\n)\\n(.*)$/s", &cpHeaders, &msg->cpBody) <= 0)
- return MSG_ERR_SPLITSPLITBODY;
+ return MSG_ERR_SPLITHEADBODY;
/* replace envelope From w/o colon by X-F: pseudotag. This eliminates the
* special case of having one header, which is really an embedded
@@ -110,19 +110,14 @@
memcpy(cpHeaders, "X-F:", 4);
/* unwrap header lines */
- /*FIXME poor man's s///g simulator as current str library doesn't support //global substitution */
+ /* poor man's s///g simulator as current str library doesn't support global substitution */
while (str_parse(cpHeaders, "s/(.*?)\\n[ \\t]+(.*)/$1 $2/s", &cpRem) > 0) {
free(cpHeaders);
cpHeaders = cpRem;
}
/* split header lines into names and values */
- /*FIXME str enhancement requests and bugs to be fixed */
- /*FIXME - fix bug "not" [^...] working */
- /*FIXME - improve str_parse(foo, "...", &foo) should free foo() on it's own */
- /*FIXME - add "global" in s/search/replace/g (see above "unwrap hader lines") */
- while (str_parse(cpHeaders, "m/^([\\w-]+?:)[ \\t]*(.*?)[ \\t]*\\n(.*)/s",
- &cpName, &cpValue, &cpRem) > 0) {
+ while (str_parse(cpHeaders, "m/^([\\w-]+?:)[ \\t]*([^\\n]*?)[ \\t]*\\n(.*)/s", &cpName, &cpValue, &cpRem) > 0) {
free(cpHeaders);
cpHeaders = cpRem;
argz_add(&msg->azHeaders, &msg->asHeaders, cpName);
@@ -194,7 +189,7 @@
return MSG_ERR_MEM;
}
argz_add(&msg->azHeaders, &msg->asHeaders, "Path:");
- argz_add(&msg->azHeaders, &msg->asHeaders, "not-for-mail"); /*FIXME */
+ argz_add(&msg->azHeaders, &msg->asHeaders, "not-for-mail");
return MSG_OK;
}
@@ -205,6 +200,7 @@
char *cpRem;
char **aHeaders;
int i;
+ int o;
char *cpCut;
char *cpWrap;
char c;
@@ -248,36 +244,47 @@
}
free(aHeaders);
- /* fold headers */
+ /* fold headers
+ *
+ * A logical line is split into one or more physical '\n'-terminated
+ * lines. The physical line is never longer than WRAPAT characters. This
+ * includes the folded data and the header name + colon + space for the
+ * first line and WRAPUSING string prefix for all other lines. Leading and
+ * trailing blanks of folded lines are removed while blanks inside the
+ * line are preserved. The header is never left alone in a physical line.
+ * Fragments exceeding WRAPAT characters without having a blank as a
+ * splitting point are forcibly cut at a non-blank character.
+ */
cp = NULL;
while ((cp = argz_next(msg->azHeaders, msg->asHeaders, cp)) != NULL) {
- if (strlen(cp) >= WRAPAT) {
+ if (strlen(cp) > WRAPAT) {
cpRem = cp;
cpWrap = NULL;
- while (strlen(cpRem) >= WRAPAT) {
- for (i = WRAPAT; i >= 1 && (cpRem[i] != ' ') && (cpRem[i] != '\t'); i--);
- if (i == 0)
- i = WRAPAT; /* sorry, hard cut at non-whitespace */
- if (i < WRAPAT)
- i++; /* we don't care about the whitespace itself */
- cpCut = str_dup(cpRem, i);
- /*FIXME 1.) continue searching downwards skipping all whitespaces and 2.) as we know the length replace str_dup/ strcat/ free with strncat only */
- if (cpWrap == NULL) {
- if ((cpWrap = (char *)malloc(strlen(cpCut)+strlen(WRAPUSING)+1)) == NULL)
- return MSG_ERR_MEM;
- *cpWrap = '\0';
- }
- else {
- if ((cpWrap = (char *)realloc(cpWrap, strlen(cpWrap)+strlen(cpCut)+strlen(WRAPUSING)+1)) == NULL)
- return MSG_ERR_MEM;
- strcat(cpWrap, WRAPUSING);
- }
- strcat(cpWrap, cpCut);
- free(cpCut);
+ for (o = 0; (cpRem[o] != ':') && (cpRem[o] != '\0'); o++); /* offset name so at least one char of value remains in first line */
+ o += 2; /* skip ": " */
+ while ((strlen(cpRem) + (cpWrap == NULL ? 0 : strlen(WRAPUSING))) > WRAPAT) {
+ for (i = WRAPAT - 1 - (cpWrap == NULL ? 0 : strlen(WRAPUSING)); (i >= o) && !isblank(cpRem[i]); i--);
+ if (i < o)
+ i = WRAPAT - 1 - (cpWrap == NULL ? 0 : strlen(WRAPUSING) - 1); /* sorry, forced cut at non-blank */
+ cpCut = cpRem;
cpRem += i;
+ for (; (isblank(*cpRem) && (*cpRem != '\0')); cpRem++); /* skip next lines leading blanks */
+ for (; (i >= o) && isblank(cpCut[i-1]); i--); /* chop off this lines trailing blanks */
+ if (i >= o) { /* only keep line fragment if some non-blanks inside */
+ if (cpWrap == NULL) {
+ if ((cpWrap = (char *)malloc(i+strlen(WRAPUSING)+1)) == NULL)
+ return MSG_ERR_MEM;
+ *cpWrap = '\0';
+ o = 1;
+ }
+ else {
+ if ((cpWrap = (char *)realloc(cpWrap, strlen(cpWrap)+i+strlen(WRAPUSING)+1)) == NULL)
+ return MSG_ERR_MEM;
+ strcat(cpWrap, WRAPUSING);
+ }
+ strncat(cpWrap, cpCut, i);
+ }
}
- for (i = 0; i < strlen(cpRem) && ((cpRem[i] == ' ') || (cpRem[i] == '\t')); i++);
- cpRem += i;
if (strlen(cpRem) > 0) {
if ((cpWrap = (char *)realloc(cpWrap, strlen(cpWrap)+strlen(cpRem)+strlen(WRAPUSING)+1)) == NULL)
return MSG_ERR_MEM;
@@ -374,7 +381,7 @@
str = "MSG: no description";
if (rc == MSG_OK ) str = "MSG: no error";
else if (rc == MSG_ERR_MEM ) str = "MSG: memory";
- else if (rc == MSG_ERR_SPLITSPLITBODY ) str = "MSG: split into header and body failed";
+ else if (rc == MSG_ERR_SPLITHEADBODY ) str = "MSG: split into header and body failed";
else if (rc == MSG_ERR_SPLITLEN ) str = "MSG: header is too short";
else if (rc == MSG_ERR_SPLITMISSINGFROM ) str = "MSG: header is missing 'From ' envelope";
else if (rc == MSG_ERR_SPLITIDNONE ) str = "MSG: header is missing 'Message-ID'";
|