Esempio n. 1
0
static int
virtual_config_parse_line(struct virtual_parse_context *ctx, const char *line,
                          const char **error_r)
{
    struct mail_user *user = ctx->mbox->storage->storage.user;
    struct virtual_backend_box *bbox;
    const char *p;
    bool no_wildcards = FALSE;

    if (*line == ' ' || *line == '\t') {
        /* continues the previous search rule */
        if (ctx->rule_idx == array_count(&ctx->mbox->backend_boxes)) {
            *error_r = "Search rule without a mailbox";
            return -1;
        }
        while (*line == ' ' || *line == '\t') line++;
        str_append_c(ctx->rule, ' ');
        str_append(ctx->rule, line);
        return 0;
    }
    /* if there is no rule yet, it means we want the previous mailboxes
       to use the rule that comes later */
    if (str_len(ctx->rule) > 0) {
        if (virtual_config_add_rule(ctx, error_r) < 0)
            return -1;
    }
    if (!uni_utf8_str_is_valid(line)) {
        *error_r = t_strdup_printf("Mailbox name not UTF-8: %s",
                                   line);
        return -1;
    }

    /* new mailbox. the search args are added to it later. */
    bbox = p_new(ctx->pool, struct virtual_backend_box, 1);
    bbox->virtual_mbox = ctx->mbox;
    if (strcasecmp(line, "INBOX") == 0)
        line = "INBOX";
    bbox->name = p_strdup(ctx->pool, line);
    switch (bbox->name[0]) {
    case '+':
        bbox->name++;
        bbox->clear_recent = TRUE;
        break;
    case '-':
        bbox->name++;
        bbox->negative_match = TRUE;
        break;
    case '!':
        /* save messages here */
        if (ctx->mbox->save_bbox != NULL) {
            *error_r = "Multiple save mailboxes defined";
            return -1;
        }
        bbox->name++;
        ctx->mbox->save_bbox = bbox;
        no_wildcards = TRUE;
        break;
    }
    if (bbox->name[0] == '/') {
        /* [+-!]/metadata entry:value */
        if ((p = strchr(bbox->name, ':')) == NULL) {
            *error_r = "':' separator missing between metadata entry name and value";
            return -1;
        }
        bbox->metadata_entry = p_strdup_until(ctx->pool, bbox->name, p++);
        bbox->metadata_value = p;
        if (!imap_metadata_verify_entry_name(bbox->metadata_entry, error_r))
            return -1;
        no_wildcards = TRUE;
    }

    if (!no_wildcards &&
            (strchr(bbox->name, '*') != NULL ||
             strchr(bbox->name, '%') != NULL)) {
        bbox->glob = imap_match_init(ctx->pool, bbox->name, TRUE, ctx->sep);
        ctx->have_wildcards = TRUE;
    }
    if (bbox->metadata_entry == NULL) {
        /* now that the prefix characters have been processed,
           find the namespace */
        bbox->ns = strcasecmp(bbox->name, "INBOX") == 0 ?
                   mail_namespace_find_inbox(user->namespaces) :
                   mail_namespace_find(user->namespaces, bbox->name);
        if (bbox->ns == NULL) {
            *error_r = t_strdup_printf("Namespace not found for %s",
                                       bbox->name);
            return -1;
        }
        if (strcmp(bbox->name, ctx->mbox->box.vname) == 0) {
            *error_r = "Virtual mailbox can't point to itself";
            return -1;
        }
        ctx->have_mailbox_defines = TRUE;
    }

    array_append(&ctx->mbox->backend_boxes, &bbox, 1);
    return 0;
}
Esempio n. 2
0
static int
cmd_setmetadata_parse_entryvalue(struct imap_setmetadata_context *ctx,
                                 const char **entry_r,
                                 const struct imap_arg **value_r)
{
    const struct imap_arg *args;
    const char *name, *error;
    int ret;
    bool fatal;

    /* parse the entry name */
    ret = imap_parser_read_args(ctx->parser, 1,
                                IMAP_PARSE_FLAG_INSIDE_LIST, &args);
    if (ret >= 0) {
        if (ret == 0) {
            /* ')' found */
            *entry_r = NULL;
            return 1;
        }
        if (!imap_arg_get_astring(args, &name)) {
            client_send_command_error(ctx->cmd,
                                      "Entry name isn't astring");
            return -1;
        }

        ret = imap_parser_read_args(ctx->parser, 2,
                                    IMAP_PARSE_FLAG_INSIDE_LIST |
                                    IMAP_PARSE_FLAG_LITERAL_SIZE |
                                    IMAP_PARSE_FLAG_LITERAL8, &args);
    }
    if (ret < 0) {
        if (ret == -2)
            return 0;
        error = imap_parser_get_error(ctx->parser, &fatal);
        if (fatal) {
            client_disconnect_with_error(ctx->cmd->client, error);
            return -1;
        }
        client_send_command_error(ctx->cmd, error);
        return -1;
    }
    if (args[1].type == IMAP_ARG_EOL) {
        client_send_command_error(ctx->cmd, "Entry value missing");
        return -1;
    }
    if (args[1].type == IMAP_ARG_LIST) {
        client_send_command_error(ctx->cmd, "Entry value can't be a list");
        return -1;
    }
    if (!ctx->cmd_error_sent &&
            !imap_metadata_verify_entry_name(name, &error)) {
        client_send_command_error(ctx->cmd, error);
        ctx->cmd_error_sent = TRUE;
    }
    if (ctx->cmd_error_sent) {
        ctx->cmd->param_error = FALSE;
        ctx->cmd->state = CLIENT_COMMAND_STATE_WAIT_INPUT;

        ctx->failed = TRUE;
        if (args[1].type == IMAP_ARG_LITERAL_SIZE) {
            /* client won't see "+ OK", so we can abort
               immediately */
            ctx->cmd->client->input_skip_line = FALSE;
            return -1;
        }
    }

    /* entry names are case-insensitive. handle this by using only
       lowercase names. */
    *entry_r = t_str_lcase(name);
    *value_r = &args[1];
    return 1;
}