Index: ossp-pkg/lmtp2nntp/lmtp2nntp_config.c RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/lmtp2nntp_config.c,v rcsdiff -q -kk '-r1.70' '-r1.71' -u '/v/ossp/cvs/ossp-pkg/lmtp2nntp/lmtp2nntp_config.c,v' 2>/dev/null --- 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, ®ex_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]); - } - } -} Index: ossp-pkg/lmtp2nntp/lmtp2nntp_msg.c RCS File: /v/ossp/cvs/ossp-pkg/lmtp2nntp/lmtp2nntp_msg.c,v rcsdiff -q -kk '-r1.4' '-r1.5' -u '/v/ossp/cvs/ossp-pkg/lmtp2nntp/lmtp2nntp_msg.c,v' 2>/dev/null --- 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, ®ex_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]); + } + } +}