]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Merged latest v1.1 changes.
authorTimo Sirainen <tss@iki.fi>
Mon, 9 Jun 2008 02:11:18 +0000 (05:11 +0300)
committerTimo Sirainen <tss@iki.fi>
Mon, 9 Jun 2008 02:11:18 +0000 (05:11 +0300)
--HG--
branch : HEAD

44 files changed:
1  2 
configure.in
src/imap/client.c
src/imap/client.h
src/imap/cmd-append.c
src/imap/cmd-search.c
src/imap/cmd-store.c
src/imap/commands.h
src/imap/imap-search.c
src/imap/imap-sync.c
src/lib-index/mail-index-map.c
src/lib-index/mail-index-private.h
src/lib-index/mail-index-sync-ext.c
src/lib-index/mail-index-sync-update.c
src/lib-index/mail-index-transaction.c
src/lib-index/mail-index.c
src/lib-index/mail-index.h
src/lib-storage/index/Makefile.am
src/lib-storage/index/cydir/cydir-storage.c
src/lib-storage/index/dbox/dbox-mail.c
src/lib-storage/index/dbox/dbox-storage.c
src/lib-storage/index/index-mail.c
src/lib-storage/index/index-mail.h
src/lib-storage/index/index-search.c
src/lib-storage/index/index-storage.h
src/lib-storage/index/index-sync.c
src/lib-storage/index/maildir/maildir-mail.c
src/lib-storage/index/maildir/maildir-storage.c
src/lib-storage/index/mbox/mbox-mail.c
src/lib-storage/index/mbox/mbox-storage.c
src/lib-storage/index/raw/raw-mail.c
src/lib-storage/index/raw/raw-storage.c
src/lib-storage/mail-storage.c
src/lib-storage/mail-storage.h
src/plugins/convert/convert-storage.c
src/plugins/expire/expire-tool.c
src/plugins/fts-squat/fts-backend-squat.c
src/plugins/fts/fts-storage.c
src/plugins/lazy-expunge/lazy-expunge-plugin.c
src/plugins/mbox-snarf/mbox-snarf-plugin.c
src/plugins/quota/quota-count.c
src/plugins/quota/quota-storage.c
src/pop3/client.c
src/pop3/commands.c
src/util/idxview.c

diff --cc configure.in
Simple merge
index 8dafdbba4081edcc8c670ba66b4ebf63e7c1c80f,615268ec246ef90a310a634c6cfa7b4d728ecab7..d80b01b5d4a5b55870c13e9486bba4df541d919a
@@@ -127,16 -147,20 +147,22 @@@ void client_destroy(struct client *clie
  
        /* finish off all the queued commands. */
        if (client->output_lock != NULL)
-               client_command_cancel(client->output_lock);
+               client_command_cancel(&client->output_lock);
+       while (client->command_queue != NULL) {
+               cmd = client->command_queue;
+               client_command_cancel(&cmd);
+       }
+       /* handle the input_lock command last. it might have been waiting on
+          other queued commands (although we probably should just drop the
+          command at that point since it hasn't started running. but this may
+          change in future). */
        if (client->input_lock != NULL)
-               client_command_cancel(client->input_lock);
-       while (client->command_queue != NULL)
-               client_command_cancel(client->command_queue);
+               client_command_cancel(&client->input_lock);
  
 -      if (client->mailbox != NULL)
 +      if (client->mailbox != NULL) {
 +              client_search_updates_free(client);
                mailbox_close(&client->mailbox);
 +      }
        mail_namespaces_deinit(&client->namespaces);
  
        if (client->free_parser != NULL)
Simple merge
Simple merge
Simple merge
index 4ae413339c1dedb201e3a4a379d375a175c959f5,44f3c2cde996ac3873c3c8bec12ab8eb943dad3f..54f5f0695e82b294c130ecdd64a9490cf86f4b4a
@@@ -121,13 -49,8 +121,13 @@@ bool cmd_store(struct client_command_co
        struct mail_search_context *search_ctx;
          struct mailbox_transaction_context *t;
        struct mail *mail;
 -      const char *messageset, *item;
 -      bool silent, failed;
 +      struct imap_store_context ctx;
 +      ARRAY_TYPE(seq_range) modified_set = ARRAY_INIT;
 +      enum mailbox_transaction_flags flags = 0;
 +      enum imap_sync_flags imap_sync_flags = 0;
-       const char *tagged_reply;
++      const char *reply, *tagged_reply;
 +      string_t *str;
 +      int ret;
  
        if (!client_read_args(cmd, 0, 0, &args))
                return FALSE;
                client_send_command_error(cmd, "Invalid arguments.");
                return TRUE;
        }
 -
 -      if (!get_modify_type(cmd, item, &modify_type, &silent))
 -              return TRUE;
 -
 -      if (args[2].type == IMAP_ARG_LIST) {
 -              if (!client_parse_mail_flags(cmd,
 -                                           IMAP_ARG_LIST_ARGS(&args[2]),
 -                                           &flags, &keywords_list))
 -                      return TRUE;
 -      } else {
 -              if (!client_parse_mail_flags(cmd, args+2,
 -                                           &flags, &keywords_list))
 -                      return TRUE;
 -      }
 -
 -      box = client->mailbox;
 -      search_arg = imap_search_get_arg(cmd, messageset, cmd->uid);
 -      if (search_arg == NULL)
 +      ret = imap_search_get_seqset(cmd, IMAP_ARG_STR_NONULL(args),
 +                                   cmd->uid, &search_args);
 +      if (ret <= 0)
 +              return ret < 0;
 +
 +      memset(&ctx, 0, sizeof(ctx));
 +      ctx.cmd = cmd;
 +      if (!store_parse_args(&ctx, ++args))
                return TRUE;
  
 -      if (mailbox_is_readonly(box)) {
++      if (mailbox_is_readonly(client->mailbox)) {
++              if (ctx.max_modseq < (uint64_t)-1)
++                      reply = "NO CONDSTORE failed: Mailbox is read-only.";
++              else
++                      reply = "OK Store ignored with read-only mailbox.";
+               return cmd_sync(cmd, MAILBOX_SYNC_FLAG_FAST |
+                               (cmd->uid ? 0 : MAILBOX_SYNC_FLAG_NO_EXPUNGES),
 -                              0, "OK Store ignored with read-only mailbox.");
++                              0, reply);
+       }
 -      t = mailbox_transaction_begin(box, !silent ? 0 :
 -                                    MAILBOX_TRANSACTION_FLAG_HIDE);
 -      if (keywords_list == NULL && modify_type != MODIFY_REPLACE)
 -              keywords = NULL;
 -      else if (mailbox_keywords_create(box, keywords_list, &keywords) < 0) {
 -              /* invalid keywords */
 -              mailbox_transaction_rollback(&t);
 -              client_send_storage_error(cmd, mailbox_get_storage(box));
 -              return TRUE;
 -      }
 -      search_ctx = mailbox_search_init(t, NULL, search_arg, NULL);
 +      if (ctx.silent)
 +              flags |= MAILBOX_TRANSACTION_FLAG_HIDE;
 +      if (ctx.max_modseq < (uint64_t)-1)
 +              flags |= MAILBOX_TRANSACTION_FLAG_REFRESH;
++
 +      t = mailbox_transaction_begin(client->mailbox, flags);
 +      search_ctx = mailbox_search_init(t, search_args, NULL);
 +      mail_search_args_unref(&search_args);
  
 +      /* FIXME: UNCHANGEDSINCE should be atomic, but this requires support
 +         from mail-storage API. So for now we fake it. */
        mail = mail_alloc(t, MAIL_FETCH_FLAGS, NULL);
        while (mailbox_search_next(search_ctx, mail) > 0) {
 -              if (modify_type == MODIFY_REPLACE || flags != 0)
 -                      mail_update_flags(mail, modify_type, flags);
 -              if (modify_type == MODIFY_REPLACE || keywords != NULL)
 -                      mail_update_keywords(mail, modify_type, keywords);
 +              if (ctx.max_modseq < (uint64_t)-1) {
 +                      if (mail_get_modseq(mail) > ctx.max_modseq) {
 +                              seq_range_array_add(&modified_set, 64,
 +                                      cmd->uid ? mail->uid : mail->seq);
 +                              continue;
 +                      }
 +              }
 +              if (ctx.modify_type == MODIFY_REPLACE || ctx.flags != 0)
 +                      mail_update_flags(mail, ctx.modify_type, ctx.flags);
 +              if (ctx.modify_type == MODIFY_REPLACE || ctx.keywords != NULL) {
 +                      mail_update_keywords(mail, ctx.modify_type,
 +                                           ctx.keywords);
 +              }
        }
        mail_free(&mail);
  
Simple merge
index c567f35631be4ca0910e7a1b0abdae65a6e85089,d3b3636c6f9f342f85a1ea587733eadacfe9a355..0b93aff48500c05097d2bac0a5c0d5aaff25fd7d
@@@ -15,56 -16,546 +15,61 @@@ struct search_build_data 
        const char *error;
  };
  
 -static int
 -imap_uidset_parse(pool_t pool, struct mailbox *box, const char *uidset,
 -                struct mail_search_seqset **seqset_r, const char **error_r)
 +static bool search_args_have_searchres(struct mail_search_arg *sargs)
  {
 -      struct mail_search_seqset *seqset, **p;
 -      bool last;
 -
 -      *seqset_r = imap_messageset_parse(pool, uidset);
 -      if (*seqset_r == NULL) {
 -              *error_r = "Invalid UID messageset";
 -              return -1;
 -      }
 -
 -      p = seqset_r;
 -      for (seqset = *seqset_r; seqset != NULL; seqset = seqset->next) {
 -              if (seqset->seq1 == (uint32_t)-1) {
 -                      /* last message, stays same */
 -                      continue;
 +      for (; sargs != NULL; sargs = sargs->next) {
 +              switch (sargs->type) {
 +              case SEARCH_UIDSET:
 +                      if (strcmp(sargs->value.str, "$") == 0)
 +                              return TRUE;
 +                      break;
 +              case SEARCH_SUB:
 +              case SEARCH_OR:
 +                      if (search_args_have_searchres(sargs->value.subargs))
 +                              return TRUE;
 +                      break;
 +              default:
 +                      break;
                }
 -
 -              last = seqset->seq2 == (uint32_t)-1;
 -              mailbox_get_uids(box, seqset->seq1, seqset->seq2,
 -                               &seqset->seq1, &seqset->seq2);
 -              if (seqset->seq1 == 0 && last) {
 -                      /* we need special case for too_high_uid:* case */
 -                      seqset->seq1 = seqset->seq2 = (uint32_t)-1;
 -              }
 -
 -              if (seqset->seq1 != 0)
 -                      p = &seqset->next;
 -              else
 -                      *p = seqset->next;
        }
 -
 -      *error_r = NULL;
 -      return 0;
 +      return FALSE;
  }
  
 -static struct mail_search_arg *
 -search_arg_new(pool_t pool, enum mail_search_arg_type type)
 +int imap_search_args_build(struct client_command_context *cmd,
 +                         const struct imap_arg *args, const char *charset,
 +                         struct mail_search_args **search_args_r)
  {
 -      struct mail_search_arg *arg;
 -
 -      arg = p_new(pool, struct mail_search_arg, 1);
 -      arg->type = type;
 -
 -      return arg;
 -}
 +      struct mail_search_args *sargs;
 +      const char *error;
  
 -static bool
 -arg_get_next(struct search_build_data *data, const struct imap_arg **args,
 -           const char **value_r)
 -{
 -      if ((*args)->type == IMAP_ARG_EOL) {
 -              data->error = "Missing parameter for argument";
 -              return FALSE;
 -      }
 -      if ((*args)->type != IMAP_ARG_ATOM &&
 -          (*args)->type != IMAP_ARG_STRING) {
 -              data->error = "Invalid parameter for argument";
 -              return FALSE;
++      if (args->type == IMAP_ARG_EOL) {
++              client_send_command_error(cmd, "Missing search parameters");
++              return -1;
+       }
 -      *value_r = IMAP_ARG_STR(*args);
 -      *args += 1;
 -      return TRUE;
 -}
 -
 -#define ARG_NEW_SINGLE(type) \
 -      arg_new_single(data, next_sarg, type)
 -static bool
 -arg_new_single(struct search_build_data *data,
 -             struct mail_search_arg **next_sarg,
 -             enum mail_search_arg_type type)
 -{
 -      *next_sarg = search_arg_new(data->pool, type);
 -      return TRUE;
 -}
 -
 -#define ARG_NEW_STR(type) \
 -      arg_new_str(data, args, next_sarg, type)
 -static bool
 -arg_new_str(struct search_build_data *data,
 -          const struct imap_arg **args, struct mail_search_arg **next_sarg,
 -          enum mail_search_arg_type type)
 -{
 -      struct mail_search_arg *sarg;
 -      const char *value;
 -
 -      *next_sarg = sarg = search_arg_new(data->pool, type);
 -      if (!arg_get_next(data, args, &value))
 -              return FALSE;
 -      sarg->value.str = p_strdup(data->pool, value);
 -      return TRUE;
 -}
 -
 -#define ARG_NEW_FLAGS(flags) \
 -      arg_new_flags(data, next_sarg, flags)
 -static bool
 -arg_new_flags(struct search_build_data *data,
 -            struct mail_search_arg **next_sarg, enum mail_flags flags)
 -{
 -      struct mail_search_arg *sarg;
 -
 -      *next_sarg = sarg = search_arg_new(data->pool, SEARCH_FLAGS);
 -      sarg->value.flags = flags;
 -      return TRUE;
 -}
 -
 -static bool
 -arg_new_keyword(struct search_build_data *data,
 -              const struct imap_arg **args,
 -              struct mail_search_arg **next_sarg)
 -{
 -      struct mail_search_arg *sarg;
 -      const char *value, *keywords[2];
 -      struct mail_storage *storage;
 -      enum mail_error error;
 -
 -      *next_sarg = sarg = search_arg_new(data->pool, SEARCH_KEYWORDS);
 -      if (!arg_get_next(data, args, &value))
 -              return FALSE;
 -
 -      keywords[0] = value;
 -      keywords[1] = NULL;
 -
 -      if (mailbox_keywords_create(data->box, keywords,
 -                                  &sarg->value.keywords) < 0) {
 -              storage = mailbox_get_storage(data->box);
 -              data->error = mail_storage_get_last_error(storage, &error);
 -              return FALSE;
 +      if (mail_search_build_from_imap_args(args, charset,
 +                                           &sargs, &error) < 0) {
 +              client_send_command_error(cmd, error);
 +              return -1;
        }
 -      return TRUE;
 -}
 -
 -#define ARG_NEW_SIZE(type) \
 -      arg_new_size(data, args, next_sarg, type)
 -static bool
 -arg_new_size(struct search_build_data *data,
 -           const struct imap_arg **args, struct mail_search_arg **next_sarg,
 -           enum mail_search_arg_type type)
 -{
 -      struct mail_search_arg *sarg;
 -      const char *value;
 -      char *p;
 -
 -      *next_sarg = sarg = search_arg_new(data->pool, type);
 -      if (!arg_get_next(data, args, &value))
 -              return FALSE;
  
 -      sarg->value.size = strtoull(value, &p, 10);
 -      if (*p != '\0') {
 -              data->error = "Invalid search size parameter";
 -              return FALSE;
 +      if (search_args_have_searchres(sargs->args)) {
 +              if (client_handle_search_save_ambiguity(cmd))
 +                      return 0;
        }
 -      return TRUE;
 -}
 -
 -#define ARG_NEW_DATE(type) \
 -      arg_new_date(data, args, next_sarg, type)
 -static bool
 -arg_new_date(struct search_build_data *data,
 -           const struct imap_arg **args, struct mail_search_arg **next_sarg,
 -           enum mail_search_arg_type type)
 -{
 -      struct mail_search_arg *sarg;
 -      const char *value;
  
 -      *next_sarg = sarg = search_arg_new(data->pool, type);
 -      if (!arg_get_next(data, args, &value))
 -              return FALSE;
 -      if (!imap_parse_date(value, &sarg->value.time)) {
 -              data->error = "Invalid search date parameter";
 -              return FALSE;
 -      }
 -      return TRUE;
 +      mail_search_args_init(sargs, cmd->client->mailbox, TRUE,
 +                            &cmd->client->search_saved_uidset);
 +      *search_args_r = sargs;
 +      return 1;
  }
  
 -#define ARG_NEW_HEADER(type, hdr_name) \
 -      arg_new_header(data, args, next_sarg, type, hdr_name)
  static bool
 -arg_new_header(struct search_build_data *data,
 -             const struct imap_arg **args, struct mail_search_arg **next_sarg,
 -             enum mail_search_arg_type type, const char *hdr_name)
 +msgset_is_valid(ARRAY_TYPE(seq_range) *seqset, uint32_t messages_count)
  {
 -      struct mail_search_arg *sarg;
 -      const char *value;
 +      const struct seq_range *range;
 +      unsigned int count;
  
 -      *next_sarg = sarg = search_arg_new(data->pool, type);
 -      if (!arg_get_next(data, args, &value))
 -              return FALSE;
 -
 -      sarg->hdr_field_name = p_strdup(data->pool, hdr_name);
 -      sarg->value.str = p_strdup(data->pool, value);
 -      return TRUE;
 -}
 -
 -static bool search_arg_build(struct search_build_data *data,
 -                           const struct imap_arg **args,
 -                           struct mail_search_arg **next_sarg)
 -{
 -        struct mail_search_seqset *seqset;
 -      struct mail_search_arg **subargs;
 -      const struct imap_arg *arg;
 -      const char *str;
 -
 -      if ((*args)->type == IMAP_ARG_EOL) {
 -              data->error = "Missing argument";
 -              return FALSE;
 -      }
 -
 -      arg = *args;
 -
 -      if (arg->type == IMAP_ARG_NIL) {
 -              /* NIL not allowed */
 -              data->error = "NIL not allowed";
 -              return FALSE;
 -      }
 -
 -      if (arg->type == IMAP_ARG_LIST) {
 -              const struct imap_arg *listargs = IMAP_ARG_LIST_ARGS(arg);
 -
 -              if (listargs->type == IMAP_ARG_EOL) {
 -                      data->error = "Empty list not allowed";
 -                      return FALSE;
 -              }
 -
 -              *next_sarg = search_arg_new(data->pool, SEARCH_SUB);
 -              subargs = &(*next_sarg)->value.subargs;
 -              while (listargs->type != IMAP_ARG_EOL) {
 -                      if (!search_arg_build(data, &listargs, subargs))
 -                              return FALSE;
 -                      subargs = &(*subargs)->next;
 -              }
 -
 -              *args += 1;
 -              return TRUE;
 -      }
 -
 -      i_assert(arg->type == IMAP_ARG_ATOM ||
 -               arg->type == IMAP_ARG_STRING);
 -
 -      /* string argument - get the name and jump to next */
 -      str = IMAP_ARG_STR(arg);
 -      *args += 1;
 -      str = t_str_ucase(str);
 -
 -      switch (*str) {
 -      case 'A':
 -              if (strcmp(str, "ANSWERED") == 0)
 -                      return ARG_NEW_FLAGS(MAIL_ANSWERED);
 -              else if (strcmp(str, "ALL") == 0)
 -                      return ARG_NEW_SINGLE(SEARCH_ALL);
 -              break;
 -      case 'B':
 -              if (strcmp(str, "BODY") == 0) {
 -                      /* <string> */
 -                      if (IMAP_ARG_TYPE_IS_STRING((*args)->type) &&
 -                          *IMAP_ARG_STR(*args) == '\0') {
 -                              *args += 1;
 -                              return ARG_NEW_SINGLE(SEARCH_ALL);
 -                      }
 -                      return ARG_NEW_STR(SEARCH_BODY);
 -              } else if (strcmp(str, "BEFORE") == 0) {
 -                      /* <date> */
 -                      return ARG_NEW_DATE(SEARCH_BEFORE);
 -              } else if (strcmp(str, "BCC") == 0) {
 -                      /* <string> */
 -                      return ARG_NEW_HEADER(SEARCH_HEADER_ADDRESS, str);
 -              }
 -              break;
 -      case 'C':
 -              if (strcmp(str, "CC") == 0) {
 -                      /* <string> */
 -                      return ARG_NEW_HEADER(SEARCH_HEADER_ADDRESS, str);
 -              }
 -              break;
 -      case 'D':
 -              if (strcmp(str, "DELETED") == 0)
 -                      return ARG_NEW_FLAGS(MAIL_DELETED);
 -              else if (strcmp(str, "DRAFT") == 0)
 -                      return ARG_NEW_FLAGS(MAIL_DRAFT);
 -              break;
 -      case 'F':
 -              if (strcmp(str, "FLAGGED") == 0)
 -                      return ARG_NEW_FLAGS(MAIL_FLAGGED);
 -              else if (strcmp(str, "FROM") == 0) {
 -                      /* <string> */
 -                      return ARG_NEW_HEADER(SEARCH_HEADER_ADDRESS, str);
 -              }
 -              break;
 -      case 'H':
 -              if (strcmp(str, "HEADER") == 0) {
 -                      /* <field-name> <string> */
 -                      const char *key;
 -
 -                      if ((*args)->type == IMAP_ARG_EOL) {
 -                              data->error = "Missing parameter for HEADER";
 -                              return FALSE;
 -                      }
 -                      if ((*args)->type != IMAP_ARG_ATOM &&
 -                          (*args)->type != IMAP_ARG_STRING) {
 -                              data->error = "Invalid parameter for HEADER";
 -                              return FALSE;
 -                      }
 -
 -                      key = t_str_ucase(IMAP_ARG_STR(*args));
 -                      *args += 1;
 -                      return ARG_NEW_HEADER(SEARCH_HEADER, key);
 -              }
 -              break;
 -      case 'K':
 -              if (strcmp(str, "KEYWORD") == 0) {
 -                      /* <flag> */
 -                      return arg_new_keyword(data, args, next_sarg);
 -              }
 -              break;
 -      case 'L':
 -              if (strcmp(str, "LARGER") == 0) {
 -                      /* <n> */
 -                      return ARG_NEW_SIZE(SEARCH_LARGER);
 -              }
 -              break;
 -      case 'N':
 -              if (strcmp(str, "NOT") == 0) {
 -                      if (!search_arg_build(data, args, next_sarg))
 -                              return FALSE;
 -                      (*next_sarg)->not = !(*next_sarg)->not;
 -                      return TRUE;
 -              } else if (strcmp(str, "NEW") == 0) {
 -                      /* NEW == (RECENT UNSEEN) */
 -                      *next_sarg = search_arg_new(data->pool, SEARCH_SUB);
 -
 -                      subargs = &(*next_sarg)->value.subargs;
 -                      *subargs = search_arg_new(data->pool, SEARCH_FLAGS);
 -                      (*subargs)->value.flags = MAIL_RECENT;
 -                      (*subargs)->next = search_arg_new(data->pool,
 -                                                        SEARCH_FLAGS);
 -                      (*subargs)->next->value.flags = MAIL_SEEN;
 -                      (*subargs)->next->not = TRUE;
 -                      return TRUE;
 -              }
 -              break;
 -      case 'O':
 -              if (strcmp(str, "OR") == 0) {
 -                      /* <search-key1> <search-key2> */
 -                      *next_sarg = search_arg_new(data->pool, SEARCH_OR);
 -
 -                      subargs = &(*next_sarg)->value.subargs;
 -                      for (;;) {
 -                              if (!search_arg_build(data, args, subargs))
 -                                      return FALSE;
 -
 -                              subargs = &(*subargs)->next;
 -
 -                              /* <key> OR <key> OR ... <key> - put them all
 -                                 under one SEARCH_OR list. */
 -                              if ((*args)->type == IMAP_ARG_EOL)
 -                                      break;
 -
 -                              if ((*args)->type != IMAP_ARG_ATOM ||
 -                                  strcasecmp(IMAP_ARG_STR_NONULL(*args),
 -                                             "OR") != 0)
 -                                      break;
 -
 -                              *args += 1;
 -                      }
 -
 -                      if (!search_arg_build(data, args, subargs))
 -                              return FALSE;
 -                      return TRUE;
 -              } if (strcmp(str, "ON") == 0) {
 -                      /* <date> */
 -                      return ARG_NEW_DATE(SEARCH_ON);
 -              } if (strcmp(str, "OLD") == 0) {
 -                      /* OLD == NOT RECENT */
 -                      if (!ARG_NEW_FLAGS(MAIL_RECENT))
 -                              return FALSE;
 -
 -                      (*next_sarg)->not = TRUE;
 -                      return TRUE;
 -              }
 -              break;
 -      case 'R':
 -              if (strcmp(str, "RECENT") == 0)
 -                      return ARG_NEW_FLAGS(MAIL_RECENT);
 -              break;
 -      case 'S':
 -              if (strcmp(str, "SEEN") == 0)
 -                      return ARG_NEW_FLAGS(MAIL_SEEN);
 -              else if (strcmp(str, "SUBJECT") == 0) {
 -                      /* <string> */
 -                      return ARG_NEW_HEADER(SEARCH_HEADER_COMPRESS_LWSP, str);
 -              } else if (strcmp(str, "SENTBEFORE") == 0) {
 -                      /* <date> */
 -                      return ARG_NEW_DATE(SEARCH_SENTBEFORE);
 -              } else if (strcmp(str, "SENTON") == 0) {
 -                      /* <date> */
 -                      return ARG_NEW_DATE(SEARCH_SENTON);
 -              } else if (strcmp(str, "SENTSINCE") == 0) {
 -                      /* <date> */
 -                      return ARG_NEW_DATE(SEARCH_SENTSINCE);
 -              } else if (strcmp(str, "SINCE") == 0) {
 -                      /* <date> */
 -                      return ARG_NEW_DATE(SEARCH_SINCE);
 -              } else if (strcmp(str, "SMALLER") == 0) {
 -                      /* <n> */
 -                      return ARG_NEW_SIZE(SEARCH_SMALLER);
 -              }
 -              break;
 -      case 'T':
 -              if (strcmp(str, "TEXT") == 0) {
 -                      /* <string> */
 -                      if (IMAP_ARG_TYPE_IS_STRING((*args)->type) &&
 -                          *IMAP_ARG_STR(*args) == '\0') {
 -                              *args += 1;
 -                              return ARG_NEW_SINGLE(SEARCH_ALL);
 -                      }
 -                      return ARG_NEW_STR(SEARCH_TEXT);
 -              } else if (strcmp(str, "TO") == 0) {
 -                      /* <string> */
 -                      return ARG_NEW_HEADER(SEARCH_HEADER_ADDRESS, str);
 -              }
 -              break;
 -      case 'U':
 -              if (strcmp(str, "UID") == 0) {
 -                      /* <message set> */
 -                      if (!ARG_NEW_STR(SEARCH_SEQSET))
 -                              return FALSE;
 -
 -                      return imap_uidset_parse(data->pool, data->box,
 -                                               (*next_sarg)->value.str,
 -                                               &(*next_sarg)->value.seqset,
 -                                               &data->error) == 0;
 -              } else if (strcmp(str, "UNANSWERED") == 0) {
 -                      if (!ARG_NEW_FLAGS(MAIL_ANSWERED))
 -                              return FALSE;
 -                      (*next_sarg)->not = TRUE;
 -                      return TRUE;
 -              } else if (strcmp(str, "UNDELETED") == 0) {
 -                      if (!ARG_NEW_FLAGS(MAIL_DELETED))
 -                              return FALSE;
 -                      (*next_sarg)->not = TRUE;
 -                      return TRUE;
 -              } else if (strcmp(str, "UNDRAFT") == 0) {
 -                      if (!ARG_NEW_FLAGS(MAIL_DRAFT))
 -                              return FALSE;
 -                      (*next_sarg)->not = TRUE;
 -                      return TRUE;
 -              } else if (strcmp(str, "UNFLAGGED") == 0) {
 -                      if (!ARG_NEW_FLAGS(MAIL_FLAGGED))
 -                              return FALSE;
 -                      (*next_sarg)->not = TRUE;
 -                      return TRUE;
 -              } else if (strcmp(str, "UNKEYWORD") == 0) {
 -                      /* <flag> */
 -                      if (!arg_new_keyword(data, args, next_sarg))
 -                              return FALSE;
 -                      (*next_sarg)->not = TRUE;
 -                      return TRUE;
 -              } else if (strcmp(str, "UNSEEN") == 0) {
 -                      if (!ARG_NEW_FLAGS(MAIL_SEEN))
 -                              return FALSE;
 -                      (*next_sarg)->not = TRUE;
 -                      return TRUE;
 -              }
 -              break;
 -      case 'X':
 -              if (strcmp(str, "X-BODY-FAST") == 0) {
 -                      /* <string> */
 -                      if (IMAP_ARG_TYPE_IS_STRING((*args)->type) &&
 -                          *IMAP_ARG_STR(*args) == '\0') {
 -                              *args += 1;
 -                              return ARG_NEW_SINGLE(SEARCH_ALL);
 -                      }
 -                      return ARG_NEW_STR(SEARCH_BODY_FAST);
 -              } else if (strcmp(str, "X-TEXT-FAST") == 0) {
 -                      /* <string> */
 -                      if (IMAP_ARG_TYPE_IS_STRING((*args)->type) &&
 -                          *IMAP_ARG_STR(*args) == '\0') {
 -                              *args += 1;
 -                              return ARG_NEW_SINGLE(SEARCH_ALL);
 -                      }
 -                      return ARG_NEW_STR(SEARCH_TEXT_FAST);
 -              }
 -              break;
 -      default:
 -              if (*str == '*' || (*str >= '0' && *str <= '9')) {
 -                      /* <message-set> */
 -                      seqset = imap_messageset_parse(data->pool, str);
 -                      if (seqset == NULL) {
 -                              data->error = "Invalid messageset";
 -                              return FALSE;
 -                      }
 -
 -                      if (!ARG_NEW_SINGLE(SEARCH_SEQSET))
 -                              return FALSE;
 -
 -                      (*next_sarg)->value.seqset = seqset;
 -                      return TRUE;
 -              }
 -              break;
 -      }
 -
 -      data->error = t_strconcat("Unknown argument ", str, NULL);
 -      return FALSE;
 -}
 -
 -struct mail_search_arg *
 -imap_search_args_build(pool_t pool, struct mailbox *box,
 -                     const struct imap_arg *args, const char **error_r)
 -{
 -        struct search_build_data data;
 -      struct mail_search_arg *first_sarg, **sargs;
 -
 -      *error_r = NULL;
 -
 -      data.box = box;
 -      data.pool = pool;
 -      data.error = NULL;
 -
 -      /* get the first arg */
 -      first_sarg = NULL; sargs = &first_sarg;
 -      while (args->type != IMAP_ARG_EOL) {
 -              if (!search_arg_build(&data, &args, sargs)) {
 -                      imap_search_args_free(box, first_sarg);
 -                      *error_r = data.error;
 -                      return NULL;
 -              }
 -              sargs = &(*sargs)->next;
 -      }
 -
 -      if (first_sarg == NULL)
 -              *error_r = "Missing search parameters";
 -      return first_sarg;
 -}
 -
 -static bool
 -msgset_is_valid(const struct mail_search_seqset *set, uint32_t messages_count)
 -{
        /* when there are no messages, all messagesets are invalid.
           if there's at least one message:
            - * gives seq1 = seq2 = (uint32_t)-1
Simple merge
Simple merge
index b6c9db7879d271b6d72681ac7a107d705a988ec4,42b928a4556dae4b5301ed19f2cb5f0d4af87000..e5845df3363538eb2a7b989363efdcc3805036cd
@@@ -220,7 -218,7 +220,8 @@@ struct mail_index 
        unsigned int mapping:1;
        unsigned int syncing:1;
        unsigned int need_recreate:1;
 +      unsigned int modseqs_enabled:1;
+       unsigned int initial_create:1;
  };
  
  extern struct mail_index_module_register mail_index_module_register;
Simple merge
Simple merge
Simple merge
index b4217cfa8ec4c545ade9872582ce4d3ad7af400e,086d324031fe6f4a58ecbbfa5e35af7123f242a1..25a434f61765a00674c9201096aa6348030f552c
@@@ -29,10 -26,9 +30,11 @@@ libstorage_index_a_SOURCES = 
  headers = \
        index-mail.h \
        index-sort.h \
+       index-sort-private.h \
        index-storage.h \
 -      index-sync-changes.h
 +      index-sync-changes.h \
 +      index-sync-private.h \
 +      index-thread-private.h
  
  if INSTALL_HEADERS
    pkginc_libdir=$(pkgincludedir)/src/lib-storage/index
Simple merge
Simple merge
index ec1153c896bd59ef8ac6300e04958fe7ca60e1ba,feafec1c4f5ed9d4ada930ad0dda22623811e9ea..a26eef39a49c259f610567e530981fb8acdf0c03
@@@ -140,10 -144,10 +140,12 @@@ static int search_arg_match_index(struc
        int ret;
  
        switch (arg->type) {
 +      case SEARCH_UIDSET:
 +              return seq_range_exists(&arg->value.seqset, rec->uid);
        case SEARCH_FLAGS:
-               flags = rec->flags;
+               /* recent flag shouldn't be set, but indexes from v1.0.x
+                  may contain it. */
+               flags = rec->flags & ~MAIL_RECENT;
                if ((arg->value.flags & MAIL_RECENT) != 0 &&
                    index_mailbox_is_recent(ctx->ibox, rec->uid))
                        flags |= MAIL_RECENT;
Simple merge
index 7a4435a8be09b529af9d10224323c8d5998af337,1262dd23e15411c364d0bf63f9e7096b064d35b8..2a722c8962a836df539a88a33045b688e6fdf5da
@@@ -99,10 -122,8 +108,10 @@@ static void index_view_sync_recs_get(st
        uint32_t seq1, seq2;
  
        i_array_init(&ctx->flag_updates, 128);
-       while (mail_index_view_sync_next(ctx->sync_ctx, &sync)) {
-               switch (sync.type) {
 +      if ((ctx->ibox->box.enabled_features & MAILBOX_FEATURE_CONDSTORE) != 0)
 +              i_array_init(&ctx->modseq_updates, 32);
+       while (mail_index_view_sync_next(ctx->sync_ctx, &sync_rec)) {
+               switch (sync_rec.type) {
                case MAIL_INDEX_SYNC_TYPE_APPEND:
                        /* not interested */
                        break;
                case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
                case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
                case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
 -                      if (mail_index_lookup_seq_range(ctx->ibox->view,
 -                                                      sync_rec.uid1,
 -                                                      sync_rec.uid2,
 -                                                      &seq1, &seq2)) {
 +                      if (!mail_index_lookup_seq_range(ctx->ibox->view,
-                                                        sync.uid1, sync.uid2,
++                                                       sync_rec.uid1, sync_rec.uid2,
 +                                                       &seq1, &seq2))
 +                              break;
 +
-                       if (!sync.hidden) {
++                      if (!sync_rec.hidden) {
                                seq_range_array_add_range(&ctx->flag_updates,
                                                          seq1, seq2);
 +                      } else if (array_is_created(&ctx->modseq_updates)) {
 +                              seq_range_array_add_range(&ctx->modseq_updates,
 +                                                        seq1, seq2);
                        }
                        break;
                }
@@@ -225,24 -231,14 +234,24 @@@ bool index_mailbox_sync_next(struct mai
        if (ctx->failed)
                return FALSE;
  
 -      flag_updates = array_get(&ctx->flag_updates, &count);
 -      if (ctx->flag_update_pos < count) {
 +      range = array_get(&ctx->flag_updates, &count);
 +      if (ctx->flag_update_idx < count) {
                sync_rec_r->type = MAILBOX_SYNC_TYPE_FLAGS;
 -              sync_rec_r->seq1 = flag_updates[ctx->flag_update_pos].seq1;
 -              sync_rec_r->seq2 = flag_updates[ctx->flag_update_pos].seq2;
 -              ctx->flag_update_pos++;
 +              sync_rec_r->seq1 = range[ctx->flag_update_idx].seq1;
 +              sync_rec_r->seq2 = range[ctx->flag_update_idx].seq2;
 +              ctx->flag_update_idx++;
-               return 1;
+               return TRUE;
        }
-                       return 1;
 +      if (array_is_created(&ctx->modseq_updates)) {
 +              range = array_get(&ctx->modseq_updates, &count);
 +              if (ctx->modseq_update_idx < count) {
 +                      sync_rec_r->type = MAILBOX_SYNC_TYPE_MODSEQ;
 +                      sync_rec_r->seq1 = range[ctx->modseq_update_idx].seq1;
 +                      sync_rec_r->seq2 = range[ctx->modseq_update_idx].seq2;
 +                      ctx->modseq_update_idx++;
++                      return TRUE;
 +              }
 +      }
  
        return index_mailbox_sync_next_expunge(ctx, sync_rec_r);
  }
Simple merge
index addc92e09f9f9711ad6c18f9cc6436e2894f0a94,9dc401ca08b63e5bbb3b93f3a5a524dca94b5fc9..b48cf769c904e8d03a131dd1b37eb091fd1c7f0e
@@@ -542,17 -530,12 +542,14 @@@ int mailbox_sync(struct mailbox *box, e
                 struct mailbox_status *status_r)
  {
        struct mailbox_sync_context *ctx;
-         struct mailbox_sync_rec sync_rec;
  
 -      /* we don't care about mailbox's current state, so we might as well
 -         fix inconsistency state */
 -      flags |= MAILBOX_SYNC_FLAG_FIX_INCONSISTENT;
 +      if (array_count(&box->search_results) == 0) {
 +              /* we don't care about mailbox's current state, so we might
 +                 as well fix inconsistency state */
 +              flags |= MAILBOX_SYNC_FLAG_FIX_INCONSISTENT;
 +      }
  
        ctx = mailbox_sync_init(box, flags);
-       while (mailbox_sync_next(ctx, &sync_rec))
-               ;
        return mailbox_sync_deinit(&ctx, status_items, status_r);
  }
  
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 99470eff654dc001aa4a30c59fbb040fd7f9eed0,76fc7999aed7f928efb38b03699fde3bdf4aa6ef..a0528f4a2246ffd15f0261af41f3d591c5577458
@@@ -505,8 -503,52 +505,51 @@@ struct cmd_uidl_context 
        unsigned int message;
  
        struct mail_search_arg search_arg;
 -      struct mail_search_seqset seqset;
  };
  
+ static void pop3_get_uid(struct cmd_uidl_context *ctx,
+                        struct var_expand_table *tab, string_t *str)
+ {
+       char uid_str[MAX_INT_STRLEN];
+       const char *uidl;
+       if (mail_get_special(ctx->mail, MAIL_FETCH_UIDL_BACKEND, &uidl) == 0 &&
+           *uidl != '\0') {
+               str_append(str, uidl);
+               return;
+       }
+       if (reuse_xuidl &&
+           mail_get_first_header(ctx->mail, "X-UIDL", &uidl) > 0) {
+               str_append(str, uidl);
+               return;
+       }
+       if ((uidl_keymask & UIDL_UID) != 0) {
+               i_snprintf(uid_str, sizeof(uid_str), "%u",
+                          ctx->mail->uid);
+               tab[1].value = uid_str;
+       }
+       if ((uidl_keymask & UIDL_MD5) != 0) {
+               if (mail_get_special(ctx->mail, MAIL_FETCH_HEADER_MD5,
+                                    &tab[2].value) < 0 ||
+                   *tab[2].value == '\0') {
+                       /* broken */
+                       i_fatal("UIDL: Header MD5 not found");
+               }
+       }
+       if ((uidl_keymask & UIDL_FILE_NAME) != 0) {
+               if (mail_get_special(ctx->mail,
+                                    MAIL_FETCH_UIDL_FILE_NAME,
+                                    &tab[3].value) < 0 ||
+                   *tab[3].value == '\0') {
+                       /* broken */
+                       i_fatal("UIDL: File name not found");
+               }
+       }
+       var_expand(str, uidl_format, tab);
+ }
  static bool list_uids_iter(struct client *client, struct cmd_uidl_context *ctx)
  {
        static struct var_expand_table static_tab[] = {
Simple merge