summaryrefslogtreecommitdiffstats
path: root/src/lib-imap/imap-arg.c
blob: 0b947ce81421cd1a910bf656db6cf916d5558689 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/* Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file */

#include "lib.h"
#include "imap-arg.h"

bool imap_arg_get_atom(const struct imap_arg *arg, const char **str_r)
{
	if (arg->type != IMAP_ARG_ATOM && arg->type != IMAP_ARG_NIL)
		return FALSE;

	*str_r = arg->_data.str;
	return TRUE;
}

bool imap_arg_get_quoted(const struct imap_arg *arg, const char **str_r)
{
	if (arg->type != IMAP_ARG_STRING)
		return FALSE;

	*str_r = arg->_data.str;
	return TRUE;
}

bool imap_arg_get_string(const struct imap_arg *arg, const char **str_r)
{
	if (arg->type != IMAP_ARG_STRING && arg->type != IMAP_ARG_LITERAL)
		return FALSE;

	*str_r = arg->_data.str;
	return TRUE;
}

bool imap_arg_get_astring(const struct imap_arg *arg, const char **str_r)
{
	/* RFC 3501 4.5. specifies that NIL is the same as "NIL" when
	   reading astring. */
	if (!IMAP_ARG_IS_ASTRING(arg) && arg->type != IMAP_ARG_NIL)
		return FALSE;

	*str_r = arg->_data.str;
	return TRUE;
}

bool imap_arg_get_nstring(const struct imap_arg *arg, const char **str_r)
{
	if (arg->type == IMAP_ARG_NIL) {
		*str_r = NULL;
		return TRUE;
	}
	return imap_arg_get_string(arg, str_r);
}

bool imap_arg_get_literal_size(const struct imap_arg *arg, uoff_t *size_r)
{
	if (arg->type != IMAP_ARG_LITERAL_SIZE &&
	    arg->type != IMAP_ARG_LITERAL_SIZE_NONSYNC)
		return FALSE;

	*size_r = arg->_data.literal_size;
	return TRUE;
}

bool imap_arg_get_list(const struct imap_arg *arg,
		       const struct imap_arg **list_r)
{
	unsigned int count;

	return imap_arg_get_list_full(arg, list_r, &count);
}

bool imap_arg_get_list_full(const struct imap_arg *arg,
			    const struct imap_arg **list_r,
			    unsigned int *list_count_r)
{
	unsigned int count;

	if (arg->type != IMAP_ARG_LIST)
		return FALSE;

	*list_r = array_get(&arg->_data.list, &count);

	if (count > 0 && (*list_r)[count-1].type == IMAP_ARG_EOL)
		count--;
	else {
		/* imap-parser stopped early (e.g. due to reading literal size).
		   The IMAP_ARG_EOL was added to the list only temporarily. */
		i_assert((*list_r)[count].type == IMAP_ARG_EOL);
	}
	*list_count_r = count;
	return TRUE;
}

const char *imap_arg_as_astring(const struct imap_arg *arg)
{
	const char *str;

	if (!imap_arg_get_astring(arg, &str))
		i_unreached();
	return str;
}

const char *imap_arg_as_nstring(const struct imap_arg *arg)
{
	const char *str;

	if (!imap_arg_get_nstring(arg, &str))
		i_unreached();
	return str;
}

uoff_t imap_arg_as_literal_size(const struct imap_arg *arg)
{
	uoff_t size;

	if (!imap_arg_get_literal_size(arg, &size))
		i_unreached();
	return size;
}

const struct imap_arg *
imap_arg_as_list(const struct imap_arg *arg)
{
	const struct imap_arg *ret;

	if (!imap_arg_get_list(arg, &ret))
		i_unreached();
	return ret;
}

bool imap_arg_atom_equals(const struct imap_arg *arg, const char *str)
{
	const char *value;

	if (!imap_arg_get_atom(arg, &value))
		return FALSE;
	return strcasecmp(value, str) == 0;
}