/* This file is part of Mailfromd. -*- c -*- Copyright (C) 2008 Sergey Poznyakoff This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "msg.h" struct current_header { mu_header_t hdr; }; static void * alloc_header() { return xzalloc(sizeof(struct current_header)); } static void destroy_header(void *data) { struct current_header *chdr = data; mu_header_destroy(&chdr->hdr, NULL); free(chdr); } static void free_header(void *data) { struct current_header *chdr = data; mu_header_destroy(&chdr->hdr, NULL); } MF_DECLARE_DATA(HEADER, alloc_header, destroy_header, free_header) static mu_header_t get_current_header(eval_environ_t env, mu_stream_t mstr) { struct current_header *chdr = MF_GET_DATA; if (!chdr->hdr) { mu_header_t hdr; char *text; int rc; mu_off_t size; size_t total; size_t start; rc = mu_stream_size (mstr, &size); MF_ASSERT(rc == 0, mfe_failure, "mu_stream_size: %s", mu_strerror (rc)); text = malloc (size + 1); MF_ASSERT(text != NULL, mfe_failure, _("Not enough memory")); rc = mu_stream_seek(mstr, 0, SEEK_SET); MF_ASSERT(rc == 0, mfe_failure, "mu_stream_seek: %s", mu_strerror(rc)); for (total = 0; total < size;) { size_t nrd; rc = mu_stream_sequential_read(mstr, text + total, size - total, &nrd); if (rc || nrd == 0) break; total += nrd; } text[total] = 0; /* FIXME: Reposition the stream at its end. This call may happen in the middle of capturing so I have to make sure to not disturb the capturing process. FIXME: MU: The env_reposition call is a kludge necessary because MU stream interface does not offer mu_stream_tell function. */ env_reposition(env); if (memcmp (text, "From ", 5) == 0) start = strcspn (text, "\n") + 1; else start = 0; rc = mu_header_create (&hdr, text + start, total - start, NULL); free(text); MF_ASSERT(rc == 0, mfe_failure, "mu_header_create: %s", mu_strerror (rc)); chdr->hdr = hdr; } return chdr->hdr; } /* number current_header_count([string name]) */ MF_STATE(eoh) MF_STATE(body) MF_STATE(eom) MF_CAPTURE MF_DEFUN(current_header_count, NUMBER, OPTIONAL, STRING name) { mu_header_t hdr = get_current_header(env, env_get_stream(env)); size_t total; size_t count; int rc = mu_header_get_field_count (hdr, &total); MF_ASSERT(rc == 0, mfe_failure, "mu_header_get_field_count: %s", mu_strerror (rc)); if (MF_DEFINED(name)) { size_t i; count = 0; for (i = 1; i <= total; i++) { const char *sptr; if (mu_header_sget_field_name(hdr, i, &sptr) == 0 && strcasecmp(sptr, name) == 0) count++; } } else count = total; MF_RETURN(count); } END /* string current_header_nth_name(number index) */ MF_STATE(eoh) MF_STATE(body) MF_STATE(eom) MF_CAPTURE MF_DEFUN(current_header_nth_name, STRING, NUMBER index) { mu_header_t hdr = get_current_header(env, env_get_stream(env)); const char *sptr; int rc = mu_header_sget_field_name(hdr, index, &sptr); if (rc == MU_ERR_NOENT) MF_THROW(mfe_not_found, _("requested item (#%ld) not found"), index); else if (rc != 0) MF_THROW(mfe_failure, "mu_header_sget_field_name: %s", mu_strerror(rc)); MF_RETURN_STRING(sptr); } END /* string current_header_nth_value(number index) */ MF_STATE(eoh) MF_STATE(body) MF_STATE(eom) MF_CAPTURE MF_DEFUN(current_header_nth_value, STRING, NUMBER index) { mu_header_t hdr = get_current_header(env, env_get_stream(env)); const char *sptr; int rc = mu_header_sget_field_value(hdr, index, &sptr); if (rc == MU_ERR_NOENT) MF_THROW(mfe_not_found, _("requested item (#%ld) not found"), index); else if (rc != 0) MF_THROW(mfe_failure, "mu_header_sget_field_name: %s", mu_strerror(rc)); MF_RETURN_STRING(sptr); } END /* string current_header(string name[, number index]) */ MF_STATE(eoh) MF_STATE(body) MF_STATE(eom) MF_CAPTURE MF_DEFUN(current_header, STRING, STRING name, OPTIONAL, NUMBER index) { mu_header_t hdr = get_current_header(env, env_get_stream(env)); const char *sptr; int rc = mu_header_sget_value_n(hdr, name, MF_OPTVAL(index, 1), &sptr); if (rc == MU_ERR_NOENT) MF_THROW(mfe_not_found, _("requested item (%s,%ld) not found"), name, MF_OPTVAL(index, 1)); else if (rc != 0) MF_THROW(mfe_failure, "mu_header_sget_field_name: %s", mu_strerror(rc)); MF_RETURN_STRING(sptr); } END MF_INIT