--- msg.c 2001/08/13 15:16:32 1.2
+++ msg.c 2001/08/14 08:15:25 1.3
@@ -12,17 +12,16 @@
if ((msg = (msg_t *)malloc(sizeof(msg_t))) == NULL)
return NULL;
+ msg->cpMsg = NULL;
+ msg->azHeaders = NULL;
+ msg->asHeaders = 0;
+ msg->cpBody = NULL;
+ msg->cpMsgid = NULL;
msg->mail_from = NULL;
msg->azRcpt = NULL;
msg->asRcpt = 0;
msg->azNewsgroups = NULL;
msg->asNewsgroups = 0;
- msg->azHeaders = NULL;
- msg->asHeaders = 0;
- msg->cpMsg = NULL;
- msg->cpHeaders = NULL;
- msg->cpBody = NULL;
- msg->cpMsgid = NULL;
return msg;
}
@@ -32,29 +31,32 @@
if (msg == NULL)
return;
//FIXME what about non-graceful aborts?
+ if (msg->cpMsg != NULL)
+ free(msg->cpMsg);
+ if (msg->azHeaders != NULL)
+ free(msg->azHeaders);
+ if (msg->cpBody != NULL)
+ free(msg->cpBody);
+ if (msg->cpMsgid != NULL)
+ free(msg->cpMsgid);
if (msg->mail_from != NULL)
free(msg->mail_from);
if (msg->azRcpt != NULL)
free(msg->azRcpt);
- if (msg->azHeaders != NULL)
- free(msg->azHeaders);
if (msg->azNewsgroups != NULL)
free(msg->azNewsgroups);
- if (msg->cpMsg != NULL)
- free(msg->cpMsg);
- if (msg->cpHeaders != NULL)
- free(msg->cpHeaders);
- if (msg->cpBody != NULL)
- free(msg->cpBody);
+
free(msg);
+ return;
}
msg_rc_t msg_split(msg_t *msg)
{
char *cpName;
char *cpValue;
- char *cpRem;
+ char *cpRem; /* Remainder */
char *cp;
+ char *cpHeaders;
/* INPUTS
*
@@ -65,12 +67,12 @@
*
* OUTPUTS
*
- * msg->azHeaders, msg->asHeaders
- * contains the headers in argz format, one logical '\0'-terminated line
- * per header which might be wrapped into multiple '\n'-ended physical
- * lines. The "To:" and "Cc:" headers are silently. The "Newsgroups:" and
- * "Message-ID" headers are removed and their values are stored in
- * separate structures (see below).
+ * msg->azHeaders, msg->asHeaders contains the headers in argz format, one
+ * logical '\0'-terminated line per header which might be wrapped into
+ * multiple '\n'-ended physical lines. The "From " envelope, "To:" and
+ * "Cc:" headers are removed silently. The "Newsgroups:" and "Message-ID"
+ * headers are removed and their values are stored in separate structures
+ * (see below).
*
* msg->cpBody
* contains the unmodified body of the message, '\0'-terminated, no
@@ -85,25 +87,25 @@
*/
/* split message into header and body */
- if (!str_parse(msg->cpMsg, "m/((?:.*?)\\n)\\n(.*)$/s", &msg->cpHeaders, &msg->cpBody))
+ if (!str_parse(msg->cpMsg, "m/((?:.*?)\\n)\\n(.*)$/s", &cpHeaders, &msg->cpBody))
return MSG_ERR_SPLITSPLITBODY;
/* replace envelope From w/o colon by X-F: pseudotag. This eliminates the
* special case of having one header, which is really an embedded
- * envelope, not ending with a colon while all other do. After splitting
+ * envelope, not ending with a colon while all others do. After splitting
* headers into name and value pairs this action is reversed.
*/
- if (strlen(msg->cpHeaders) < 4)
+ if (strlen(cpHeaders) < 4)
return MSG_ERR_SPLITLEN;
- if (strncasecmp(msg->cpHeaders, "From", 4) != 0)
+ if (strncasecmp(cpHeaders, "From", 4) != 0)
return MSG_ERR_SPLITMISSINGFROM;
- memcpy(msg->cpHeaders, "X-F:", 4);
+ memcpy(cpHeaders, "X-F:", 4);
/* unwrap header lines */
//FIXME poor man's s///g simulator as current str library doesn't support //global substitution
- while (str_parse(msg->cpHeaders, "s/(.*?)\\n[ \\t]+(.*)/$1 $2/s", &cpRem)) {
- free(msg->cpHeaders);
- msg->cpHeaders = cpRem;
+ while (str_parse(cpHeaders, "s/(.*?)\\n[ \\t]+(.*)/$1 $2/s", &cpRem)) {
+ free(cpHeaders);
+ cpHeaders = cpRem;
}
/* split header lines into names and values */
@@ -111,9 +113,9 @@
//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(msg->cpHeaders, "m/^([\\w-]+?:)[ \\t]*(.*?)[ \\t]*\\n(.*)/s", &cpName, &cpValue, &cpRem)) {
- free(msg->cpHeaders);
- msg->cpHeaders = cpRem;
+ while (str_parse(cpHeaders, "m/^([\\w-]+?:)[ \\t]*(.*?)[ \\t]*\\n(.*)/s", &cpName, &cpValue, &cpRem)) {
+ free(cpHeaders);
+ cpHeaders = cpRem;
argz_add(&msg->azHeaders, &msg->asHeaders, cpName);
argz_add(&msg->azHeaders, &msg->asHeaders, cpValue);
}
@@ -187,9 +189,10 @@
int i;
char *cpCut;
char *cpWrap;
- char *cpNew;
char c;
+ char cOld;
int n;
+ char *cpHeaders;
/* verify asNewsgroups */
if (msg->azNewsgroups == NULL)
@@ -211,10 +214,12 @@
/* merge name/value pairs into single string */
argz_add(&msg->azHeaders, &msg->asHeaders, ""); /* append empty string */
- if ((aHeaders = (char **)malloc((argz_count(msg->azHeaders,
- msg->asHeaders) + 1) * sizeof(char *))) == NULL)
- exit(1); //FIXME
+ if ((aHeaders = (char **)malloc((argz_count(msg->azHeaders, msg->asHeaders) + 1) * sizeof(char *))) == NULL)
+ return MSG_ERR_MEM;
argz_extract(msg->azHeaders, msg->asHeaders, aHeaders);
+ /* replace the trailing '\0', which is *(cp-1) of the predecessor, with a
+ * space at every second string. Break action when terminating NULL string
+ * is detected */
i=0;
while(1) {
if ((cp = aHeaders[++i]) == NULL)
@@ -222,13 +227,10 @@
*(cp-1) = ' ';
if ((cp = aHeaders[++i]) == NULL)
break;
- // *(cp-1) = '\n';
}
+ free(aHeaders);
/* fold headers */
-//FIXME where to place this defines best
-#define WRAPAT 120
-#define WRAPUSING "\n "
cp = NULL;
while ((cp = argz_next(msg->azHeaders, msg->asHeaders, cp)) != NULL) {
if (strlen(cp) >= WRAPAT) {
@@ -244,12 +246,12 @@
//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)
- exit(1); //FIXME
+ return MSG_ERR_MEM;
*cpWrap = '\0';
}
else {
if ((cpWrap = (char *)realloc(cpWrap, strlen(cpWrap)+strlen(cpCut)+strlen(WRAPUSING)+1)) == NULL)
- exit(1); //FIXME
+ return MSG_ERR_MEM;
strcat(cpWrap, WRAPUSING);
}
strcat(cpWrap, cpCut);
@@ -260,7 +262,7 @@
cpRem += i;
if (strlen(cpRem) > 0) {
if ((cpWrap = (char *)realloc(cpWrap, strlen(cpWrap)+strlen(cpRem)+strlen(WRAPUSING)+1)) == NULL)
- exit(1); //FIXME
+ return MSG_ERR_MEM;
strcat(cpWrap, WRAPUSING);
strcat(cpWrap, cpRem);
}
@@ -271,28 +273,7 @@
}
argz_stringify(msg->azHeaders, msg->asHeaders, '\n');
- msg->cpHeaders = msg->azHeaders;
-
- if (argz_create_sep(msg->cpBody, '\n', &msg->azBody, &msg->asBody) != 0)
- return MSG_ERR_MEM;
-
- /* escape dots at the beginning of each line */
- cp = NULL;
- while ((cp =argz_next(msg->azBody, msg->asBody, cp)) != NULL) {
- if (*cp == '.') {
- if ((cpNew = malloc(strlen(cp) + 1)) == NULL)
- return MSG_ERR_MEM;
- *cpNew = '.';
- cpNew++;
- *cpNew = '\0';
- strcat(cpNew, cp);
- argz_delete(&msg->azBody, &msg->asBody, cp);
- argz_insert(&msg->azBody, &msg->asBody, cp, cpNew);
- }
- }
-
- argz_stringify(msg->azBody, msg->asBody, '\n');
- msg->cpBody = msg->azBody;
+ cpHeaders = msg->azHeaders;
/********************************************************************
* header + CRLF + body + '.' + CRLF + '\0', replacing NL with CRLF *
@@ -300,21 +281,25 @@
n = 0;
/* count size of headers, reserve space for NL to CRLF conversion */
- for (i = 0; ((c = msg->cpHeaders[i]) != '\0'); i++) {
+ for (i = 0; ((c = cpHeaders[i]) != '\0'); i++) {
if (c == '\n')
n++;
n++;
}
/* if headers don't end with NL, reserve space for CRLF */
- if (i >= 0 && msg->cpHeaders[i - 1] != '\n')
+ if (i >= 0 && cpHeaders[i - 1] != '\n')
n+=2;
/* reserve space for CRLF between headers and body */
n+=2;
- /* count size of body, reserve space for NL to CRLF conversion */
+ /* count size of body, reserve space for NL-DOT escape and NL to CRLF conversion */
+ cOld = '\n';
for (i = 0; ((c = msg->cpBody[i]) != '\0'); i++) {
if (c == '\n')
n++;
+ if (c == '.' && cOld == '\n')
+ n++;
n++;
+ cOld = c;
}
/* if body doesn't end with NL, reserve space for CRLF */
if (i >= 0 && msg->cpBody[i - 1] != '\n')
@@ -327,24 +312,28 @@
n = 0;
/* copy headers, do NL to CRLF conversion */
- for (i = 0; ((c = msg->cpHeaders[i]) != '\0'); i++) {
+ for (i = 0; ((c = cpHeaders[i]) != '\0'); i++) {
if (c == '\n')
msg->cpMsg[n++] = '\r';
msg->cpMsg[n++] = c;
}
/* if headers don't end with NL, append CRLF */
- if (i >= 0 && msg->cpHeaders[i - 1] != '\n') {
+ if (i >= 0 && cpHeaders[i - 1] != '\n') {
msg->cpMsg[n++] = '\r';
msg->cpMsg[n++] = '\n';
}
/* add CRLF between headers and body */
msg->cpMsg[n++] = '\r';
msg->cpMsg[n++] = '\n';
- /* copy body, do NL to CRLF conversion */
+ /* copy body, do NL-DOT escape and NL to CRLF conversion */
+ cOld = '\n';
for (i = 0; ((c = msg->cpBody[i]) != '\0'); i++) {
if (c == '\n')
msg->cpMsg[n++] = '\r';
+ if (c == '.' && cOld == '\n')
+ msg->cpMsg[n++] = '.';
msg->cpMsg[n++] = c;
+ cOld = c;
}
/* if body doesn't end with NL, append CRLF */
if (i >= 0 && msg->cpBody[i - 1] != '\n') {
@@ -358,7 +347,6 @@
msg->cpMsg[n] = '\0';
//fprintf(stderr, "DEBUG: Message = ***%s***\n", msg->cpMsg);
-
return MSG_OK;
}
|