int sieve_execute_bytecode(sieve_execute_t *exe, sieve_interp_t *interp, void *script_context, void *message_context) { action_list_t *actions = NULL; notify_list_t *notify_list = NULL; /* notify_action_t *notify_action;*/ action_t lastaction = -1; int ret; char actions_string[ACTIONS_STRING_LEN] = ""; const char *errmsg = NULL; strarray_t imapflags = STRARRAY_INITIALIZER; if (!interp) return SIEVE_FAIL; if (interp->notify) { notify_list = new_notify_list(); if (notify_list == NULL) { return do_sieve_error(SIEVE_NOMEM, interp, script_context, message_context, &imapflags, actions, notify_list, lastaction, 0, actions_string, errmsg); } } actions = new_action_list(); if (actions == NULL) { ret = do_sieve_error(SIEVE_NOMEM, interp, script_context, message_context, &imapflags, actions, notify_list, lastaction, 0, actions_string, errmsg); } else { ret = sieve_eval_bc(exe, 0, interp, script_context, message_context, &imapflags, actions, notify_list, &errmsg); if (ret < 0) { ret = do_sieve_error(SIEVE_RUN_ERROR, interp, script_context, message_context, &imapflags, actions, notify_list, lastaction, 0, actions_string, errmsg); } else { ret = do_action_list(interp, script_context, message_context, &imapflags, actions, notify_list, actions_string, errmsg); } } strarray_fini(&imapflags); return ret; }
static int do_action_list(sieve_interp_t *interp, void *script_context, void *message_context, strarray_t *imapflags, action_list_t *actions, notify_list_t *notify_list, /* notify_action_t *notify_action,*/ char *actions_string, const char *errmsg) { action_list_t *a; action_t lastaction = -1; int ret = 0; int implicit_keep = 1; strcpy(actions_string,"Action(s) taken:\n"); /* now perform actions attached to m */ a = actions; while (a != NULL) { lastaction = a->a; errmsg = NULL; implicit_keep = implicit_keep && !a->cancel_keep; switch (a->a) { case ACTION_REJECT: if (!interp->reject) return SIEVE_INTERNAL_ERROR; ret = interp->reject(&a->u.rej, interp->interp_context, script_context, message_context, &errmsg); free(interp->lastitem); interp->lastitem = xstrdup(a->u.rej.msg); if (ret == SIEVE_OK) snprintf(actions_string+strlen(actions_string), ACTIONS_STRING_LEN-strlen(actions_string), "Rejected with: %s\n", a->u.rej.msg); break; case ACTION_FILEINTO: if (!interp->fileinto) return SIEVE_INTERNAL_ERROR; ret = interp->fileinto(&a->u.fil, interp->interp_context, script_context, message_context, &errmsg); free(interp->lastitem); interp->lastitem = xstrdup(a->u.fil.mailbox); if (ret == SIEVE_OK) snprintf(actions_string+strlen(actions_string), ACTIONS_STRING_LEN-strlen(actions_string), "Filed into: %s\n",a->u.fil.mailbox); break; case ACTION_KEEP: if (!interp->keep) return SIEVE_INTERNAL_ERROR; ret = interp->keep(&a->u.keep, interp->interp_context, script_context, message_context, &errmsg); free(interp->lastitem); interp->lastitem = NULL; if (ret == SIEVE_OK) snprintf(actions_string+strlen(actions_string), ACTIONS_STRING_LEN-strlen(actions_string), "Kept\n"); break; case ACTION_REDIRECT: if (!interp->redirect) return SIEVE_INTERNAL_ERROR; ret = interp->redirect(&a->u.red, interp->interp_context, script_context, message_context, &errmsg); free(interp->lastitem); interp->lastitem = xstrdup(a->u.red.addr); if (ret == SIEVE_OK) snprintf(actions_string+strlen(actions_string), ACTIONS_STRING_LEN-strlen(actions_string), "Redirected to %s\n", a->u.red.addr); break; case ACTION_DISCARD: if (interp->discard) /* discard is optional */ ret = interp->discard(NULL, interp->interp_context, script_context, message_context, &errmsg); free(interp->lastitem); interp->lastitem = NULL; if (ret == SIEVE_OK) snprintf(actions_string+strlen(actions_string), ACTIONS_STRING_LEN-strlen(actions_string), "Discarded\n"); break; case ACTION_VACATION: { if (!interp->vacation) return SIEVE_INTERNAL_ERROR; /* first, let's figure out if we should respond to this */ ret = interp->vacation->autorespond(&a->u.vac.autoresp, interp->interp_context, script_context, message_context, &errmsg); free(interp->lastitem); interp->lastitem = NULL; if (ret == SIEVE_OK) { /* send the response */ ret = interp->vacation->send_response(&a->u.vac.send, interp->interp_context, script_context, message_context, &errmsg); if (ret == SIEVE_OK) snprintf(actions_string+strlen(actions_string), ACTIONS_STRING_LEN-strlen(actions_string), "Sent vacation reply\n"); } else if (ret == SIEVE_DONE) { snprintf(actions_string+strlen(actions_string), ACTIONS_STRING_LEN-strlen(actions_string), "Vacation reply suppressed\n"); ret = SIEVE_OK; } break; } case ACTION_SETFLAG: strarray_fini(imapflags); break; case ACTION_ADDFLAG: strarray_add_case(imapflags, a->u.fla.flag); free(interp->lastitem); interp->lastitem = xstrdup(a->u.fla.flag); break; case ACTION_REMOVEFLAG: strarray_remove_all_case(imapflags, a->u.fla.flag); free(interp->lastitem); interp->lastitem = xstrdup(a->u.fla.flag); break; case ACTION_MARK: { int n = interp->markflags->count; ret = SIEVE_OK; while (n) { strarray_add_case(imapflags, interp->markflags->data[--n]); } free(interp->lastitem); interp->lastitem = NULL; break; } case ACTION_UNMARK: { int n = interp->markflags->count; ret = SIEVE_OK; while (n) { strarray_remove_all_case(imapflags, interp->markflags->data[--n]); } free(interp->lastitem); interp->lastitem = NULL; break; } case ACTION_NONE: break; default: ret = SIEVE_INTERNAL_ERROR; break; } a = a->next; if (ret != SIEVE_OK) { /* uh oh! better bail! */ break; } } return do_sieve_error(ret, interp, script_context, message_context, imapflags, actions, notify_list, lastaction, implicit_keep, actions_string, errmsg); }
static int do_sieve_error(int ret, sieve_interp_t *interp, void *script_context, void *message_context, strarray_t *imapflags, action_list_t *actions, notify_list_t *notify_list, /* notify_action_t *notify_action,*/ int lastaction, int implicit_keep, char *actions_string, const char *errmsg ) { if (ret != SIEVE_OK) { if (lastaction == -1) /* we never executed an action */ snprintf(actions_string+strlen(actions_string), ACTIONS_STRING_LEN-strlen(actions_string), "script execution failed: %s\n", errmsg ? errmsg : sieve_errstr(ret)); else snprintf(actions_string+strlen(actions_string), ACTIONS_STRING_LEN-strlen(actions_string), "%s action failed: %s\n", action_to_string(lastaction), errmsg ? errmsg : sieve_errstr(ret)); } /* Process notify actions */ if (interp->notify && notify_list) { notify_list_t *n = notify_list; int notify_ret = SIEVE_OK; while (n != NULL) { if (n->isactive) { lastaction = ACTION_NOTIFY; notify_ret = send_notify_callback(interp, message_context, script_context,n, actions_string, &errmsg); ret |= notify_ret; } n = n->next; } if (notify_list) free_notify_list(notify_list); notify_list = NULL; /* don't try any notifications again */ if (notify_ret != SIEVE_OK) return do_sieve_error(ret, interp, script_context, message_context, imapflags, actions, notify_list, lastaction, implicit_keep, actions_string, errmsg); } if ((ret != SIEVE_OK) && interp->execute_err) { char buf[ERR_BUF_SIZE]; if (lastaction == -1) /* we never executed an action */ snprintf(buf, ERR_BUF_SIZE, "%s", errmsg ? errmsg : sieve_errstr(ret)); else { if (interp->lastitem) { snprintf(buf, ERR_BUF_SIZE, "%s (%s): %s", action_to_string(lastaction), interp->lastitem, errmsg ? errmsg : sieve_errstr(ret)); } else { snprintf(buf, ERR_BUF_SIZE, "%s: %s", action_to_string(lastaction), errmsg ? errmsg : sieve_errstr(ret)); } } ret |= interp->execute_err(buf, interp->interp_context, script_context, message_context); } if (implicit_keep) { sieve_keep_context_t keep_context; int keep_ret; keep_context.imapflags = imapflags; lastaction = ACTION_KEEP; keep_ret = interp->keep(&keep_context, interp->interp_context, script_context, message_context, &errmsg); ret |= keep_ret; if (keep_ret == SIEVE_OK) snprintf(actions_string+strlen(actions_string), ACTIONS_STRING_LEN-strlen(actions_string), "Kept\n"); else { implicit_keep = 0; /* don't try an implicit keep again */ return do_sieve_error(ret, interp, script_context, message_context, imapflags, actions, notify_list, lastaction, implicit_keep, actions_string, errmsg); } } if (actions) free_action_list(actions); return ret; }