| 2183 | #include "rtpengine_bracket.h" |
| 2184 | |
| 2185 | static int parse_flags(struct ng_flags_parse *ng_flags, struct sip_msg *msg, |
| 2186 | enum rtpe_operation *op, const char *flags_str) |
| 2187 | { |
| 2188 | char *e; |
| 2189 | const char *err; |
| 2190 | str key, val; |
| 2191 | int delete_delay; |
| 2192 | bencode_item_t *bitem; |
| 2193 | str iniface, outiface; |
| 2194 | |
| 2195 | if (!flags_str) |
| 2196 | return 0; |
| 2197 | |
| 2198 | iniface.len = outiface.len = 0; |
| 2199 | iniface.s = outiface.s = NULL; |
| 2200 | |
| 2201 | while (1) { |
| 2202 | while (*flags_str == ' ') |
| 2203 | flags_str++; |
| 2204 | |
| 2205 | key.s = (void *) flags_str; |
| 2206 | val.len = key.len = -1; |
| 2207 | val.s = NULL; |
| 2208 | |
| 2209 | e = strpbrk(key.s, " ="); |
| 2210 | if (!e) |
| 2211 | e = key.s + strlen(key.s); |
| 2212 | else if (*e == '=') { |
| 2213 | key.len = e - key.s; |
| 2214 | val.s = e + 1; |
| 2215 | if (*val.s == '[') { |
| 2216 | /* bracket value: scan forward to the matching ']', |
| 2217 | * tracking nesting depth so inner brackets like |
| 2218 | * key=[a=[x y] b=[z]] are consumed as a single value */ |
| 2219 | int depth = 0; |
| 2220 | for (e = val.s; *e; e++) { |
| 2221 | if (*e == '[') depth++; |
| 2222 | else if (*e == ']' && --depth == 0) { e++; break; } |
| 2223 | } |
| 2224 | if (depth != 0) { |
| 2225 | /* set val.len before error so the error handler |
| 2226 | * can safely log the partial value with %.*s */ |
| 2227 | val.len = e - val.s; |
| 2228 | err = "unmatched bracket in flag value"; |
| 2229 | goto error; |
| 2230 | } |
| 2231 | } else { |
| 2232 | /* non-bracket value: terminate at next space */ |
| 2233 | e = strchr(val.s, ' '); |
| 2234 | if (!e) |
| 2235 | e = val.s + strlen(val.s); |
| 2236 | } |
| 2237 | /* e now points past the value; compute length */ |
| 2238 | val.len = e - val.s; |
| 2239 | } |
| 2240 | |
| 2241 | if (key.len == -1) |
| 2242 | key.len = e - key.s; |
no test coverage detected