1 /**
2 * @file
3 * Store attributes associated with a MIME part
4 *
5 * @authors
6 * Copyright (C) 2017 Richard Russon <rich@flatcap.org>
7 *
8 * @copyright
9 * This program is free software: you can redistribute it and/or modify it under
10 * the terms of the GNU General Public License as published by the Free Software
11 * Foundation, either version 2 of the License, or (at your option) any later
12 * version.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 /**
24 * @page email_parameter Attributes for a MIME part
25 *
26 * Store attributes associated with a MIME part
27 */
28
29 #include "config.h"
30 #include <stddef.h>
31 #include <stdbool.h>
32 #include "mutt/lib.h"
33 #include "parameter.h"
34
35 /**
36 * mutt_param_new - Create a new Parameter
37 * @retval ptr Newly allocated Parameter
38 */
mutt_param_new(void)39 struct Parameter *mutt_param_new(void)
40 {
41 return mutt_mem_calloc(1, sizeof(struct Parameter));
42 }
43
44 /**
45 * mutt_param_free_one - Free a Parameter
46 * @param[out] p Parameter to free
47 */
mutt_param_free_one(struct Parameter ** p)48 void mutt_param_free_one(struct Parameter **p)
49 {
50 if (!p || !*p)
51 return;
52 FREE(&(*p)->attribute);
53 FREE(&(*p)->value);
54 FREE(p);
55 }
56
57 /**
58 * mutt_param_free - Free a ParameterList
59 * @param pl ParameterList to free
60 */
mutt_param_free(struct ParameterList * pl)61 void mutt_param_free(struct ParameterList *pl)
62 {
63 if (!pl)
64 return;
65
66 struct Parameter *np = TAILQ_FIRST(pl);
67 struct Parameter *next = NULL;
68 while (np)
69 {
70 next = TAILQ_NEXT(np, entries);
71 mutt_param_free_one(&np);
72 np = next;
73 }
74 TAILQ_INIT(pl);
75 }
76
77 /**
78 * mutt_param_get - Find a matching Parameter
79 * @param pl ParameterList
80 * @param s String to match
81 * @retval ptr Matching Parameter
82 * @retval NULL No match
83 */
mutt_param_get(const struct ParameterList * pl,const char * s)84 char *mutt_param_get(const struct ParameterList *pl, const char *s)
85 {
86 if (!pl)
87 return NULL;
88
89 struct Parameter *np = NULL;
90 TAILQ_FOREACH(np, pl, entries)
91 {
92 if (mutt_istr_equal(s, np->attribute))
93 return np->value;
94 }
95
96 return NULL;
97 }
98
99 /**
100 * mutt_param_set - Set a Parameter
101 * @param[in] pl ParameterList
102 * @param[in] attribute Attribute to match
103 * @param[in] value Value to set
104 *
105 * @note If value is NULL, the Parameter will be deleted
106 *
107 * @note If a matching Parameter isn't found a new one will be allocated.
108 * The new Parameter will be inserted at the front of the list.
109 */
mutt_param_set(struct ParameterList * pl,const char * attribute,const char * value)110 void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
111 {
112 if (!pl)
113 return;
114
115 if (!value)
116 {
117 mutt_param_delete(pl, attribute);
118 return;
119 }
120
121 struct Parameter *np = NULL;
122 TAILQ_FOREACH(np, pl, entries)
123 {
124 if (mutt_istr_equal(attribute, np->attribute))
125 {
126 mutt_str_replace(&np->value, value);
127 return;
128 }
129 }
130
131 np = mutt_param_new();
132 np->attribute = mutt_str_dup(attribute);
133 np->value = mutt_str_dup(value);
134 TAILQ_INSERT_HEAD(pl, np, entries);
135 }
136
137 /**
138 * mutt_param_delete - Delete a matching Parameter
139 * @param[in] pl ParameterList
140 * @param[in] attribute Attribute to match
141 */
mutt_param_delete(struct ParameterList * pl,const char * attribute)142 void mutt_param_delete(struct ParameterList *pl, const char *attribute)
143 {
144 if (!pl)
145 return;
146
147 struct Parameter *np = NULL;
148 TAILQ_FOREACH(np, pl, entries)
149 {
150 if (mutt_istr_equal(attribute, np->attribute))
151 {
152 TAILQ_REMOVE(pl, np, entries);
153 mutt_param_free_one(&np);
154 return;
155 }
156 }
157 }
158
159 /**
160 * mutt_param_cmp_strict - Strictly compare two ParameterLists
161 * @param pl1 First parameter
162 * @param pl2 Second parameter
163 * @retval true Parameters are strictly identical
164 */
mutt_param_cmp_strict(const struct ParameterList * pl1,const struct ParameterList * pl2)165 bool mutt_param_cmp_strict(const struct ParameterList *pl1, const struct ParameterList *pl2)
166 {
167 if (!pl1 && !pl2)
168 return false;
169
170 if ((pl1 == NULL) ^ (pl2 == NULL))
171 return true;
172
173 struct Parameter *np1 = TAILQ_FIRST(pl1);
174 struct Parameter *np2 = TAILQ_FIRST(pl2);
175
176 while (np1 && np2)
177 {
178 if (!mutt_str_equal(np1->attribute, np2->attribute) ||
179 !mutt_str_equal(np1->value, np2->value))
180 {
181 return false;
182 }
183
184 np1 = TAILQ_NEXT(np1, entries);
185 np2 = TAILQ_NEXT(np2, entries);
186 }
187
188 if (np1 || np2)
189 return false;
190
191 return true;
192 }
193