/src/dovecot/src/lib-imap/imap-seqset.c
Line | Count | Source |
1 | | /* Copyright (c) Dovecot authors, see top-level COPYING file */ |
2 | | |
3 | | #include "lib.h" |
4 | | #include "array.h" |
5 | | #include "imap-seqset.h" |
6 | | |
7 | | static uint32_t get_next_number(const char **str) |
8 | 0 | { |
9 | 0 | uint32_t num; |
10 | |
|
11 | 0 | if (str_parse_uint32(*str, &num, str) < 0) |
12 | 0 | return 0; |
13 | | |
14 | 0 | if (num == (uint32_t)-1) { |
15 | | /* FIXME: ugly hack, we're using this number to mean the |
16 | | last existing message. In reality UIDs should never get |
17 | | this high, so we can quite safely just drop this one down. */ |
18 | 0 | num--; |
19 | 0 | } |
20 | |
|
21 | 0 | return num; |
22 | 0 | } |
23 | | |
24 | | static int |
25 | | get_next_seq_range(const char **str, uint32_t *seq1_r, uint32_t *seq2_r) |
26 | 0 | { |
27 | 0 | uint32_t seq1, seq2; |
28 | |
|
29 | 0 | if (**str == '*') { |
30 | | /* last message */ |
31 | 0 | seq1 = (uint32_t)-1; |
32 | 0 | *str += 1; |
33 | 0 | } else { |
34 | 0 | seq1 = get_next_number(str); |
35 | 0 | if (seq1 == 0) |
36 | 0 | return -1; |
37 | 0 | } |
38 | | |
39 | 0 | if (**str != ':') |
40 | 0 | seq2 = seq1; |
41 | 0 | else { |
42 | | /* first:last range */ |
43 | 0 | *str += 1; |
44 | |
|
45 | 0 | if (**str == '*') { |
46 | 0 | seq2 = (uint32_t)-1; |
47 | 0 | *str += 1; |
48 | 0 | } else { |
49 | 0 | seq2 = get_next_number(str); |
50 | 0 | if (seq2 == 0) |
51 | 0 | return -1; |
52 | 0 | } |
53 | 0 | } |
54 | | |
55 | 0 | if (seq1 > seq2) { |
56 | | /* swap, as specified by RFC-3501 */ |
57 | 0 | *seq1_r = seq2; |
58 | 0 | *seq2_r = seq1; |
59 | 0 | } else { |
60 | 0 | *seq1_r = seq1; |
61 | 0 | *seq2_r = seq2; |
62 | 0 | } |
63 | 0 | return 0; |
64 | 0 | } |
65 | | |
66 | | int imap_seq_set_parse(const char *str, ARRAY_TYPE(seq_range) *dest) |
67 | 0 | { |
68 | 0 | uint32_t seq1, seq2; |
69 | |
|
70 | 0 | do { |
71 | 0 | if (get_next_seq_range(&str, &seq1, &seq2) < 0) |
72 | 0 | return -1; |
73 | 0 | seq_range_array_add_range(dest, seq1, seq2); |
74 | |
|
75 | 0 | if (*str == ',') |
76 | 0 | str++; |
77 | 0 | } while (*str != '\0'); |
78 | 0 | return 0; |
79 | 0 | } |
80 | | |
81 | | int imap_seq_set_nostar_parse(const char *str, ARRAY_TYPE(seq_range) *dest) |
82 | 0 | { |
83 | 0 | if (imap_seq_set_parse(str, dest) < 0) |
84 | 0 | return -1; |
85 | | |
86 | 0 | if (seq_range_exists(dest, (uint32_t)-1)) { |
87 | | /* '*' used */ |
88 | 0 | return -1; |
89 | 0 | } |
90 | 0 | return 0; |
91 | 0 | } |
92 | | |
93 | | int imap_seq_set_ordered_parse(const char *str, ARRAY_TYPE(uint32_t) *dest) |
94 | 0 | { |
95 | 0 | uint32_t seq1, seq2; |
96 | |
|
97 | 0 | for (;;) { |
98 | 0 | seq1 = get_next_number(&str); |
99 | 0 | if (seq1 == 0) |
100 | 0 | return -1; |
101 | 0 | if (*str != ':') |
102 | 0 | seq2 = seq1; |
103 | 0 | else { |
104 | 0 | str++; |
105 | 0 | seq2 = get_next_number(&str); |
106 | 0 | if (seq2 == 0) |
107 | 0 | return -1; |
108 | 0 | } |
109 | 0 | if (seq1 > seq2) |
110 | 0 | return -1; |
111 | | |
112 | 0 | for (uint32_t seq = seq1; seq <= seq2; seq++) |
113 | 0 | array_push_back(dest, &seq); |
114 | |
|
115 | 0 | if (*str == '\0') |
116 | 0 | break; |
117 | 0 | if (*str != ',') |
118 | 0 | return -1; |
119 | 0 | str++; |
120 | 0 | } |
121 | 0 | return 0; |
122 | 0 | } |
123 | | |
124 | | int imap_seq_range_parse(const char *str, uint32_t *seq1_r, uint32_t *seq2_r) |
125 | 0 | { |
126 | 0 | if (get_next_seq_range(&str, seq1_r, seq2_r) < 0) |
127 | 0 | return -1; |
128 | 0 | return *str == '\0' ? 0 : -1; |
129 | 0 | } |