--- lmtp2nntp_config.c 2002/02/14 15:11:08 1.50
+++ lmtp2nntp_config.c 2002/02/20 15:42:26 1.51
@@ -39,6 +39,7 @@
#include "pcre.h"
#include "popt.h"
#include "str.h"
+#include "var.h"
#include "val.h"
/* library version check (compile-time) */
@@ -103,6 +104,8 @@
return L2_OK;
}
+static void headersimulation(lmtp2nntp_t *); //FIXME
+
void config_context(lmtp2nntp_t *ctx)
{
ex_t ex;
@@ -539,6 +542,8 @@
char *cpVal;
headerrule_t *hrI;
headerrule_t *hrP;
+ const char *cpError;
+ int iError;
if ( (val_get(ctx->val, "option.headerrule", &ov) != VAL_OK)
|| (ov->ndata < 0)
@@ -554,8 +559,10 @@
log2(ctx, DEBUG, "cp = (data.m)[%d] = \"%s\"", i, cp);
hrNew = (headerrule_t *)mallocex(sizeof(headerrule_t));
- hrNew->next = NULL;
- hrNew->carve = NULL; // initialize variables which might have resources allocated that need to be cleaned up when an exception is caught
+ hrNew->next = NULL;
+ hrNew->carve = NULL;
+ hrNew->pcreRegex = NULL;
+ hrNew->pcreExtra = NULL;
cp = hrNew->carve = strdupex(cp);
/* priority */
@@ -600,8 +607,21 @@
hrNew->header = cpHeader;
hrNew->val = cpVal;
+ if (cpRegex != NULL) {
+ /* compile regular expression into finite state machine and optimize */
+ if ((hrNew->pcreRegex = pcre_compile(cpRegex, PCRE_CASELESS, &cpError, &iError, NULL)) == NULL) {
+ log3(ctx, ERROR, "option --headerrule, regex (%s) failed at pos %d with %s", cpRegex, iError, cpError);
+ throw(0,0,0);
+ }
+ hrNew->pcreExtra = pcre_study(hrNew->pcreRegex, 0, &cpError);
+ if (cpError != NULL) {
+ log1(ctx, ERROR, "option --headerrule, regex optimization failed with %s", cpError);
+ throw(0,0,0);
+ }
+ }
+
if (ctx->option_firstheaderrule == NULL)
- ctx->option_firstheaderrule = (headerrule_t *)hrNew; // interesting point since hrNew is declared volatile we have to cast it. This makes me unhappy as it enlarges the code which is far from the spirit of lib_ex
+ ctx->option_firstheaderrule = (headerrule_t *)hrNew; /* first */
else {
for (hrP = NULL, hrI = ctx->option_firstheaderrule;
hrI != NULL && hrI->pri <= hrNew->pri;
@@ -611,23 +631,20 @@
if (hrP != NULL)
hrP->next = (headerrule_t *)hrNew; /* append */
else
- ctx->option_firstheaderrule = (headerrule_t *)hrNew; /* newfirst */
+ ctx->option_firstheaderrule = (headerrule_t *)hrNew; /* new first */
}
- /* after linking the structure into a parental-controlled structure we
- expect that the parental cleanup will handle normal and exceptional
- resource releasing and therefore we *must* reset this variable initialization
- to avoid accidental local cleanup! In fact, this code will fail if the
- next statement is omitted.
- */
- hrNew = NULL; // initialize variables which might have resources allocated that need to be cleaned up when an exception is caught
-
+ hrNew = NULL; /* release cleanup responsibility */
}
}
}
- cleanup { // make sure the conditional variables are *always* proper initialized and cleared volatile
+ cleanup {
if (hrNew != NULL) {
if (hrNew->carve != NULL)
freeex(hrNew->carve);
+ if (hrNew->pcreRegex != NULL)
+ free(hrNew->pcreRegex);
+ if (hrNew->pcreExtra != NULL)
+ free(hrNew->pcreExtra);
freeex((headerrule_t *)hrNew);
}
}
@@ -1004,6 +1021,8 @@
catch (ex)
rethrow;
+ headersimulation(ctx); //FIXME
+
//void testpcre(void)
{
char *szRegex;
@@ -1077,3 +1096,307 @@
CUS:
return;
}
+
+
+
+static void headerdestroy(headerdata_t *hdC)
+{
+ int i;
+
+ if (hdC->ndata > 1) {
+ for (i = 0; i < hdC->ndata; i++) {
+ if (hdC->data.m[i] == NULL)
+ break;
+ free(hdC->data.m[i]);
+ }
+ free (hdC->data.m);
+ } else
+ if (hdC->ndata == 1)
+ if (hdC->data.s != NULL)
+ free(hdC->data.s);
+ if (hdC->name != NULL)
+ free(hdC->name);
+ if (hdC->prev != NULL && hdC->prev->next == hdC)
+ return; //FIXME still linked, cannot be destroyed
+ if (hdC->next != NULL && hdC->next->prev == hdC)
+ return; //FIXME still linked, cannot be destroyed
+ free(hdC);
+}
+
+static void headerdelete(headerdata_t *hdC)
+{
+ if (hdC->prev != NULL)
+ hdC->prev->next = hdC->next;
+ hdC->next = NULL;
+ if (hdC->next != NULL)
+ hdC->next->prev = hdC->prev;
+ hdC->prev = NULL;
+ headerdestroy(hdC);
+}
+
+static void headerreplace(headerdata_t *hdC, headerdata_t *hdNew)
+{
+ hdNew->prev = hdC->prev;
+ hdC->prev = NULL;
+ hdNew->next = hdC->next;
+ hdC->next = NULL;
+ headerdestroy(hdC);
+}
+
+static headerdata_t *headercreate(void)
+{
+ ex_t ex;
+ volatile headerdata_t *hdNew = NULL;
+ try {
+ hdNew = mallocex(sizeof(headerdata_t));
+ hdNew->prev = NULL;
+ hdNew->next = NULL;
+ hdNew->name = NULL;
+ hdNew->ndata = 0;
+ }
+ catch (ex) {
+ if (hdNew != NULL)
+ free((headerdata_t *)hdNew);
+ rethrow;
+ }
+ return (headerdata_t *)hdNew;
+}
+#if 0
+//headermatrix()
+{
+ volatile header_t *hNew = NULL;
+ try {
+ char *cp;
+
+ cp = NULL;
+ while ((cp = argz_next(ctx->msg->azHeaders, ctx->msg->asHeaders, cp)) != NULL) {
+ hNew = mallocex(sizeof(header_t));
+ //FIXME
+ }
+ }
+ cleanup {
+ if (hNew != NULL)
+ free(hNew);
+ }
+ catch(ex) {
+ rethrow;
+ }
+}
+#endif
+
+static var_config_t ctx_lookup_cfg = {
+ '$', /* varinit */
+ '{', /* startdelim */
+ '}', /* enddelim */
+ '[', /* startindex */
+ ']', /* endindex */
+ '#', /* current_index */
+ '\\', /* escape */
+ "a-zA-Z0-9_.-" /* namechars */
+};
+
+static var_rc_t ctx_lookup(
+ void *_ctx,
+ const char *var_ptr, size_t var_len, int var_idx,
+ const char **val_ptr, size_t *val_len, size_t *val_size)
+{
+ lmtp2nntp_t *ctx = (lmtp2nntp_t *)_ctx;
+ /*FIXME
+ const char *name;
+ size_t len;
+ char *cp;
+ */
+ var_rc_t rc;
+
+ log2(ctx, DEBUG, "lookup variable \"%s\" (%d)", var_ptr, var_len);
+ rc = VAR_ERR_UNDEFINED_VARIABLE;
+ if (strncasecmp(var_ptr, "test", var_len) == 0) {
+ }
+ else if (strncasecmp(var_ptr, "xyz", var_len) == 0) {
+ *val_ptr = "Hello, World!";
+ *val_len = strlen("Hello, World!");
+ *val_size = 0;
+ rc = VAR_OK;
+ }
+ if (rc == VAR_OK)
+ log4(ctx, DEBUG, "lookup variable \"%s\" (%d) ok: result is \"%s\" (%d)", var_ptr, var_len, *val_ptr, *val_len);
+ else
+ log3(ctx, DEBUG, "lookup variable \"%s\" (%d) failed: %s", var_ptr, var_len, var_strerror(rc));
+ return rc;
+}
+
+static void headerrewrite(lmtp2nntp_t *ctx)
+{
+ headerrule_t *hrI;
+ headerdata_t *hdI, *hdNew;
+ /*
+ char *cp;
+ int i;
+ char *cpPri;
+ char *cpRegex;
+ char *cpHeader;
+ char *cpVal;
+ headerrule_t *hrP;
+ hrNew->pri = atoi(cpPri);
+ hrNew->regex = cpRegex;
+ hrNew->header = cpHeader;
+ hrNew->val = cpVal;
+ char *szRegex;
+ pcre *pcreRegex;
+ pcre_extra *pcreExtra;
+ const char *szError;
+ int nErrorOffset;
+ int opt;
+ char *buf;
+ int buf_size;
+#define OVECSIZE 30
+ int ovec[OVECSIZE];
+ int i;
+ const char **cpList;
+ */
+ int ovec[OVECSIZE];
+ int iCheck;
+
+ { //FIXME debug code block
+ int i;
+
+ log0(ctx, DEBUG, "FIXME trace ---------- headerrewrite() ----------");
+ for (hrI = ctx->option_firstheaderrule; hrI != NULL; hrI = hrI->next)
+ log1(ctx, DEBUG, "hrI->header=%s", hrI->header);
+ for (hdI = ctx->msg->hdFirst; hdI != NULL; hdI = hdI->next) {
+ if (hdI->ndata == 0)
+ log1(ctx, DEBUG, "hdI->name=%s, (NO DATA)", hdI->name);
+ if (hdI->ndata == 1)
+ log2(ctx, DEBUG, "hdI->name=%s, hdI->data.s=%s", hdI->name, hdI->data.s);
+ if (hdI->ndata > 1)
+ for (i = 0; i < hdI->ndata; i++)
+ log3(ctx, DEBUG, "hdI->name=%s, hdI->data.m[%d]=%s", hdI->name, i, hdI->data.m[i]);
+ }
+ }
+
+ for (hrI = ctx->option_firstheaderrule; hrI != NULL; hrI = hrI->next) { /* for each rule */
+ //log1(ctx, DEBUG, "FIXME trace loop hrI=%.8lx", hrI);
+ if (hrI->regex != NULL) {
+ log1(ctx, DEBUG, "rule has regex %s", hrI->regex);
+ for (hdI = ctx->msg->hdFirst; hdI != NULL; hdI = hdI->next) { /* for each header */
+ //log2(ctx, DEBUG, "FIXME trace loop hdI=%.8lx, hI->name=\"%s\"", hdI, hdI->name);
+ if (hdI->name == NULL || strlen(hdI->name) == 0)
+ continue; //FIXME header w/o name cannot happen normally
+ iCheck = pcre_exec(hrI->pcreRegex, hrI->pcreExtra, hdI->name, strlen(hdI->name), 0, 0, ovec, OVECSIZE);
+ log1(ctx, DEBUG, "FIXME trace iCheck=%d", iCheck);
+ if (iCheck >= 1) {
+ log0(ctx, DEBUG, "regex matches");
+ hdNew = headercreate();
+ hdNew->name = strdupex(hrI->header); //FIXME rename ->header to ->name
+ {
+ var_rc_t var_rc;
+ char *res_ptr;
+ if ((var_rc = var_expand(hrI->val, strlen(hrI->val), &res_ptr, NULL,
+ ctx_lookup, ctx, &ctx_lookup_cfg, TRUE)) != VAR_OK) {
+ log2(ctx, ERROR, "expansion of '%s' failed: %s", hrI->val, var_strerror(var_rc));
+ }
+ log2(ctx, ERROR, "expansion of '%s' succeeded: %s", hrI->val, res_ptr);
+ hdNew->data.s = res_ptr;
+ hdNew->ndata = 1;
+ /*FIXME clean up data.m */
+ headerreplace(hdI, hdNew);
+ if (hdNew->prev == NULL)
+ ctx->msg->hdFirst = hdNew;
+ hdI = hdNew;
+ }
+ }
+ }
+ }
+ else {
+ log1(ctx, DEBUG, "rule has no regex but static header %s", hrI->header);
+ hdNew = headercreate();
+ hdNew->name = strdupex(hrI->header); //FIXME rename ->header to ->name
+ hdNew->data.s = strdupex(hrI->val);
+ hdNew->ndata = 1;
+ /*FIXME clean up data.m */
+ for (hdI = ctx->msg->hdFirst; hdI != NULL; hdI = hdI->next) { /* for each header */
+ if (hdI->name == NULL || strlen(hdI->name) == 0)
+ continue; //FIXME header w/o name cannot happen normally
+ log2(ctx, DEBUG, "hrI->header=%s, hdI->name=%s", hrI->header, hdI->name);
+ if (strcmp(hrI->header, hdI->name) == 0)
+ break;
+ }
+ if (hdI != NULL) {
+ log1(ctx, DEBUG, "replacing header %s", hrI->header);
+ headerreplace(hdI, hdNew);
+ if (hdNew->prev == NULL)
+ ctx->msg->hdFirst = hdNew;
+ }
+ else {
+ log1(ctx, DEBUG, "appending header %s", hrI->header);
+ for (hdI = ctx->msg->hdFirst; hdI->next != NULL; hdI = hdI->next);
+ hdI->next = hdNew;
+ hdNew->prev = hdI;
+ }
+ }
+ }
+
+ { //FIXME debug code block
+ int i;
+
+ log0(ctx, DEBUG, "FIXME trace ---------- headerrewrite() ---------- FINISH");
+ for (hrI = ctx->option_firstheaderrule; hrI != NULL; hrI = hrI->next)
+ log1(ctx, DEBUG, "hrI->header=%s", hrI->header);
+ for (hdI = ctx->msg->hdFirst; hdI != NULL; hdI = hdI->next) {
+ if (hdI->ndata == 0)
+ log1(ctx, DEBUG, "hdI->name=%s, (NO DATA)", hdI->name);
+ if (hdI->ndata == 1)
+ log2(ctx, DEBUG, "hdI->name=%s, hdI->data.s=%s", hdI->name, hdI->data.s);
+ if (hdI->ndata > 1)
+ for (i = 0; i < hdI->ndata; i++)
+ log3(ctx, DEBUG, "hdI->name=%s, hdI->data.m[%d]=%s", hdI->name, i, hdI->data.m[i]);
+ }
+ }
+}
+
+static void headersimulation(lmtp2nntp_t *ctx)
+{
+ headerdata_t *hdI, *hdNew;
+
+ ctx->msg = msg_create();
+
+ log0(ctx, DEBUG, "FIXME simulation - GO");
+ char *replyto[4] = { "foo@example.com", "bar@example.com", "quux@example.com", NULL };
+
+ hdNew = headercreate();
+ hdNew->name = "To";
+ hdNew->data.s = "foo@invalid.com";
+ hdNew->ndata = 1;
+ ctx->msg->hdFirst = hdNew;
+ hdI = hdNew;
+
+ hdNew = headercreate();
+ hdNew->name = "Reply-To";
+ hdNew->data.m = replyto;
+ hdNew->ndata = 3;
+ hdI->next = hdNew;
+ hdI = hdNew;
+
+ hdNew = headercreate();
+ hdNew->name = "Subject";
+ hdNew->data.s = "a tiny little test";
+ hdNew->ndata = 1;
+ hdI->next = hdNew;
+ hdI = hdNew;
+
+ hdNew = headercreate();
+ hdNew->name = "Date";
+ hdNew->data.s = "Mon, 18 Feb 2002 09:43:52 +0100";
+ hdNew->ndata = 1;
+ hdI->next = hdNew;
+ hdI = hdNew;
+
+ hdNew = headercreate();
+ hdNew->name = "Message-ID";
+ hdNew->data.s = "<200201172300.AAA29400@procter012.pg-cw.de>";
+ hdNew->ndata = 1;
+ hdI->next = hdNew;
+ hdI = hdNew;
+
+ headerrewrite(ctx);
+}
|