OSSP CVS Repository

ossp - Check-in [2084]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 2084
Date: 2002-Apr-18 16:09:25 (local)
2002-Apr-18 14:09:25 (UTC)
User:thl
Branch:
Comment: no change, only a code move
Tickets:
Inspections:
Files:
ossp-pkg/lmtp2nntp/lmtp2nntp_config.c      1.70 -> 1.71     0 inserted, 461 deleted
ossp-pkg/lmtp2nntp/lmtp2nntp_msg.c      1.4 -> 1.5     463 inserted, 0 deleted

ossp-pkg/lmtp2nntp/lmtp2nntp_config.c 1.70 -> 1.71

--- lmtp2nntp_config.c   2002/04/18 13:31:27     1.70
+++ lmtp2nntp_config.c   2002/04/18 14:09:25     1.71
@@ -1161,464 +1161,3 @@
     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)
-        throw(0,0,0);
-    if (hdC->next != NULL && hdC->next->prev == hdC)
-        throw(0,0,0);
-    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;
-    if (hdNew->prev != NULL)
-        hdNew->prev->next = hdNew;
-    if (hdNew->next != NULL)
-        hdNew->next->prev = hdNew;
-    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;
-}
-
-struct regex_ctx_st; //FIXME go into a header!
-typedef struct regex_ctx_st regex_ctx_t;
-struct regex_ctx_st {
-    int            nMatch;
-    const char   **acpMatch;
-    l2_env_t      *l2_env;
-    l2_channel_t  *l2;
-};
-
-static var_rc_t regex_lookup(
-    var_t *var, 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)
-{
-    regex_ctx_t *ctx = (regex_ctx_t *)_ctx;
-    var_rc_t rc;
-    char *cp;
-    int i;
-
-    logbook(ctx->l2, L2_LEVEL_DEBUG, "rgx_lookup variable \"%s\" (%d)", var_ptr, var_len);
-    rc = VAR_ERR_UNDEFINED_VARIABLE;
-    i = atoi(var_ptr); /* works with both '}' and '\0' termination */
-    if (i < ctx->nMatch) {
-        *val_ptr = ctx->acpMatch[i];
-        *val_len = strlen(ctx->acpMatch[i]);
-        *val_size = 0;
-        rc = VAR_OK;
-    }
-    if (rc == VAR_OK)
-        logbook(ctx->l2, L2_LEVEL_DEBUG, "rgx_lookup variable \"%s\" (%d) ok: result is \"%s\" (%d)", var_ptr, var_len, *val_ptr, *val_len);
-    else
-        logbook(ctx->l2, L2_LEVEL_DEBUG, "rgx_lookup variable \"%s\" (%d) failed: %s (%d)", var_ptr, var_len, var_strerror(var, rc, &cp) == VAR_OK ? cp : "Unknown Error", rc);
-    return rc;
-}
-
-static var_rc_t operate_cb(
-    var_t *var, void *ctx,
-    const char  *op_ptr, size_t op_len,
-    const char  *arg_ptr, size_t arg_len,
-    const char  *val_ptr, size_t val_len,
-    char **out_ptr, size_t *out_len, size_t *out_size)
-{
-    int i;
-
-    if (val_ptr == NULL) {
-        *out_ptr = "";
-        *out_len = 0;
-        *out_size = 0;
-        return VAR_OK;
-    }
-    if (op_len == 6 && strncmp(op_ptr, "return", 6) == 0) {
-        *out_ptr = malloc(arg_len);
-        *out_len = arg_len;
-        *out_size = arg_len;
-        memcpy(*out_ptr, arg_ptr, arg_len);
-        return VAR_OK;
-    }
-    else if (op_len == 5 && strncmp(op_ptr, "upper", 5) == 0) {
-        *out_ptr = malloc(val_len);
-        *out_len = val_len;
-        *out_size = val_len;
-        for (i = 0; i < val_len; i++)
-            (*out_ptr)[i] = (char)toupper((int)(val_ptr[i]));
-        return VAR_OK;
-    }
-    else if (op_len == 5 && strncmp(op_ptr, "lower", 5) == 0) {
-        *out_ptr = malloc(val_len);
-        *out_len = val_len;
-        *out_size = val_len;
-        for (i = 0; i < val_len; i++)
-            (*out_ptr)[i] = (char)tolower((int)(val_ptr[i]));
-        return VAR_OK;
-    }
-    else 
-        return VAR_ERR_UNDEFINED_OPERATION;
-}
-
-void msg_headermatrixbuildup(msg_t *msg)
-{
-    ex_t ex;
-    volatile headerdata_t *hdNew = NULL;
-    try {
-        headerdata_t *hdI, *hdP;
-        char *cp;
-
-        cp = NULL;
-        while ((cp = argz_next(msg->azHeaders, msg->asHeaders, cp)) != NULL) { /* for each message header */
-
-            /*FIXME we want O(1) here */
-            for (hdP = NULL, hdI = msg->hdFirst; hdI != NULL; hdP = hdI, hdI = hdI->next) { /* for each matrix header */
-                if (hdI->name == NULL || strlen(hdI->name) == 0 || hdI->ndata == 0)
-                    continue;
-                if (strcasecmp(cp, hdI->name) == 0)
-                    break;
-            }
-
-            if (hdI == NULL) {
-                hdNew = headercreate(); /* not found, create new */
-                hdNew->name = strdupex(cp);
-                hdI = (headerdata_t *)hdNew; hdNew = NULL; /* ex cleanup */
-                if (hdP == NULL)
-                    msg->hdFirst = hdI; /* no previous? this is the first */
-                else {
-                    hdP->next = hdI;
-                    hdI->prev = hdP;
-                }
-            }
-            cp = argz_next(msg->azHeaders, msg->asHeaders, cp);
-            if (hdI->ndata == 0) {
-                logbook(msg->l2, L2_LEVEL_DEBUG, "header=%s, currently empty", hdI->name);
-                hdI->data.s = strdupex(cp);
-                hdI->ndata = 1;
-            }
-            else if(hdI->ndata == 1) {
-                char *cpOld;
-                cpOld = hdI->data.s;
-                logbook(msg->l2, L2_LEVEL_DEBUG, "header=%s, currently single valued", hdI->name);
-                hdI->data.m = (char **)mallocex(3 * sizeof(char *));
-                hdI->data.m[0] = strdupex(cpOld); //FIXME
-                hdI->data.m[1] = strdupex(cp);
-                hdI->data.m[2] = NULL;
-                hdI->ndata = 2;
-            }
-            else {
-                logbook(msg->l2, L2_LEVEL_DEBUG, "header=%s, currently multi valued %d", hdI->name, hdI->ndata);
-                hdI->data.m = (char **)reallocex(hdI->data.m, (hdI->ndata + 2) * sizeof(char *));
-                hdI->data.m[hdI->ndata++] = strdupex(cp);
-                hdI->data.m[hdI->ndata] = NULL;
-            }
-        }
-    }
-    cleanup {
-        if (hdNew != NULL)
-            free((headerdata_t *)hdNew);
-    }
-    catch(ex) {
-        rethrow;
-    }
-}
-
-void msg_headermatrixteardwn(msg_t *msg)
-{
-    ex_t ex;
-    try {
-        headerdata_t *hdI;
-
-        if (msg->azHeaders != NULL)
-            free(msg->azHeaders);
-        msg->azHeaders = NULL;
-        msg->asHeaders = 0;
-
-        for (hdI = msg->hdFirst; hdI != NULL; hdI = hdI->next) { /* for each matrix header */
-            logbook(msg->l2, L2_LEVEL_DEBUG, "FIXME trace loop hdI=%.8lx, hI->name=\"%s\"", hdI, hdI->name);
-            if (hdI->name == NULL || strlen(hdI->name) == 0 || hdI->ndata == 0)
-                continue;
-            if (hdI->ndata == 0) {
-                logbook(msg->l2, L2_LEVEL_DEBUG, "header=%s, no data", hdI->name);
-            }
-            else if(hdI->ndata == 1) { /* header data is single valued */
-                logbook(msg->l2, L2_LEVEL_DEBUG, "header=%s, data=%s", hdI->name, hdI->data.s);
-                argz_add(&msg->azHeaders, &msg->asHeaders, hdI->name);
-                argz_add(&msg->azHeaders, &msg->asHeaders, hdI->data.s);
-            }
-            else { /* header data is multi valued */
-                int i;
-                for (i = 0; i < hdI->ndata; i++) {
-                    logbook(msg->l2, L2_LEVEL_DEBUG, "header=%s[%d], data=%s", hdI->name, i, hdI->data.m[i]);
-                    argz_add(&msg->azHeaders, &msg->asHeaders, hdI->name);
-                    argz_add(&msg->azHeaders, &msg->asHeaders, hdI->data.m[i]);
-                }
-            }
-        }
-    }
-    catch(ex) {
-        rethrow;
-    }
-}
-
-void headerrewrite(lmtp2nntp_t *ctx)
-{
-    headerrule_t *hrI;
-    headerdata_t *hdI, *hdNew;
-    regex_ctx_t *regex_ctx;
-#define OVECSIZE 30
-    int            ovec[OVECSIZE];
-    var_rc_t rc; char *cp; //FIXME what a bad name, it's not the returncode of this function
-
-    /* short circuit in case no headerrules were set up */
-    if (ctx->option_firstheaderrule == NULL)
-        return;
-
-    { //FIXME debug code block
-        int i;
-        headerrule_t *hrD;
-        headerdata_t *hdD;
-
-        logbook(ctx->l2, L2_LEVEL_DEBUG, "FIXME trace ---------- headerrewrite() ----------");
-        for (hrD = ctx->option_firstheaderrule; hrD != NULL; hrD = hrD->next)
-            logbook(ctx->l2, L2_LEVEL_DEBUG, "hrD->header=%s", hrD->header);
-        for (hdD = ctx->msg->hdFirst; hdD != NULL; hdD = hdD->next) {
-            if (hdD->ndata == 0)
-                logbook(ctx->l2, L2_LEVEL_DEBUG, "hdD->name=%s: (NO DATA)", hdD->name);
-            if (hdD->ndata == 1)
-                logbook(ctx->l2, L2_LEVEL_DEBUG, "hdD->name:hdD->data.s    %s %s", hdD->name, hdD->data.s);
-            if (hdD->ndata > 1)
-                for (i = 0; i < hdD->ndata; i++)
-                    logbook(ctx->l2, L2_LEVEL_DEBUG, "hdD->name:hdD->data.m[%d] %s %s", i, hdD->name, hdD->data.m[i]);
-        }
-    }
-    
-    regex_ctx = (regex_ctx_t *)mallocex(sizeof(regex_ctx_t));
-    regex_ctx->nMatch = 0;
-    regex_ctx->acpMatch = NULL;
-    regex_ctx->l2_env = ctx->l2_env;
-    regex_ctx->l2 = ctx->l2;
-    if ((rc = var_config(ctx->config_varregex, VAR_CONFIG_CB_VALUE, regex_lookup, regex_ctx)) != VAR_OK) {
-        logbook(ctx->l2, L2_LEVEL_ERROR, "configure regex callback failed with %s (%d)", var_strerror(ctx->config_varctx, rc, &cp) == VAR_OK ? cp : "Unknown Error", rc);
-        throw(0,0,0);
-    }
-    if ((rc = var_config(ctx->config_varregex, VAR_CONFIG_CB_OPERATION, operate_cb, NULL)) != VAR_OK) {
-        logbook(ctx->l2, L2_LEVEL_ERROR, "configure operate callback failed with %s (%d)", var_strerror(ctx->config_varctx, rc, &cp) == VAR_OK ? cp : "Unknown Error", rc);
-        throw(0,0,0);
-    }
-    for (hrI = ctx->option_firstheaderrule; hrI != NULL; hrI = hrI->next) { /* for each rule */
-        { //FIXME debug code block
-            int i;
-            headerrule_t *hrD;
-            headerdata_t *hdD;
-
-            logbook(ctx->l2, L2_LEVEL_DEBUG, "FIXME trace ---------- headerrewrite() ---------- MIDDLE");
-            for (hrD = ctx->option_firstheaderrule; hrD != NULL; hrD = hrD->next)
-                logbook(ctx->l2, L2_LEVEL_DEBUG, "hrD->header=%s", hrD->header);
-            for (hdD = ctx->msg->hdFirst; hdD != NULL; hdD = hdD->next) {
-                //logbook(ctx->l2, L2_LEVEL_DEBUG, "hdD=%.8lx, hdD->name=%.8lx, hdD->data.s=%.8lx", (long)hdD, (long)&hdD->name, (long)&hdD->data.s);
-                if (hdD->ndata == 0)
-                    logbook(ctx->l2, L2_LEVEL_DEBUG, "hdD->name=%s: (NO DATA)", hdD->name);
-                if (hdD->ndata == 1)
-                    logbook(ctx->l2, L2_LEVEL_DEBUG, "hdD->name:hdD->data.s    %s %s", hdD->name, hdD->data.s);
-                if (hdD->ndata > 1)
-                    for (i = 0; i < hdD->ndata; i++)
-                        logbook(ctx->l2, L2_LEVEL_DEBUG, "hdD->name:hdD->data.m[%d] %s %s", i, hdD->name, hdD->data.m[i]);
-            }
-        }
-        if (hrI->regex != NULL) {
-            logbook(ctx->l2, L2_LEVEL_DEBUG, "rule has regex %s", hrI->regex);
-            for (hdI = ctx->msg->hdFirst; hdI != NULL; hdI = hdI->next) { /* for each header */
-                if (hdI->name == NULL || strlen(hdI->name) == 0 || hdI->ndata == 0)
-                    continue;
-                regex_ctx->nMatch = pcre_exec(hrI->pcreRegex, hrI->pcreExtra, hdI->name, strlen(hdI->name), 0, 0, ovec, OVECSIZE);
-                if (regex_ctx->nMatch >= 1) {
-                    int i;
-                    char *cp;
-                    logbook(ctx->l2, L2_LEVEL_DEBUG, "regex matches, %d references", regex_ctx->nMatch);
-                    pcre_get_substring_list(hdI->name, ovec, regex_ctx->nMatch, &regex_ctx->acpMatch);
-                    if (regex_ctx->acpMatch != NULL)
-                        for (i = 0; i < regex_ctx->nMatch; i++)
-                            logbook(ctx->l2, L2_LEVEL_DEBUG, "regex reference[%d]=\'%s\'", i, regex_ctx->acpMatch[i] == NULL ? "(UNDEFINED)" : regex_ctx->acpMatch[i]);
-                    hdNew = headercreate();
-                    /* expanding regex references into header name */
-                    {
-                        var_rc_t var_rc;
-                        char *res_ptr;
-                        logbook(ctx->l2, L2_LEVEL_DEBUG, "expanding regex references in headername '%s'", hrI->header);
-                        if ((var_rc = var_expand(ctx->config_varregex, hrI->header, strlen(hrI->header), &res_ptr, NULL, FALSE)) != VAR_OK) {
-                            logbook(ctx->l2, L2_LEVEL_ERROR, "expansion of '%s' failed: %s", hrI->header, var_strerror(ctx->config_varctx, rc, &cp) == VAR_OK ? cp : "Unknown Error", rc);
-                        }
-                        logbook(ctx->l2, L2_LEVEL_DEBUG, "expansion result '%s'", res_ptr);
-                        if (strlen(res_ptr) == 0) {
-                            logbook(ctx->l2, L2_LEVEL_DEBUG, "marking deleted - emtpy headername");
-                            hdNew->name = NULL; //FIXME rename ->header to ->name
-                            /*FIXME clean up data.s and data.m */
-                            hdNew->ndata = 0;
-                        }
-                        else {
-                            hdNew->name = res_ptr; //FIXME rename ->header to ->name
-                        }
-                    }
-                    if (hrI->val == NULL) {
-                        logbook(ctx->l2, L2_LEVEL_DEBUG, "marking deleted - empty headervalue before expansion");
-                        /*FIXME clean up data.s and data.m */
-                        hdNew->ndata = 0;
-                    }
-                    else {
-                        /* expanding regex references into header value */
-                        {
-                            var_rc_t var_rc;
-                            char *res_ptr;
-                            logbook(ctx->l2, L2_LEVEL_DEBUG, "expanding regex references in header value '%s'", hrI->val);
-                            if ((var_rc = var_expand(ctx->config_varregex, hrI->val, strlen(hrI->val), &res_ptr, NULL, FALSE)) != VAR_OK) {
-                                logbook(ctx->l2, L2_LEVEL_ERROR, "expansion of '%s' failed: %s", hrI->val, var_strerror(ctx->config_varctx, rc, &cp) == VAR_OK ? cp : "Unknown Error", rc);
-                            }
-                            logbook(ctx->l2, L2_LEVEL_DEBUG, "expansion result '%s'", res_ptr);
-                            cp = res_ptr;
-                        }
-                        /* expanding variables into header value */
-                        if (hrI->val != NULL) {
-                            var_rc_t var_rc;
-                            char *res_ptr;
-                            logbook(ctx->l2, L2_LEVEL_DEBUG, "expanding variables in header value '%s'", hrI->val);
-                            if ((var_rc = var_expand(ctx->config_varctx, cp, strlen(cp), &res_ptr, NULL, FALSE)) != VAR_OK) {
-                                logbook(ctx->l2, L2_LEVEL_ERROR, "expansion of '%s' failed: %s", cp, var_strerror(ctx->config_varctx, rc, &cp) == VAR_OK ? cp : "Unknown Error", rc);
-                            }
-                            logbook(ctx->l2, L2_LEVEL_DEBUG, "expansion result '%s'", res_ptr);
-                            if (strlen(res_ptr) == 0) {
-                                logbook(ctx->l2, L2_LEVEL_DEBUG, "marking deleted - empty headervalue after expansion");
-                                /*FIXME clean up data.s and data.m */
-                                hdNew->ndata = 0;
-                            }
-                            else {
-                                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 {
-            logbook(ctx->l2, L2_LEVEL_DEBUG, "rule has no regex but static header %s", hrI->header);
-            hdNew = headercreate();
-            hdNew->name = strdupex(hrI->header); //FIXME rename ->header to ->name
-            if (hrI->val == NULL) {
-                logbook(ctx->l2, L2_LEVEL_DEBUG, "marking deleted");
-                /*FIXME clean up data.s and data.m */
-                hdNew->ndata = 0;
-            }
-            else {
-                /*FIXME clean up data.m */
-                /* expanding variables into header value */
-                var_rc_t var_rc;
-                char *res_ptr;
-                logbook(ctx->l2, L2_LEVEL_DEBUG, "expanding variables in header value '%s'", hrI->val);
-                if ((var_rc = var_expand(ctx->config_varctx, hrI->val, strlen(hrI->val), &res_ptr, NULL, FALSE)) != VAR_OK) {
-                    logbook(ctx->l2, L2_LEVEL_ERROR, "expansion of '%s' failed: %s", hrI->val, var_strerror(ctx->config_varctx, rc, &cp) == VAR_OK ? cp : "Unknown Error", rc);
-                }
-                logbook(ctx->l2, L2_LEVEL_DEBUG, "expansion result '%s'", res_ptr);
-                if (strlen(res_ptr) == 0) {
-                    logbook(ctx->l2, L2_LEVEL_DEBUG, "marking deleted - empty headervalue after expansion");
-                    /*FIXME clean up data.s and data.m */
-                    hdNew->ndata = 0;
-                }
-                else {
-                    hdNew->data.s = res_ptr;
-                    hdNew->ndata = 1;
-                }
-            }
-            for (hdI = ctx->msg->hdFirst; hdI != NULL; hdI = hdI->next) { /* for each header */
-                if (hdI->name == NULL || strlen(hdI->name) == 0)
-                    continue;
-                logbook(ctx->l2, L2_LEVEL_DEBUG, "hrI->header=%s, hdI->name=%s", hrI->header, hdI->name);
-                if (strcasecmp(hrI->header, hdI->name) == 0)
-                    break;
-            }
-            if (hdI != NULL) {
-                logbook(ctx->l2, L2_LEVEL_DEBUG, "replacing header %s", hrI->header);
-                headerreplace(hdI, hdNew);
-                if (hdNew->prev == NULL) {
-                    logbook(ctx->l2, L2_LEVEL_DEBUG, "FIXME trace #1");
-                    ctx->msg->hdFirst = hdNew;
-                }
-            }
-            else {
-                logbook(ctx->l2, L2_LEVEL_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;
-        headerrule_t *hrD;
-        headerdata_t *hdD;
-
-        logbook(ctx->l2, L2_LEVEL_DEBUG, "FIXME trace ---------- headerrewrite() ---------- FINISH");
-        for (hrD = ctx->option_firstheaderrule; hrD != NULL; hrD = hrD->next)
-            logbook(ctx->l2, L2_LEVEL_DEBUG, "hrD->header=%s", hrD->header);
-        for (hdD = ctx->msg->hdFirst; hdD != NULL; hdD = hdD->next) {
-            if (hdD->ndata == 0)
-                logbook(ctx->l2, L2_LEVEL_DEBUG, "hdD->name=%s: (NO DATA)", hdD->name);
-            if (hdD->ndata == 1)
-                logbook(ctx->l2, L2_LEVEL_DEBUG, "hdD->name:hdD->data.s    %s %s", hdD->name, hdD->data.s);
-            if (hdD->ndata > 1)
-                for (i = 0; i < hdD->ndata; i++)
-                    logbook(ctx->l2, L2_LEVEL_DEBUG, "hdD->name:hdD->data.m[%d] %s %s", i, hdD->name, hdD->data.m[i]);
-        }
-    }
-}


ossp-pkg/lmtp2nntp/lmtp2nntp_msg.c 1.4 -> 1.5

--- lmtp2nntp_msg.c      2002/03/13 14:41:13     1.4
+++ lmtp2nntp_msg.c      2002/04/18 14:09:25     1.5
@@ -460,3 +460,466 @@
     return str;
 }
 
+    //FIXME below is the header rewriting engine which must be cleaned up and integrated
+
+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)
+        throw(0,0,0);
+    if (hdC->next != NULL && hdC->next->prev == hdC)
+        throw(0,0,0);
+    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;
+    if (hdNew->prev != NULL)
+        hdNew->prev->next = hdNew;
+    if (hdNew->next != NULL)
+        hdNew->next->prev = hdNew;
+    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;
+}
+
+struct regex_ctx_st; //FIXME go into a header!
+typedef struct regex_ctx_st regex_ctx_t;
+struct regex_ctx_st {
+    int            nMatch;
+    const char   **acpMatch;
+    l2_env_t      *l2_env;
+    l2_channel_t  *l2;
+};
+
+static var_rc_t regex_lookup(
+    var_t *var, 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)
+{
+    regex_ctx_t *ctx = (regex_ctx_t *)_ctx;
+    var_rc_t rc;
+    char *cp;
+    int i;
+
+    logbook(ctx->l2, L2_LEVEL_DEBUG, "rgx_lookup variable \"%s\" (%d)", var_ptr, var_len);
+    rc = VAR_ERR_UNDEFINED_VARIABLE;
+    i = atoi(var_ptr); /* works with both '}' and '\0' termination */
+    if (i < ctx->nMatch) {
+        *val_ptr = ctx->acpMatch[i];
+        *val_len = strlen(ctx->acpMatch[i]);
+        *val_size = 0;
+        rc = VAR_OK;
+    }
+    if (rc == VAR_OK)
+        logbook(ctx->l2, L2_LEVEL_DEBUG, "rgx_lookup variable \"%s\" (%d) ok: result is \"%s\" (%d)", var_ptr, var_len, *val_ptr, *val_len);
+    else
+        logbook(ctx->l2, L2_LEVEL_DEBUG, "rgx_lookup variable \"%s\" (%d) failed: %s (%d)", var_ptr, var_len, var_strerror(var, rc, &cp) == VAR_OK ? cp : "Unknown Error", rc);
+    return rc;
+}
+
+static var_rc_t operate_cb(
+    var_t *var, void *ctx,
+    const char  *op_ptr, size_t op_len,
+    const char  *arg_ptr, size_t arg_len,
+    const char  *val_ptr, size_t val_len,
+    char **out_ptr, size_t *out_len, size_t *out_size)
+{
+    int i;
+
+    if (val_ptr == NULL) {
+        *out_ptr = "";
+        *out_len = 0;
+        *out_size = 0;
+        return VAR_OK;
+    }
+    if (op_len == 6 && strncmp(op_ptr, "return", 6) == 0) {
+        *out_ptr = malloc(arg_len);
+        *out_len = arg_len;
+        *out_size = arg_len;
+        memcpy(*out_ptr, arg_ptr, arg_len);
+        return VAR_OK;
+    }
+    else if (op_len == 5 && strncmp(op_ptr, "upper", 5) == 0) {
+        *out_ptr = malloc(val_len);
+        *out_len = val_len;
+        *out_size = val_len;
+        for (i = 0; i < val_len; i++)
+            (*out_ptr)[i] = (char)toupper((int)(val_ptr[i]));
+        return VAR_OK;
+    }
+    else if (op_len == 5 && strncmp(op_ptr, "lower", 5) == 0) {
+        *out_ptr = malloc(val_len);
+        *out_len = val_len;
+        *out_size = val_len;
+        for (i = 0; i < val_len; i++)
+            (*out_ptr)[i] = (char)tolower((int)(val_ptr[i]));
+        return VAR_OK;
+    }
+    else 
+        return VAR_ERR_UNDEFINED_OPERATION;
+}
+
+void msg_headermatrixbuildup(msg_t *msg)
+{
+    ex_t ex;
+    volatile headerdata_t *hdNew = NULL;
+    try {
+        headerdata_t *hdI, *hdP;
+        char *cp;
+
+        cp = NULL;
+        while ((cp = argz_next(msg->azHeaders, msg->asHeaders, cp)) != NULL) { /* for each message header */
+
+            /*FIXME we want O(1) here */
+            for (hdP = NULL, hdI = msg->hdFirst; hdI != NULL; hdP = hdI, hdI = hdI->next) { /* for each matrix header */
+                if (hdI->name == NULL || strlen(hdI->name) == 0 || hdI->ndata == 0)
+                    continue;
+                if (strcasecmp(cp, hdI->name) == 0)
+                    break;
+            }
+
+            if (hdI == NULL) {
+                hdNew = headercreate(); /* not found, create new */
+                hdNew->name = strdupex(cp);
+                hdI = (headerdata_t *)hdNew; hdNew = NULL; /* ex cleanup */
+                if (hdP == NULL)
+                    msg->hdFirst = hdI; /* no previous? this is the first */
+                else {
+                    hdP->next = hdI;
+                    hdI->prev = hdP;
+                }
+            }
+            cp = argz_next(msg->azHeaders, msg->asHeaders, cp);
+            if (hdI->ndata == 0) {
+                logbook(msg->l2, L2_LEVEL_DEBUG, "header=%s, currently empty", hdI->name);
+                hdI->data.s = strdupex(cp);
+                hdI->ndata = 1;
+            }
+            else if(hdI->ndata == 1) {
+                char *cpOld;
+                cpOld = hdI->data.s;
+                logbook(msg->l2, L2_LEVEL_DEBUG, "header=%s, currently single valued", hdI->name);
+                hdI->data.m = (char **)mallocex(3 * sizeof(char *));
+                hdI->data.m[0] = strdupex(cpOld); //FIXME
+                hdI->data.m[1] = strdupex(cp);
+                hdI->data.m[2] = NULL;
+                hdI->ndata = 2;
+            }
+            else {
+                logbook(msg->l2, L2_LEVEL_DEBUG, "header=%s, currently multi valued %d", hdI->name, hdI->ndata);
+                hdI->data.m = (char **)reallocex(hdI->data.m, (hdI->ndata + 2) * sizeof(char *));
+                hdI->data.m[hdI->ndata++] = strdupex(cp);
+                hdI->data.m[hdI->ndata] = NULL;
+            }
+        }
+    }
+    cleanup {
+        if (hdNew != NULL)
+            free((headerdata_t *)hdNew);
+    }
+    catch(ex) {
+        rethrow;
+    }
+}
+
+void msg_headermatrixteardwn(msg_t *msg)
+{
+    ex_t ex;
+    try {
+        headerdata_t *hdI;
+
+        if (msg->azHeaders != NULL)
+            free(msg->azHeaders);
+        msg->azHeaders = NULL;
+        msg->asHeaders = 0;
+
+        for (hdI = msg->hdFirst; hdI != NULL; hdI = hdI->next) { /* for each matrix header */
+            logbook(msg->l2, L2_LEVEL_DEBUG, "FIXME trace loop hdI=%.8lx, hI->name=\"%s\"", hdI, hdI->name);
+            if (hdI->name == NULL || strlen(hdI->name) == 0 || hdI->ndata == 0)
+                continue;
+            if (hdI->ndata == 0) {
+                logbook(msg->l2, L2_LEVEL_DEBUG, "header=%s, no data", hdI->name);
+            }
+            else if(hdI->ndata == 1) { /* header data is single valued */
+                logbook(msg->l2, L2_LEVEL_DEBUG, "header=%s, data=%s", hdI->name, hdI->data.s);
+                argz_add(&msg->azHeaders, &msg->asHeaders, hdI->name);
+                argz_add(&msg->azHeaders, &msg->asHeaders, hdI->data.s);
+            }
+            else { /* header data is multi valued */
+                int i;
+                for (i = 0; i < hdI->ndata; i++) {
+                    logbook(msg->l2, L2_LEVEL_DEBUG, "header=%s[%d], data=%s", hdI->name, i, hdI->data.m[i]);
+                    argz_add(&msg->azHeaders, &msg->asHeaders, hdI->name);
+                    argz_add(&msg->azHeaders, &msg->asHeaders, hdI->data.m[i]);
+                }
+            }
+        }
+    }
+    catch(ex) {
+        rethrow;
+    }
+}
+
+void headerrewrite(lmtp2nntp_t *ctx)
+{
+    headerrule_t *hrI;
+    headerdata_t *hdI, *hdNew;
+    regex_ctx_t *regex_ctx;
+#define OVECSIZE 30
+    int            ovec[OVECSIZE];
+    var_rc_t rc; char *cp; //FIXME what a bad name, it's not the returncode of this function
+
+    /* short circuit in case no headerrules were set up */
+    if (ctx->option_firstheaderrule == NULL)
+        return;
+
+    { //FIXME debug code block
+        int i;
+        headerrule_t *hrD;
+        headerdata_t *hdD;
+
+        logbook(ctx->l2, L2_LEVEL_DEBUG, "FIXME trace ---------- headerrewrite() ----------");
+        for (hrD = ctx->option_firstheaderrule; hrD != NULL; hrD = hrD->next)
+            logbook(ctx->l2, L2_LEVEL_DEBUG, "hrD->header=%s", hrD->header);
+        for (hdD = ctx->msg->hdFirst; hdD != NULL; hdD = hdD->next) {
+            if (hdD->ndata == 0)
+                logbook(ctx->l2, L2_LEVEL_DEBUG, "hdD->name=%s: (NO DATA)", hdD->name);
+            if (hdD->ndata == 1)
+                logbook(ctx->l2, L2_LEVEL_DEBUG, "hdD->name:hdD->data.s    %s %s", hdD->name, hdD->data.s);
+            if (hdD->ndata > 1)
+                for (i = 0; i < hdD->ndata; i++)
+                    logbook(ctx->l2, L2_LEVEL_DEBUG, "hdD->name:hdD->data.m[%d] %s %s", i, hdD->name, hdD->data.m[i]);
+        }
+    }
+    
+    regex_ctx = (regex_ctx_t *)mallocex(sizeof(regex_ctx_t));
+    regex_ctx->nMatch = 0;
+    regex_ctx->acpMatch = NULL;
+    regex_ctx->l2_env = ctx->l2_env;
+    regex_ctx->l2 = ctx->l2;
+    if ((rc = var_config(ctx->config_varregex, VAR_CONFIG_CB_VALUE, regex_lookup, regex_ctx)) != VAR_OK) {
+        logbook(ctx->l2, L2_LEVEL_ERROR, "configure regex callback failed with %s (%d)", var_strerror(ctx->config_varctx, rc, &cp) == VAR_OK ? cp : "Unknown Error", rc);
+        throw(0,0,0);
+    }
+    if ((rc = var_config(ctx->config_varregex, VAR_CONFIG_CB_OPERATION, operate_cb, NULL)) != VAR_OK) {
+        logbook(ctx->l2, L2_LEVEL_ERROR, "configure operate callback failed with %s (%d)", var_strerror(ctx->config_varctx, rc, &cp) == VAR_OK ? cp : "Unknown Error", rc);
+        throw(0,0,0);
+    }
+    for (hrI = ctx->option_firstheaderrule; hrI != NULL; hrI = hrI->next) { /* for each rule */
+        { //FIXME debug code block
+            int i;
+            headerrule_t *hrD;
+            headerdata_t *hdD;
+
+            logbook(ctx->l2, L2_LEVEL_DEBUG, "FIXME trace ---------- headerrewrite() ---------- MIDDLE");
+            for (hrD = ctx->option_firstheaderrule; hrD != NULL; hrD = hrD->next)
+                logbook(ctx->l2, L2_LEVEL_DEBUG, "hrD->header=%s", hrD->header);
+            for (hdD = ctx->msg->hdFirst; hdD != NULL; hdD = hdD->next) {
+                //logbook(ctx->l2, L2_LEVEL_DEBUG, "hdD=%.8lx, hdD->name=%.8lx, hdD->data.s=%.8lx", (long)hdD, (long)&hdD->name, (long)&hdD->data.s);
+                if (hdD->ndata == 0)
+                    logbook(ctx->l2, L2_LEVEL_DEBUG, "hdD->name=%s: (NO DATA)", hdD->name);
+                if (hdD->ndata == 1)
+                    logbook(ctx->l2, L2_LEVEL_DEBUG, "hdD->name:hdD->data.s    %s %s", hdD->name, hdD->data.s);
+                if (hdD->ndata > 1)
+                    for (i = 0; i < hdD->ndata; i++)
+                        logbook(ctx->l2, L2_LEVEL_DEBUG, "hdD->name:hdD->data.m[%d] %s %s", i, hdD->name, hdD->data.m[i]);
+            }
+        }
+        if (hrI->regex != NULL) {
+            logbook(ctx->l2, L2_LEVEL_DEBUG, "rule has regex %s", hrI->regex);
+            for (hdI = ctx->msg->hdFirst; hdI != NULL; hdI = hdI->next) { /* for each header */
+                if (hdI->name == NULL || strlen(hdI->name) == 0 || hdI->ndata == 0)
+                    continue;
+                regex_ctx->nMatch = pcre_exec(hrI->pcreRegex, hrI->pcreExtra, hdI->name, strlen(hdI->name), 0, 0, ovec, OVECSIZE);
+                if (regex_ctx->nMatch >= 1) {
+                    int i;
+                    char *cp;
+                    logbook(ctx->l2, L2_LEVEL_DEBUG, "regex matches, %d references", regex_ctx->nMatch);
+                    pcre_get_substring_list(hdI->name, ovec, regex_ctx->nMatch, &regex_ctx->acpMatch);
+                    if (regex_ctx->acpMatch != NULL)
+                        for (i = 0; i < regex_ctx->nMatch; i++)
+                            logbook(ctx->l2, L2_LEVEL_DEBUG, "regex reference[%d]=\'%s\'", i, regex_ctx->acpMatch[i] == NULL ? "(UNDEFINED)" : regex_ctx->acpMatch[i]);
+                    hdNew = headercreate();
+                    /* expanding regex references into header name */
+                    {
+                        var_rc_t var_rc;
+                        char *res_ptr;
+                        logbook(ctx->l2, L2_LEVEL_DEBUG, "expanding regex references in headername '%s'", hrI->header);
+                        if ((var_rc = var_expand(ctx->config_varregex, hrI->header, strlen(hrI->header), &res_ptr, NULL, FALSE)) != VAR_OK) {
+                            logbook(ctx->l2, L2_LEVEL_ERROR, "expansion of '%s' failed: %s", hrI->header, var_strerror(ctx->config_varctx, rc, &cp) == VAR_OK ? cp : "Unknown Error", rc);
+                        }
+                        logbook(ctx->l2, L2_LEVEL_DEBUG, "expansion result '%s'", res_ptr);
+                        if (strlen(res_ptr) == 0) {
+                            logbook(ctx->l2, L2_LEVEL_DEBUG, "marking deleted - emtpy headername");
+                            hdNew->name = NULL; //FIXME rename ->header to ->name
+                            /*FIXME clean up data.s and data.m */
+                            hdNew->ndata = 0;
+                        }
+                        else {
+                            hdNew->name = res_ptr; //FIXME rename ->header to ->name
+                        }
+                    }
+                    if (hrI->val == NULL) {
+                        logbook(ctx->l2, L2_LEVEL_DEBUG, "marking deleted - empty headervalue before expansion");
+                        /*FIXME clean up data.s and data.m */
+                        hdNew->ndata = 0;
+                    }
+                    else {
+                        /* expanding regex references into header value */
+                        {
+                            var_rc_t var_rc;
+                            char *res_ptr;
+                            logbook(ctx->l2, L2_LEVEL_DEBUG, "expanding regex references in header value '%s'", hrI->val);
+                            if ((var_rc = var_expand(ctx->config_varregex, hrI->val, strlen(hrI->val), &res_ptr, NULL, FALSE)) != VAR_OK) {
+                                logbook(ctx->l2, L2_LEVEL_ERROR, "expansion of '%s' failed: %s", hrI->val, var_strerror(ctx->config_varctx, rc, &cp) == VAR_OK ? cp : "Unknown Error", rc);
+                            }
+                            logbook(ctx->l2, L2_LEVEL_DEBUG, "expansion result '%s'", res_ptr);
+                            cp = res_ptr;
+                        }
+                        /* expanding variables into header value */
+                        if (hrI->val != NULL) {
+                            var_rc_t var_rc;
+                            char *res_ptr;
+                            logbook(ctx->l2, L2_LEVEL_DEBUG, "expanding variables in header value '%s'", hrI->val);
+                            if ((var_rc = var_expand(ctx->config_varctx, cp, strlen(cp), &res_ptr, NULL, FALSE)) != VAR_OK) {
+                                logbook(ctx->l2, L2_LEVEL_ERROR, "expansion of '%s' failed: %s", cp, var_strerror(ctx->config_varctx, rc, &cp) == VAR_OK ? cp : "Unknown Error", rc);
+                            }
+                            logbook(ctx->l2, L2_LEVEL_DEBUG, "expansion result '%s'", res_ptr);
+                            if (strlen(res_ptr) == 0) {
+                                logbook(ctx->l2, L2_LEVEL_DEBUG, "marking deleted - empty headervalue after expansion");
+                                /*FIXME clean up data.s and data.m */
+                                hdNew->ndata = 0;
+                            }
+                            else {
+                                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 {
+            logbook(ctx->l2, L2_LEVEL_DEBUG, "rule has no regex but static header %s", hrI->header);
+            hdNew = headercreate();
+            hdNew->name = strdupex(hrI->header); //FIXME rename ->header to ->name
+            if (hrI->val == NULL) {
+                logbook(ctx->l2, L2_LEVEL_DEBUG, "marking deleted");
+                /*FIXME clean up data.s and data.m */
+                hdNew->ndata = 0;
+            }
+            else {
+                /*FIXME clean up data.m */
+                /* expanding variables into header value */
+                var_rc_t var_rc;
+                char *res_ptr;
+                logbook(ctx->l2, L2_LEVEL_DEBUG, "expanding variables in header value '%s'", hrI->val);
+                if ((var_rc = var_expand(ctx->config_varctx, hrI->val, strlen(hrI->val), &res_ptr, NULL, FALSE)) != VAR_OK) {
+                    logbook(ctx->l2, L2_LEVEL_ERROR, "expansion of '%s' failed: %s", hrI->val, var_strerror(ctx->config_varctx, rc, &cp) == VAR_OK ? cp : "Unknown Error", rc);
+                }
+                logbook(ctx->l2, L2_LEVEL_DEBUG, "expansion result '%s'", res_ptr);
+                if (strlen(res_ptr) == 0) {
+                    logbook(ctx->l2, L2_LEVEL_DEBUG, "marking deleted - empty headervalue after expansion");
+                    /*FIXME clean up data.s and data.m */
+                    hdNew->ndata = 0;
+                }
+                else {
+                    hdNew->data.s = res_ptr;
+                    hdNew->ndata = 1;
+                }
+            }
+            for (hdI = ctx->msg->hdFirst; hdI != NULL; hdI = hdI->next) { /* for each header */
+                if (hdI->name == NULL || strlen(hdI->name) == 0)
+                    continue;
+                logbook(ctx->l2, L2_LEVEL_DEBUG, "hrI->header=%s, hdI->name=%s", hrI->header, hdI->name);
+                if (strcasecmp(hrI->header, hdI->name) == 0)
+                    break;
+            }
+            if (hdI != NULL) {
+                logbook(ctx->l2, L2_LEVEL_DEBUG, "replacing header %s", hrI->header);
+                headerreplace(hdI, hdNew);
+                if (hdNew->prev == NULL) {
+                    logbook(ctx->l2, L2_LEVEL_DEBUG, "FIXME trace #1");
+                    ctx->msg->hdFirst = hdNew;
+                }
+            }
+            else {
+                logbook(ctx->l2, L2_LEVEL_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;
+        headerrule_t *hrD;
+        headerdata_t *hdD;
+
+        logbook(ctx->l2, L2_LEVEL_DEBUG, "FIXME trace ---------- headerrewrite() ---------- FINISH");
+        for (hrD = ctx->option_firstheaderrule; hrD != NULL; hrD = hrD->next)
+            logbook(ctx->l2, L2_LEVEL_DEBUG, "hrD->header=%s", hrD->header);
+        for (hdD = ctx->msg->hdFirst; hdD != NULL; hdD = hdD->next) {
+            if (hdD->ndata == 0)
+                logbook(ctx->l2, L2_LEVEL_DEBUG, "hdD->name=%s: (NO DATA)", hdD->name);
+            if (hdD->ndata == 1)
+                logbook(ctx->l2, L2_LEVEL_DEBUG, "hdD->name:hdD->data.s    %s %s", hdD->name, hdD->data.s);
+            if (hdD->ndata > 1)
+                for (i = 0; i < hdD->ndata; i++)
+                    logbook(ctx->l2, L2_LEVEL_DEBUG, "hdD->name:hdD->data.m[%d] %s %s", i, hdD->name, hdD->data.m[i]);
+        }
+    }
+}

CVSTrac 2.0.1