/* $Cambridge: hermes/src/prayer/cmd/cmd_attachments.c,v 1.2 2008/05/19 15:55:54 dpc22 Exp $ */
/************************************************
 *    Prayer - a Webmail Interface              *
 ************************************************/

/* Copyright (c) University of Cambridge 2000 - 2008 */
/* See the file NOTICE for conditions of use and distribution. */

#include "prayer_session.h"

static void generate_form(struct session *session)
{
    struct template_vals *tvals = session->template_vals;
    struct request *request = session->request;
    struct draft *draft = session->draft;
    struct buffer *b = request->write_buffer;
    unsigned long count;
    struct attlist *a;

    for (count = 0, a = draft->attlist; a; a = a->next, count++) {
        template_vals_foreach_init(tvals, "@atts", count);
        template_vals_foreach_ulong(tvals, "@atts", count, "offset", count+1);
        template_vals_foreach_string(tvals, "@atts", count, "name", a->name);
        template_vals_foreach_string(tvals, "@atts", count, "type", a->type);
        template_vals_foreach_ulong(tvals, "@atts", count, "size", a->size);
    }

    session_seed_template(session, tvals);
    template_expand("attachments", tvals, b);
    response_html(request, 200);        /* Success */
}

static void process_form(struct session *session)
{
    struct config *config = session->config;
    struct request *request = session->request;
    struct draft *draft = session->draft;
    struct assoc *hdrs = assoc_create(request->pool, 16, T);
    char *start, *end;
    char *type, *disp, *encoding, *name, *s;
    unsigned long len;

    if (!request_decode_post_multipart(request, hdrs, &start, &end))
        return;

    if (end > start)
        len = (char *) end - (char *) start;
    else
        len = 0;

    if ((config->draft_att_single_max > 0) &&
        (len > config->draft_att_single_max)) {
        session_message(session,
                        "Attachment too large: %lu bytes exceeds limit %lu",
                        len, config->draft_att_single_max);
        session_log(session,
                    ("[cmd_attachments] Attachment too large: "
                     "%lu bytes exceeds limit %lu"),
                    len, config->draft_att_single_max);
        return;
    }

    if ((config->draft_att_total_max > 0) &&
        ((len + draft_att_size(draft)) > config->draft_att_total_max)) {
        session_message(session,
                        "Total size of attachments exceeds limit: %lu bytes",
                        config->draft_att_total_max);
        session_log(session,
                    ("[cmd_attachments] Total size of attachments "
                     "exceeds limit: %lu bytes"),
                    config->draft_att_total_max);
        return;
    }


    if (!(type = assoc_lookup(hdrs, "content-type")))
        type = "application/octet-stream";

    /* Opera attaches filename to Content-Type header e.g:
     *   Content-Type: application/octet-stream; name="<whatever>"
     */
    if ((s = strchr(type, ';')))
        *s = '\0';

    if (!(encoding = assoc_lookup(hdrs, "content-transfer-encoding")))
        encoding = "";

    name = "";

    if ((disp = assoc_lookup(hdrs, "content-disposition"))) {
        for (s = disp; *s; s++) {
            if (!strncasecmp(s, "filename=\"", strlen("filename=\""))) {
                name = s = s + strlen("filename=\"");
                while (*s && (*s != '"'))
                    s++;
                *s = '\0';
                name = string_trim_whitespace(name);
                break;
            } else if (!strncasecmp(s, "filename=", strlen("filename="))) {
                name = s + strlen("filename=");
                name = string_trim_whitespace(name);
                break;
            }
        }
    }

    /* Isolate last component of name */
    if ((s = strrchr(name, '/')))       /* Unix names */
        name = s + 1;
    else if ((s = strrchr(name, '\\'))) /* Windows names */
        name = s + 1;

    /* Mac Netscape sends names with URL encoding. Sigh! */
    if (name && name[0])
        name = string_url_decode(name);

    draft_add_attachment(draft, name, type, encoding, NIL, 0, start, len);

    session_message(session, "Added attachment \"%s\"", name);
    session_log(session,
                "[cmd_attachments] Added attachment \"%s\" (%lu bytes)",
                name, len);
}

void cmd_attachments(struct session *session)
{
    struct request *request = session->request;

    if ((request->argc >= 2) && (!strcmp(request->argv[1], "cancel"))) {
        session_redirect(session, request, "compose");
        return;
    }

    if (request->method == POST)
        process_form(session);

    generate_form(session);
}
