bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen#include "lib.h"
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen#include "imap-seqset.h"
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainenstatic uint32_t get_next_number(const char **str)
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen{
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen uint32_t num;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen num = 0;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen while (**str != '\0') {
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen if (**str < '0' || **str > '9')
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen break;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen num = num*10 + (**str - '0');
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen (*str)++;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen }
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen if (num == (uint32_t)-1) {
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen /* FIXME: ugly hack, we're using this number to mean the
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen last existing message. In reality UIDs should never get
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen this high, so we can quite safely just drop this one down. */
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen num--;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen }
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen return num;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen}
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainenstatic int
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainenget_next_seq_range(const char **str, uint32_t *seq1_r, uint32_t *seq2_r)
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen{
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen uint32_t seq1, seq2;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen if (**str == '*') {
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen /* last message */
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen seq1 = (uint32_t)-1;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen *str += 1;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen } else {
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen seq1 = get_next_number(str);
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen if (seq1 == 0)
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen return -1;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen }
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen if (**str != ':')
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen seq2 = seq1;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen else {
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen /* first:last range */
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen *str += 1;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen if (**str == '*') {
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen seq2 = (uint32_t)-1;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen *str += 1;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen } else {
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen seq2 = get_next_number(str);
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen if (seq2 == 0)
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen return -1;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen }
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen }
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen if (seq1 > seq2) {
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen /* swap, as specified by RFC-3501 */
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen *seq1_r = seq2;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen *seq2_r = seq1;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen } else {
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen *seq1_r = seq1;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen *seq2_r = seq2;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen }
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen return 0;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen}
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainenint imap_seq_set_parse(const char *str, ARRAY_TYPE(seq_range) *dest)
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen{
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen uint32_t seq1, seq2;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen while (*str != '\0') {
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen if (get_next_seq_range(&str, &seq1, &seq2) < 0)
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen return -1;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen seq_range_array_add_range(dest, seq1, seq2);
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen if (*str == ',')
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen str++;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen else if (*str != '\0')
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen return -1;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen }
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen return 0;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen}
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen
e12ccf1e6b606d96bd55ff77db3aa873127d6c72Timo Sirainenint imap_seq_set_nostar_parse(const char *str, ARRAY_TYPE(seq_range) *dest)
e12ccf1e6b606d96bd55ff77db3aa873127d6c72Timo Sirainen{
e12ccf1e6b606d96bd55ff77db3aa873127d6c72Timo Sirainen if (imap_seq_set_parse(str, dest) < 0)
e12ccf1e6b606d96bd55ff77db3aa873127d6c72Timo Sirainen return -1;
e12ccf1e6b606d96bd55ff77db3aa873127d6c72Timo Sirainen
e12ccf1e6b606d96bd55ff77db3aa873127d6c72Timo Sirainen if (seq_range_exists(dest, (uint32_t)-1)) {
e12ccf1e6b606d96bd55ff77db3aa873127d6c72Timo Sirainen /* '*' used */
e12ccf1e6b606d96bd55ff77db3aa873127d6c72Timo Sirainen return -1;
e12ccf1e6b606d96bd55ff77db3aa873127d6c72Timo Sirainen }
e12ccf1e6b606d96bd55ff77db3aa873127d6c72Timo Sirainen return 0;
e12ccf1e6b606d96bd55ff77db3aa873127d6c72Timo Sirainen}
e12ccf1e6b606d96bd55ff77db3aa873127d6c72Timo Sirainen
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainenint imap_seq_range_parse(const char *str, uint32_t *seq1_r, uint32_t *seq2_r)
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen{
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen if (get_next_seq_range(&str, seq1_r, seq2_r) < 0)
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen return -1;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen return *str == '\0' ? 0 : -1;
c27245ef934dbf93c8469fd1ae0519e6971ae64fTimo Sirainen}