2
0

msg_parser_util.c 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003
  1. /*
  2. * This file is part of the Sofia-SIP package
  3. *
  4. * Copyright (C) 2005 Nokia Corporation.
  5. *
  6. * Contact: Pekka Pessi <pekka.pessi@nokia.com>
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public License
  10. * as published by the Free Software Foundation; either version 2.1 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  21. * 02110-1301 USA
  22. *
  23. */
  24. /**@ingroup msg_parser
  25. * @CFILE msg_parser_util.c
  26. *
  27. * Text-message parser helper functions.
  28. *
  29. * @author Pekka Pessi <Pekka.Pessi@nokia.com>
  30. *
  31. * @date Created: Tue Aug 28 16:26:34 2001 ppessi
  32. *
  33. */
  34. #include "config.h"
  35. #include <stddef.h>
  36. #include <stdlib.h>
  37. #include <string.h>
  38. #include <stdio.h>
  39. #include <assert.h>
  40. #include <limits.h>
  41. #include <stdarg.h>
  42. #include <sofia-sip/su_tagarg.h>
  43. #include <sofia-sip/su.h>
  44. #include <sofia-sip/su_alloc.h>
  45. #include <sofia-sip/su_string.h>
  46. #include "msg_internal.h"
  47. #include "sofia-sip/msg_parser.h"
  48. #include "sofia-sip/bnf.h"
  49. #include "sofia-sip/url.h"
  50. static issize_t msg_comma_scanner(char *start);
  51. /**
  52. * Parse first line.
  53. *
  54. * Splits the first line from a message into three whitespace-separated
  55. * parts.
  56. */
  57. int msg_firstline_d(char *s, char **return_part2, char **return_part3)
  58. {
  59. char *s1 = s, *s2, *s3;
  60. size_t n;
  61. /* Split line into three segments separated by whitespace */
  62. if (s1[n = span_non_ws(s1)]) {
  63. s1[n] = '\0';
  64. s2 = s1 + n + 1;
  65. while (IS_WS(*s2))
  66. s2++;
  67. }
  68. else {
  69. /* Hopeless - no WS in first line */
  70. return -1;
  71. }
  72. n = span_non_ws(s2);
  73. if (s2[n]) {
  74. s2[n++] = '\0';
  75. while (IS_WS(s2[n]))
  76. n++;
  77. }
  78. s3 = s2 + n;
  79. *return_part2 = s2;
  80. *return_part3 = s3;
  81. return 0;
  82. }
  83. /**Parse a token.
  84. *
  85. * Parses a token from string pointed by @a *ss. It stores the token value
  86. * in @a return_token, and updates the @a ss to the end of token and
  87. * possible whitespace.
  88. */
  89. issize_t msg_token_d(char **ss, char const **return_token)
  90. {
  91. char *s = *ss;
  92. size_t n = span_token(s);
  93. if (n) {
  94. for (; IS_LWS(s[n]); n++)
  95. s[n] = '\0';
  96. *return_token = s;
  97. *ss = s + n;
  98. return n;
  99. }
  100. else
  101. return -1;
  102. }
  103. /** Parse a 32-bit unsigned int.
  104. *
  105. * The function msg_uint32_d() parses a 32-bit unsigned integer in string
  106. * pointed by @a *ss. It stores the value in @a return_token and updates the
  107. * @a ss to the end of integer and possible whitespace.
  108. *
  109. * @retval length of parsed integer, or -1 upon an error.
  110. */
  111. issize_t msg_uint32_d(char **ss, uint32_t *return_value)
  112. {
  113. char const *s = *ss, *s0 = s;
  114. uint32_t value;
  115. unsigned digit;
  116. if (!IS_DIGIT(*s))
  117. return -1;
  118. for (value = 0; IS_DIGIT(*s); s++) {
  119. digit = *s - '0';
  120. if (value > 429496729U)
  121. return -1;
  122. else if (value == 429496729U && digit > 5)
  123. return -1;
  124. value = 10 * value + digit;
  125. }
  126. if (*s) {
  127. if (!IS_LWS(*s))
  128. return (issize_t)-1;
  129. skip_lws(&s);
  130. }
  131. *ss = (char *)s;
  132. *return_value = value;
  133. return s - s0;
  134. }
  135. /** Parse any list.
  136. *
  137. * Parses a list of items, separated by @a sep. The parsed string is passed
  138. * in @a *ss, which is updated to point to the first non-linear-whitespace
  139. * character after the list. The function modifies the string as it parses
  140. * it.
  141. *
  142. * The parsed items are appended to the list @a *append_list. If there the
  143. * list in @a *append_list is NULL, allocate a new list and return it in @a
  144. * *append_list. Empty list items are ignored, and are not appended to the
  145. * list.
  146. *
  147. * The function @b must be passed a scanning function @a scanner. The
  148. * scanning function scans for a legitimate list item, for example, a token.
  149. * It should also compact the list item, for instance, if the item consists
  150. * of @c name=value parameter definitions it should remove whitespace around
  151. * "=" sign. The scanning function returns the length of the scanned item,
  152. * including any linear whitespace after it.
  153. *
  154. * @param[in] home memory home for allocating list pointers
  155. * @param[in,out] ss pointer to pointer to string to be parsed
  156. * @param[in,out] append_list pointer to list
  157. * where parsed list items are appended
  158. * @param[in] sep separator character
  159. * @param[in] scanner pointer to function for scanning a single item
  160. *
  161. * @retval 0 if successful.
  162. * @retval -1 upon an error.
  163. */
  164. issize_t msg_any_list_d(su_home_t *home,
  165. char **ss,
  166. msg_param_t **append_list,
  167. issize_t (*scanner)(char *s),
  168. int sep)
  169. {
  170. char const *stack[MSG_N_PARAMS];
  171. char const **list = stack, **re_list;
  172. size_t N = MSG_N_PARAMS, n = 0;
  173. issize_t tlen;
  174. char *s = *ss;
  175. char const **start;
  176. if (!scanner)
  177. return -1;
  178. if (*append_list) {
  179. list = *append_list;
  180. while (list[n])
  181. n++;
  182. N = MSG_PARAMS_NUM(n + 1);
  183. }
  184. start = &list[n];
  185. skip_lws(&s);
  186. while (*s) {
  187. tlen = scanner(s);
  188. if (tlen < 0 || (s[tlen] && s[tlen] != sep && s[tlen] != ','))
  189. goto error;
  190. if (tlen > 0) {
  191. if (n + 1 == N) { /* Reallocate list? */
  192. N = MSG_PARAMS_NUM(N + 1);
  193. if (list == stack || list == *append_list) {
  194. re_list = su_alloc(home, N * sizeof(*list));
  195. if (re_list)
  196. memcpy(re_list, list, n * sizeof(*list));
  197. }
  198. else
  199. re_list = su_realloc(home, list, N * sizeof(*list));
  200. if (!re_list)
  201. goto error;
  202. list = re_list;
  203. }
  204. list[n++] = s;
  205. s += tlen;
  206. }
  207. if (*s == sep) {
  208. *s++ = '\0';
  209. skip_lws(&s);
  210. }
  211. else if (*s)
  212. break;
  213. }
  214. *ss = s;
  215. if (n == 0) {
  216. *append_list = NULL;
  217. return 0;
  218. }
  219. if (list == stack) {
  220. size_t size = sizeof(*list) * MSG_PARAMS_NUM(n + 1);
  221. list = su_alloc(home, size);
  222. if (!list) return -1;
  223. memcpy((void *)list, stack, n * sizeof(*list));
  224. }
  225. list[n] = NULL;
  226. *append_list = list;
  227. return 0;
  228. error:
  229. *start = NULL;
  230. if (list != stack && list != *append_list)
  231. su_free(home, list);
  232. return -1;
  233. }
  234. /** Scan an attribute (name [= value]) pair.
  235. *
  236. * The attribute consists of name (a token) and optional value, separated by
  237. * equal sign. The value can be a token or quoted string.
  238. *
  239. * This function compacts the scanned value. It removes the
  240. * whitespace around equal sign "=" by moving the equal sign character and
  241. * value towards name.
  242. *
  243. * If there is whitespace within the scanned value or after it,
  244. * NUL-terminates the scanned attribute.
  245. *
  246. * @retval > 0 number of characters scanned,
  247. * including the whitespace within the value
  248. * @retval -1 upon an error
  249. */
  250. issize_t msg_attribute_value_scanner(char *s)
  251. {
  252. char *p = s;
  253. size_t tlen;
  254. skip_token(&s);
  255. if (s == p) /* invalid parameter name */
  256. return -1;
  257. tlen = s - p;
  258. if (IS_LWS(*s)) { *s++ = '\0'; skip_lws(&s); }
  259. if (*s == '=') {
  260. char *v;
  261. s++;
  262. skip_lws(&s);
  263. /* get value */
  264. if (*s == '"') {
  265. size_t qlen = span_quoted(s);
  266. if (!qlen)
  267. return -1;
  268. v = s; s += qlen;
  269. }
  270. else {
  271. v = s;
  272. skip_param(&s);
  273. if (s == v)
  274. return -1;
  275. }
  276. if (p + tlen + 1 != v) {
  277. memmove(p + tlen + 1, v, s - v);
  278. p[tlen] = '=';
  279. p[tlen + 1 + (s - v)] = '\0';
  280. }
  281. }
  282. if (IS_LWS(*s)) { *s++ = '\0'; skip_lws(&s); }
  283. return s - p;
  284. }
  285. /**Parse an attribute-value list.
  286. *
  287. * Parses an attribute-value list, which has syntax as follows:
  288. * @code
  289. * av-list = (av-pair *(";" av-pair)
  290. * av-pair = token ["=" ( value / quoted-string) ] ; optional value
  291. * @endcode
  292. *
  293. * @param[in] home pointer to a memory home
  294. * @param[in,out] ss pointer to string at the start of parameter list
  295. * @param[in,out] append_list pointer to list
  296. * where parsed list items are appended
  297. *
  298. * @retval >= 0 if successful
  299. * @retval -1 upon an error
  300. */
  301. issize_t msg_avlist_d(su_home_t *home,
  302. char **ss,
  303. msg_param_t const **append_list)
  304. {
  305. char const *stack[MSG_N_PARAMS];
  306. char const **params;
  307. size_t n = 0, N;
  308. char *s = *ss;
  309. if (!*s)
  310. return -1;
  311. if (*append_list) {
  312. params = (char const **)*append_list;
  313. for (n = 0; params[n]; n++)
  314. ;
  315. N = MSG_PARAMS_NUM(n + 1);
  316. }
  317. else {
  318. params = stack;
  319. N = MSG_PARAMS_NUM(1);
  320. }
  321. for (;;) {
  322. char *p;
  323. size_t tlen;
  324. /* XXX - we should handle also quoted parameters */
  325. skip_lws(&s);
  326. p = s;
  327. skip_token(&s);
  328. tlen = s - p;
  329. if (!tlen) /* invalid parameter name */
  330. goto error;
  331. if (IS_LWS(*s)) { *s++ = '\0'; skip_lws(&s); }
  332. if (*s == '=') {
  333. char *v;
  334. s++;
  335. skip_lws(&s);
  336. /* get value */
  337. if (*s == '"') {
  338. size_t qlen = span_quoted(s);
  339. if (!qlen)
  340. goto error;
  341. v = s; s += qlen;
  342. }
  343. else {
  344. v = s;
  345. skip_param(&s);
  346. if (s == v)
  347. goto error;
  348. }
  349. if (p + tlen + 1 != v) {
  350. p = memmove(v - tlen - 1, p, tlen);
  351. p[tlen] = '=';
  352. }
  353. }
  354. if (IS_LWS(*s)) { *s++ = '\0'; skip_lws(&s); }
  355. if (n == N) {
  356. /* Reallocate params */
  357. char const **nparams = su_realloc(home, (void*)(params != stack ? params : NULL),
  358. (N = MSG_PARAMS_NUM(N + 1)) * sizeof(*params));
  359. if (!nparams) {
  360. goto error;
  361. }
  362. if (params == stack)
  363. memcpy(nparams, stack, n * sizeof(*params));
  364. params = nparams;
  365. }
  366. params[n++] = p;
  367. if (*s != ';')
  368. break;
  369. *s++ = '\0';
  370. }
  371. *ss = s;
  372. if (params == stack) {
  373. size_t size = sizeof(*params) * MSG_PARAMS_NUM(n + 1);
  374. params = su_alloc(home, size);
  375. if (!params) return -1;
  376. memcpy((void *)params, stack, n * sizeof(*params));
  377. }
  378. else if (n == N) {
  379. /* Reallocate params */
  380. char const **nparams = su_realloc(home, (void*)(params != stack ? params : NULL),
  381. MSG_PARAMS_NUM(N + 1) * sizeof(*params));
  382. if (!nparams) {
  383. goto error;
  384. }
  385. if (params == stack)
  386. memcpy(nparams, stack, n * sizeof(*params));
  387. params = nparams;
  388. }
  389. params[n] = NULL;
  390. *append_list = params;
  391. return 0;
  392. error:
  393. if (params != stack)
  394. su_free(home, params);
  395. return -1;
  396. }
  397. /**Parse a semicolon-separated parameter list starting with semicolon.
  398. *
  399. * Parse a parameter list, which has syntax as follows:
  400. * @code
  401. * *(";" token [ "=" (token | quoted-string)]).
  402. * @endcode
  403. *
  404. * @param[in] home pointer to a memory home
  405. * @param[in,out] ss pointer to string at the start of parameter list
  406. * @param[in,out] append_list pointer to list
  407. * where parsed list items are appended
  408. *
  409. * @retval >= 0 if successful
  410. * @retval -1 upon an error
  411. *
  412. * @sa msg_avlist_d()
  413. */
  414. issize_t msg_params_d(su_home_t *home,
  415. char **ss,
  416. msg_param_t const **append_list)
  417. {
  418. if (**ss == ';') {
  419. *(*ss)++ = '\0';
  420. *append_list = NULL;
  421. return msg_avlist_d(home, ss, append_list);
  422. }
  423. if (IS_LWS(**ss)) {
  424. *(*ss)++ = '\0'; skip_lws(ss);
  425. }
  426. return 0;
  427. }
  428. /** Encode a list of parameters */
  429. isize_t msg_params_e(char b[], isize_t bsiz, msg_param_t const pparams[])
  430. {
  431. int i;
  432. char *end = b + bsiz, *b0 = b;
  433. msg_param_t p;
  434. if (pparams)
  435. for (i = 0; (p = pparams[i]); i++) {
  436. if (p[0]) {
  437. MSG_CHAR_E(b, end, ';');
  438. MSG_STRING_E(b, end, p);
  439. }
  440. }
  441. return b - b0;
  442. }
  443. /** Duplicate a parameter list */
  444. char *msg_params_dup(msg_param_t const **d, msg_param_t const s[],
  445. char *b, isize_t xtra)
  446. {
  447. char *end = b + xtra;
  448. char **pp;
  449. int i;
  450. isize_t n;
  451. n = msg_params_count(s);
  452. if (n == 0) {
  453. *d = NULL;
  454. return b;
  455. }
  456. MSG_STRUCT_ALIGN(b);
  457. pp = (char **)b;
  458. b += sizeof(*pp) * MSG_PARAMS_NUM(n + 1);
  459. for (i = 0; s[i]; i++) {
  460. MSG_STRING_DUP(b, pp[i], s[i]);
  461. }
  462. pp[i] = NULL;
  463. assert(b <= end); (void)end;
  464. *d = (msg_param_t const *)pp;
  465. return b;
  466. }
  467. /** Parse a comma-separated list.
  468. *
  469. * Parses a comma-separated list. The parsed string is passed in @a *ss,
  470. * which is updated to point to the first non-linear-whitespace character
  471. * after the list. The function modifies the string as it parses it.
  472. *
  473. * A pointer to the resulting list is returned in @a *retval. If there
  474. * already is a list in @a *retval, new items are appended. Empty list items
  475. * are ignored, and are not included in the list.
  476. *
  477. * The function can be passed an optional scanning function. The scanning
  478. * function scans for a legitimate list item, for example, a token. It also
  479. * compacts the list item, for instance, if the item consists of @c
  480. * name=value parameter definitions. The scanning function returns the
  481. * length of the scanned item, including any linear whitespace after it.
  482. *
  483. * By default, the scanning function accepts tokens, quoted strings or
  484. * separators (except comma, of course).
  485. *
  486. * @param[in] home memory home for allocating list pointers
  487. * @param[in,out] ss pointer to pointer to string to be parsed
  488. * @param[in,out] append_list pointer to list
  489. * where parsed list items are appended
  490. * @param[in] scanner pointer to function scanning a single item
  491. * (optional)
  492. *
  493. * @retval 0 if successful.
  494. * @retval -1 upon an error.
  495. */
  496. issize_t msg_commalist_d(su_home_t *home,
  497. char **ss,
  498. msg_param_t **append_list,
  499. issize_t (*scanner)(char *s))
  500. {
  501. scanner = scanner ? scanner : msg_comma_scanner;
  502. return msg_any_list_d(home, ss, append_list, scanner, ',');
  503. }
  504. /** Token scanner for msg_commalist_d() accepting also empty entries. */
  505. issize_t msg_token_scan(char *start)
  506. {
  507. char *s = start;
  508. skip_token(&s);
  509. if (IS_LWS(*s))
  510. *s++ = '\0';
  511. skip_lws(&s);
  512. return s - start;
  513. }
  514. /** Scan and compact a comma-separated item */
  515. static
  516. issize_t msg_comma_scanner(char *start)
  517. {
  518. size_t tlen;
  519. char *s, *p;
  520. s = p = start;
  521. if (s[0] == ',')
  522. return 0;
  523. for (;;) {
  524. /* Grab next section - token, quoted string, or separator character */
  525. char c = *s;
  526. if (IS_TOKEN(c))
  527. tlen = span_token(s);
  528. else if (c == '"')
  529. tlen = span_quoted(s);
  530. else /* if (IS_SEPARATOR(c)) */
  531. tlen = 1;
  532. if (tlen == 0)
  533. return -1;
  534. if (p != s)
  535. memmove(p, s, tlen); /* Move section to end of paramexter */
  536. p += tlen; s += tlen;
  537. skip_lws(&s); /* Skip possible LWS */
  538. if (*s == '\0' || *s == ',') { /* Test for possible end */
  539. if (p != s) *p = '\0';
  540. return s - start;
  541. }
  542. if (IS_TOKEN(c) && IS_TOKEN(*s))
  543. *p++ = ' '; /* Two tokens must be separated by LWS */
  544. }
  545. }
  546. /** Parse a comment.
  547. *
  548. * Parses a multilevel comment. The comment assigned to return-value
  549. * parameter @a return_comment is NUL-terminated. The string at return-value
  550. * parameter @a ss is updated to point to first non-linear-whitespace
  551. * character after the comment.
  552. */
  553. issize_t msg_comment_d(char **ss, char const **return_comment)
  554. {
  555. /* skip comment */
  556. int level = 1;
  557. char *s = *ss;
  558. assert(s[0] == '(');
  559. if (*s != '(')
  560. return -1;
  561. *s++ = '\0';
  562. if (return_comment)
  563. *return_comment = s;
  564. while (level) switch (*s++) {
  565. case '(': level++; break;
  566. case ')': level--; break;
  567. case '\0': /* ERROR */ return -1;
  568. }
  569. assert(s[-1] == ')');
  570. s[-1] = '\0';
  571. skip_lws(&s);
  572. *ss = s;
  573. return 0;
  574. }
  575. /** Parse a quoted string */
  576. issize_t msg_quoted_d(char **ss, char **return_quoted)
  577. {
  578. char *s= *ss, *s0 = s;
  579. ssize_t n = span_quoted(s);
  580. if (n <= 0)
  581. return -1;
  582. *return_quoted = s;
  583. s += n;
  584. if (IS_LWS(*s)) {
  585. *s++ = '\0';
  586. skip_lws(&s); /* skip linear whitespace */
  587. }
  588. *ss = s;
  589. return s - s0;
  590. }
  591. #if 0
  592. /** Calculate length of string when quoted. */
  593. int msg_quoted_len(char const *u)
  594. {
  595. int rv;
  596. if (!u)
  597. return 0;
  598. rv = span_token_lws(u);
  599. if (u[rv]) {
  600. /* We need to quote string */
  601. int n;
  602. int extra = 2; /* quote chars */
  603. /* Find all characters to quote */
  604. for (n = strcspn(u + rv, "\\\""); u[rv + n]; rv += n)
  605. extra++;
  606. rv += extra;
  607. }
  608. return rv;
  609. }
  610. #endif
  611. /**Parse @e host[":"port] pair.
  612. *
  613. * Parses a @e host[":"port] pair. The caller passes function a pointer to a
  614. * string via @a ss, and pointers to which parsed host and port are assigned
  615. * via @a hhost and @a pport, respectively. The value-result parameter @a
  616. * *pport must be initialized to default value (e.g., NULL).
  617. *
  618. * @param ss pointer to pointer to string to be parsed
  619. * @param return_host value-result parameter for @e host
  620. * @param return_port value-result parameter for @e port
  621. * @return
  622. * Returns zero when successful, and a negative value upon an error. The
  623. * parsed values for host and port are assigned via @a return_host and @a
  624. * return_port, respectively. The function also updates the pointer @a *ss,
  625. * so if call is successful, the @a *ss points to first
  626. * non-linear-whitespace character after @e host[":"port] pair.
  627. *
  628. * @note
  629. * If there is no whitespace after @e port, the value in @a *pport may not be
  630. * NUL-terminated. The calling function @b must NUL terminate the value by
  631. * setting the @a **ss to NUL after first examining its value.
  632. */
  633. int msg_hostport_d(char **ss,
  634. char const **return_host,
  635. char const **return_port)
  636. {
  637. char *host, *s = *ss;
  638. char *port = NULL;
  639. /* Host name */
  640. host = s;
  641. if (s[0] != '[') {
  642. skip_token(&s); if (host == s) return -1;
  643. }
  644. else {
  645. /* IPv6 */
  646. size_t n = strspn(++s, HEX ":.");
  647. if (s[n] != ']') return -1;
  648. s += n + 1;
  649. }
  650. if (IS_LWS(*s)) { *s++ = '\0'; skip_lws(&s); }
  651. if (s[0] == ':') {
  652. unsigned long nport;
  653. *s++ = '\0'; skip_lws(&s);
  654. if (!IS_DIGIT(*s))
  655. return -1;
  656. port = s;
  657. nport = strtoul(s, &s, 10);
  658. if (nport > 65535)
  659. return -1;
  660. if (IS_LWS(*s)) {
  661. *s++ = '\0';
  662. skip_lws(&s);
  663. }
  664. }
  665. *return_host = host;
  666. *return_port = port;
  667. *ss = s;
  668. return 0;
  669. }
  670. /** Find a header parameter.
  671. *
  672. * Searches for given parameter @a name from the header. If parameter is
  673. * found, it returns a non-NULL pointer to the parameter value. If there is
  674. * no value for the name (in form "name" or "name=value"), the returned pointer
  675. * points to a NUL character.
  676. *
  677. * @param h pointer to header structure
  678. * @param name parameter name (with or without "=" sign)
  679. *
  680. * @return
  681. * A pointer to parameter value, or NULL if parameter was not found.
  682. */
  683. char const *msg_header_find_param(msg_common_t const *h, char const *name)
  684. {
  685. if (h && h->h_class->hc_params) {
  686. msg_param_t const **params = (msg_param_t const **)
  687. ((char *)h + h->h_class->hc_params);
  688. return msg_params_find(*params, name);
  689. }
  690. return NULL;
  691. }
  692. /**Modify a parameter value or list item in a header.
  693. *
  694. * A header parameter @a param can be just a C-string (@a is_item > 0), or
  695. * it can have internal format <i>name [ "=" value]</i>. In the latter case,
  696. * the value part following = is ignored when replacing or removing the
  697. * parameter.
  698. *
  699. * @param home memory home used to re-allocate parameter list in header
  700. * @param h pointer to a header
  701. * @param param parameter to be replaced or added
  702. * @param is_item how to interpret @a param:
  703. * - 1 case-sensitive, no structure
  704. * - 0 case-insensitive, <i>name [ "=" value ]</i>
  705. * @param remove_replace_add what operation to do:
  706. * - -1 remove
  707. * - 0 replace
  708. * - 1 add
  709. *
  710. * @retval 1 if parameter was replaced or removed successfully
  711. * @retval 0 if parameter was added successfully,
  712. * or there was nothing to remove
  713. * @retval -1 upon an error
  714. */
  715. static
  716. int msg_header_param_modify(su_home_t *home, msg_common_t *h,
  717. char const *param,
  718. int is_item,
  719. int remove_replace_add)
  720. {
  721. msg_param_t *params, **pointer_to_params;
  722. size_t plen, n;
  723. if (!h || !h->h_class->hc_params || !param)
  724. return -1;
  725. pointer_to_params = (msg_param_t **)((char *)h + h->h_class->hc_params);
  726. params = *pointer_to_params;
  727. plen = is_item > 0 ? strlen(param) : strcspn(param, "=");
  728. n = 0;
  729. if (params) {
  730. /* Existing list, try to replace or remove */
  731. for (; params[n]; n++) {
  732. char const *maybe = params[n];
  733. if (remove_replace_add > 0)
  734. continue;
  735. if (is_item > 0) {
  736. if (strcmp(maybe, param) == 0) {
  737. if (remove_replace_add == 0)
  738. return 1;
  739. }
  740. }
  741. else {
  742. if (su_casenmatch(maybe, param, plen) &&
  743. (maybe[plen] == '=' || maybe[plen] == 0))
  744. break;
  745. }
  746. }
  747. }
  748. /* Not found? */
  749. if (!params || !params[n]) {
  750. if (remove_replace_add < 0)
  751. return 0; /* Nothing to remove */
  752. else
  753. remove_replace_add = 1; /* Add instead of replace */
  754. }
  755. if (remove_replace_add < 0) { /* Remove */
  756. for (; params[n]; n++)
  757. params[n] = params[n + 1];
  758. }
  759. else {
  760. if (remove_replace_add > 0) { /* Add */
  761. size_t m_before = MSG_PARAMS_NUM(n + 1);
  762. size_t m_after = MSG_PARAMS_NUM(n + 2);
  763. assert(!params || !params[n]);
  764. if (m_before != m_after || !params) {
  765. msg_param_t *p;
  766. /* XXX - we should know when to do realloc */
  767. p = su_alloc(home, m_after * sizeof(*p));
  768. if (!p) return -1;
  769. if (n > 0)
  770. memcpy(p, params, n * sizeof(p[0]));
  771. *pointer_to_params = params = p;
  772. }
  773. params[n + 1] = NULL;
  774. }
  775. params[n] = param; /* Add .. or replace */
  776. }
  777. msg_fragment_clear(h);
  778. if (h->h_class->hc_update) {
  779. /* Update shortcuts */
  780. size_t namelen;
  781. char const *name, *value;
  782. name = param;
  783. namelen = strcspn(name, "=");
  784. if (remove_replace_add < 0)
  785. value = NULL;
  786. else
  787. value = param + namelen + (name[namelen] == '=');
  788. h->h_class->hc_update(h, name, namelen, value);
  789. }
  790. return remove_replace_add <= 0; /* 0 when added, 1 otherwise */
  791. }
  792. /** Add a parameter to a header.
  793. *
  794. * You should use this function only when the header accepts multiple
  795. * parameters (or list items) with the same name. If that is not the case,
  796. * you should use msg_header_replace_param().
  797. *
  798. * @note This function @b does @b not duplicate @p param. The caller should
  799. * have allocated the @a param from the memory home associated with header
  800. * @a h.
  801. *
  802. * The possible shortcuts to parameter values are updated. For example, the
  803. * "received" parameter in @Via header has shortcut in structure #sip_via_t,
  804. * the @ref sip_via_s::v_received "v_received" field. The shortcut is usully
  805. * a pointer to the parameter value. If the parameter was
  806. * "received=127.0.0.1" the @ref sip_via_s::v_received "v_received" field
  807. * would be a pointer to "127.0.0.1". If the parameter was "received=" or
  808. * "received", the shortcut would be a pointer to an empty string, "".
  809. *
  810. * @param home memory home used to re-allocate parameter list in header
  811. * @param h pointer to a header
  812. * @param param parameter to be replaced or added
  813. *
  814. * @retval 0 if parameter was added
  815. * @retval -1 upon an error
  816. *
  817. * @sa msg_header_replace_param(), msg_header_remove_param(),
  818. * msg_header_update_params(),
  819. * #msg_common_t, #msg_header_t,
  820. * #msg_hclass_t, msg_hclass_t::hc_params, msg_hclass_t::hc_update
  821. */
  822. int msg_header_add_param(su_home_t *home, msg_common_t *h, char const *param)
  823. {
  824. return msg_header_param_modify(home, h, param,
  825. 0 /* case-insensitive name=value */,
  826. 1 /* add */);
  827. }
  828. /** Replace or add a parameter to a header.
  829. *
  830. * A header parameter @a param is a string of format <i>name "=" value</i>
  831. * or just name. The value part following "=" is ignored when selecting a
  832. * parameter to replace.
  833. *
  834. * @note This function @b does @b not duplicate @p param. The caller should
  835. * have allocated the @a param from the memory home associated with header
  836. * @a h.
  837. *
  838. * The possible shortcuts to parameter values are updated. For example, the
  839. * "received" parameter in @Via header has shortcut in structure #sip_via_t,
  840. * the @ref sip_via_s::v_received "v_received" field.
  841. *
  842. * @param home memory home used to re-allocate parameter list in header
  843. * @param h pointer to a header
  844. * @param param parameter to be replaced or added
  845. *
  846. * @retval 0 if parameter was added
  847. * @retval 1 if parameter was replaced
  848. * @retval -1 upon an error
  849. *
  850. * @sa msg_header_add_param(), msg_header_remove_param(),
  851. * msg_header_update_params(),
  852. * #msg_common_t, #msg_header_t,
  853. * #msg_hclass_t, msg_hclass_t::hc_params, msg_hclass_t::hc_update
  854. */
  855. int msg_header_replace_param(su_home_t *home,
  856. msg_common_t *h,
  857. char const *param)
  858. {
  859. return msg_header_param_modify(home, h, param,
  860. 0 /* case-insensitive name=value */,
  861. 0 /* replace */);
  862. }
  863. /** Remove a parameter from header.
  864. *
  865. * The parameter name is given as token optionally followed by "=" sign and
  866. * value. The "=" and value after it are ignored when selecting a parameter
  867. * to remove.
  868. *
  869. * The possible shortcuts to parameter values are updated. For example, the
  870. * "received" parameter in @Via header has shortcut in structure #sip_via_t,
  871. * the @ref sip_via_s::v_received "v_received" field. The shortcut to
  872. * removed parameter would be set to NULL.
  873. *
  874. * @param h pointer to a header
  875. * @param name name of parameter to be removed
  876. *
  877. * @retval 1 if a parameter was removed
  878. * @retval 0 if no parameter was not removed
  879. * @retval -1 upon an error
  880. *
  881. * @sa msg_header_add_param(), msg_header_replace_param(),
  882. * msg_header_update_params(),
  883. * #msg_common_t, #msg_header_t,
  884. * #msg_hclass_t, msg_hclass_t::hc_params, msg_hclass_t::hc_update
  885. */
  886. int msg_header_remove_param(msg_common_t *h, char const *name)
  887. {
  888. return msg_header_param_modify(NULL, h, name,
  889. 0 /* case-insensitive name=value */,
  890. -1 /* remove */);
  891. }
  892. /** Update shortcuts to parameter values.
  893. *
  894. * Update the shortcuts to parameter values in parameter list. For example,
  895. * the "received" parameter in @Via header has shortcut in structure
  896. * #sip_via_t, the @ref sip_via_s::v_received "v_received" field. The
  897. * shortcut is usully a pointer to the parameter value. If the parameter was
  898. * "received=127.0.0.1" the @ref sip_via_s::v_received "v_received" field
  899. * would be a pointer to "127.0.0.1". If the parameter was "received=" or
  900. * "received", the shortcut would be a pointer to an empty string, "".
  901. *
  902. * @retval 0 when successful
  903. * @retval -1 upon an error
  904. *
  905. * @sa msg_header_add_param(), msg_header_replace_param(),
  906. * msg_header_update_params(),
  907. * #msg_common_t, #msg_header_t,
  908. * #msg_hclass_t, msg_hclass_t::hc_params, msg_hclass_t::hc_update
  909. */
  910. int msg_header_update_params(msg_common_t *h, int clear)
  911. {
  912. msg_hclass_t *hc;
  913. unsigned char offset;
  914. msg_update_f *update;
  915. int retval;
  916. msg_param_t const *params;
  917. size_t n;
  918. char const *p, *v;
  919. if (h == NULL)
  920. return errno = EFAULT, -1;
  921. hc = h->h_class; offset = hc->hc_params; update = hc->hc_update;
  922. if (offset == 0 || update == NULL)
  923. return 0;
  924. if (clear)
  925. update(h, NULL, 0, NULL);
  926. params = *(msg_param_t **)((char *)h + offset);
  927. if (params == NULL)
  928. return 0;
  929. retval = 0;
  930. for (p = *params; p; p = *++params) {
  931. n = strcspn(p, "=");
  932. v = p + n + (p[n] == '=');
  933. if (update(h, p, n, v) < 0)
  934. retval = -1;
  935. }
  936. return retval;
  937. }
  938. /** Find a header item.
  939. *
  940. * Searches for given item @a name from the header. If item is found, the
  941. * function returns a non-NULL pointer to the item.
  942. *
  943. * @param h pointer to header structure
  944. * @param item item
  945. *
  946. * @return
  947. * A pointer to item, or NULL if it was not found.
  948. *
  949. * @since New in @VERSION_1_12_4
  950. *
  951. * @sa msg_header_replace_item(), msg_header_remove_item(),
  952. * @Allow, @AllowEvents
  953. */
  954. char const *msg_header_find_item(msg_common_t const *h, char const *item)
  955. {
  956. if (h && h->h_class->hc_params) {
  957. char const * const * items =
  958. *(char const * const * const *)
  959. ((char *)h + h->h_class->hc_params);
  960. if (items)
  961. for (; *items; items++) {
  962. if (strcmp(item, *items) == 0) {
  963. return *items;
  964. }
  965. }
  966. }
  967. return NULL;
  968. }
  969. /**Add an item to a header.
  970. *
  971. * This function treats a #msg_header_t as set of C strings. The @a item is
  972. * a C string. If no identical string is found from the list, it is added to
  973. * the list.
  974. *
  975. * The shortcuts, if any, to item values are updated accordingly.
  976. *
  977. * @param home memory home used to re-allocate list in header
  978. * @param h pointer to a header
  979. * @param item item to be removed
  980. *
  981. * @retval 0 if item was added
  982. * @retval 1 if item was replaced
  983. * @retval -1 upon an error
  984. *
  985. * @since New in @VERSION_1_12_4.
  986. *
  987. * @sa msg_header_remove_item(), @Allow, @AllowEvents,
  988. * msg_header_replace_param(), msg_header_remove_param(),
  989. * #msg_common_t, #msg_header_t, #msg_list_t
  990. * #msg_hclass_t, msg_hclass_t::hc_params
  991. */
  992. int msg_header_replace_item(su_home_t *home,
  993. msg_common_t *h,
  994. char const *item)
  995. {
  996. return msg_header_param_modify(home, h, item,
  997. 1 /* string item */,
  998. 0 /* replace */);
  999. }
  1000. /**Remove an item from a header.
  1001. *
  1002. * This function treats a #msg_header_t as set of C strings. The @a item is a
  1003. * C string. If identical string is found from the list, it is removed.
  1004. *
  1005. * The shortcuts, if any, to item values are updated accordingly.
  1006. *
  1007. * @param h pointer to a header
  1008. * @param name item to be removed
  1009. *
  1010. * @retval 0 if item was added
  1011. * @retval 1 if item was replaced
  1012. * @retval -1 upon an error
  1013. *
  1014. * @since New in @VERSION_1_12_4.
  1015. *
  1016. * @sa msg_header_replace_item(), @Allow, @AllowEvents,
  1017. * msg_header_replace_param(), msg_header_remove_param(),
  1018. * #msg_common_t, #msg_header_t, #msg_list_t
  1019. * #msg_hclass_t, msg_hclass_t::hc_params
  1020. */
  1021. int msg_header_remove_item(msg_common_t *h, char const *name)
  1022. {
  1023. return msg_header_param_modify(NULL, h, name,
  1024. 1 /* item */,
  1025. -1 /* remove */);
  1026. }
  1027. /** Find a parameter from a parameter list.
  1028. *
  1029. * Searches for given parameter @a token from the parameter list. If
  1030. * parameter is found, it returns a non-NULL pointer to the parameter value.
  1031. * If there is no value for the parameter (the parameter is of form "name"
  1032. * or "name="), the returned pointer points to a NUL character.
  1033. *
  1034. * @param params list (or vector) of parameters
  1035. * @param token parameter name (with or without "=" sign)
  1036. *
  1037. * @return
  1038. * A pointer to parameter value, or NULL if parameter was not found.
  1039. */
  1040. msg_param_t msg_params_find(msg_param_t const params[], msg_param_t token)
  1041. {
  1042. if (params && token) {
  1043. size_t i, n = strcspn(token, "=");
  1044. assert(n > 0);
  1045. for (i = 0; params[i]; i++) {
  1046. msg_param_t param = params[i];
  1047. if (su_casenmatch(param, token, n)) {
  1048. if (param[n] == '=')
  1049. return param + n + 1;
  1050. else if (param[n] == 0)
  1051. return param + n;
  1052. }
  1053. }
  1054. }
  1055. return NULL;
  1056. }
  1057. /** Find a slot for parameter from a parameter list.
  1058. *
  1059. * Searches for given parameter @a token from the parameter list. If
  1060. * parameter is found, it returns a non-NULL pointer to the item containing
  1061. * the parameter.
  1062. *
  1063. * @param params list (or vector) of parameters
  1064. * @param token parameter name (with or without "=" sign)
  1065. *
  1066. * @return
  1067. * A pointer to parameter slot, or NULL if parameter was not found.
  1068. */
  1069. msg_param_t *msg_params_find_slot(msg_param_t params[], msg_param_t token)
  1070. {
  1071. if (params && token) {
  1072. int i;
  1073. size_t n = strlen(token);
  1074. assert(n > 0);
  1075. for (i = 0; params[i]; i++) {
  1076. msg_param_t param = params[i];
  1077. if (su_casenmatch(param, token, n)) {
  1078. if (param[n] == '=')
  1079. return params + i;
  1080. else if (param[n] == 0 || token[n - 1] == '=')
  1081. return params + i;
  1082. }
  1083. }
  1084. }
  1085. return NULL;
  1086. }
  1087. /** Replace or add a parameter from a list.
  1088. *
  1089. * A non-NULL parameter list must have been created by msg_params_d()
  1090. * or by msg_params_dup().
  1091. *
  1092. * @note This function does not duplicate @p param.
  1093. *
  1094. * @param home memory home
  1095. * @param inout_params pointer to pointer to parameter list
  1096. * @param param parameter to be replaced or added
  1097. *
  1098. * @retval 0 if parameter was added
  1099. * @retval 1 if parameter was replaced
  1100. * @retval -1 upon an error
  1101. */
  1102. int msg_params_replace(su_home_t *home,
  1103. msg_param_t **inout_params,
  1104. msg_param_t param)
  1105. {
  1106. msg_param_t *params;
  1107. size_t i, n;
  1108. assert(inout_params);
  1109. if (param == NULL || param[0] == '=' || param[0] == '\0')
  1110. return -1;
  1111. params = *inout_params;
  1112. n = strcspn(param, "=");
  1113. if (params) {
  1114. /* Existing list, try to replace or remove */
  1115. for (i = 0; params[i]; i++) {
  1116. msg_param_t maybe = params[i];
  1117. if (su_casenmatch(maybe, param, n)) {
  1118. if (maybe[n] == '=' || maybe[n] == 0) {
  1119. params[i] = param;
  1120. return 1;
  1121. }
  1122. }
  1123. }
  1124. }
  1125. /* Not found on list */
  1126. return msg_params_add(home, inout_params, param);
  1127. }
  1128. /** Remove a parameter from a list.
  1129. *
  1130. * @retval 1 if parameter was removed
  1131. * @retval 0 if parameter was not found
  1132. * @retval -1 upon an error
  1133. */
  1134. int msg_params_remove(msg_param_t *params, msg_param_t param)
  1135. {
  1136. size_t i, n;
  1137. if (!params || !param || !param[0])
  1138. return -1;
  1139. n = strcspn(param, "=");
  1140. assert(n > 0);
  1141. for (i = 0; params[i]; i++) {
  1142. msg_param_t maybe = params[i];
  1143. if (su_casenmatch(maybe, param, n)) {
  1144. if (maybe[n] == '=' || maybe[n] == 0) {
  1145. /* Remove */
  1146. do {
  1147. params[i] = params[i + 1];
  1148. } while (params[i++]);
  1149. return 1;
  1150. }
  1151. }
  1152. }
  1153. return 0;
  1154. }
  1155. /** Calculate number of parameters in a parameter list */
  1156. size_t msg_params_length(char const * const * params)
  1157. {
  1158. size_t len;
  1159. if (!params)
  1160. return 0;
  1161. for (len = 0; params[len]; len++)
  1162. ;
  1163. return len;
  1164. }
  1165. /**
  1166. * Add a parameter to a list.
  1167. *
  1168. * Add a parameter to the list; the list must have been created by @c
  1169. * msg_params_d() or by @c msg_params_dup() (or it may contain only @c
  1170. * NULL).
  1171. *
  1172. * @note This function does not duplicate @p param.
  1173. *
  1174. * @param home memory home
  1175. * @param inout_params pointer to pointer to parameter list
  1176. * @param param parameter to be added
  1177. *
  1178. * @retval 0 if parameter was added
  1179. * @retval -1 upon an error
  1180. */
  1181. int msg_params_add(su_home_t *home,
  1182. msg_param_t **inout_params,
  1183. msg_param_t param)
  1184. {
  1185. size_t n, m_before, m_after;
  1186. msg_param_t *p = *inout_params;
  1187. if (param == NULL)
  1188. return -1;
  1189. /* Count number of parameters */
  1190. for (n = 0; p && p[n]; n++)
  1191. ;
  1192. m_before = MSG_PARAMS_NUM(n + 1);
  1193. m_after = MSG_PARAMS_NUM(n + 2);
  1194. if (m_before != m_after || !p) {
  1195. p = su_alloc(home, m_after * sizeof(*p));
  1196. assert(p); if (!p) return -1;
  1197. if (n)
  1198. memcpy(p, *inout_params, n * sizeof(*p));
  1199. *inout_params = p;
  1200. }
  1201. p[n] = param;
  1202. p[n + 1] = NULL;
  1203. return 0;
  1204. }
  1205. static
  1206. int msg_param_prune(msg_param_t const d[], msg_param_t p, unsigned prune)
  1207. {
  1208. size_t i, nlen;
  1209. if (prune == 1)
  1210. nlen = strcspn(p, "=");
  1211. else
  1212. nlen = 0;
  1213. for (i = 0; d[i]; i++) {
  1214. if ((prune == 1 &&
  1215. su_casenmatch(p, d[i], nlen)
  1216. && (d[i][nlen] == '=' || d[i][nlen] == '\0'))
  1217. ||
  1218. (prune == 2 && su_casematch(p, d[i]))
  1219. ||
  1220. (prune == 3 && strcmp(p, d[i]) == 0))
  1221. return 1;
  1222. }
  1223. return 0;
  1224. }
  1225. /**Join two parameter lists.
  1226. *
  1227. * The function @c msg_params_join() joins two parameter lists; the
  1228. * first list must have been created by @c msg_params_d() or by @c
  1229. * msg_params_dup() (or it may contain only @c NULL).
  1230. *
  1231. * @param home memory home
  1232. * @param dst pointer to pointer to destination parameter list
  1233. * @param src source list
  1234. * @param prune prune duplicates
  1235. * @param dup duplicate parameters in src list
  1236. *
  1237. * @par Pruning
  1238. * <table>
  1239. * <tr><td>0<td>do not prune</tr>
  1240. * <tr><td>1<td>prune parameters with identical names</tr>
  1241. * <tr><td>2<td>case-insensitive values</tr>
  1242. * <tr><td>3<td>case-sensitive values</tr>
  1243. * </table>
  1244. *
  1245. * @return
  1246. * @retval >= 0 when successful
  1247. * @retval -1 upon an error
  1248. */
  1249. issize_t msg_params_join(su_home_t *home,
  1250. msg_param_t **dst,
  1251. msg_param_t const *src,
  1252. unsigned prune,
  1253. int dup)
  1254. {
  1255. size_t n, m, n_before, n_after, pruned;
  1256. msg_param_t *d = *dst;
  1257. if (prune > 3)
  1258. return -1;
  1259. if (src == NULL || *src == NULL)
  1260. return 0;
  1261. /* Count number of parameters */
  1262. for (n = 0; d && d[n]; n++)
  1263. ;
  1264. n_before = MSG_PARAMS_NUM(n + 1);
  1265. for (m = 0, pruned = 0; src[m]; m++) {
  1266. if (n > 0 && prune > 0 && msg_param_prune(d, src[m], prune)) {
  1267. pruned++;
  1268. if (prune > 1)
  1269. continue;
  1270. }
  1271. }
  1272. n_after = MSG_PARAMS_NUM(n + m - pruned + 1);
  1273. if (n_before != n_after || !d) {
  1274. d = su_alloc(home, n_after * sizeof(*d));
  1275. assert(d); if (!d) return -1;
  1276. if (n)
  1277. memcpy(d, *dst, n * sizeof(*d));
  1278. *dst = d;
  1279. }
  1280. for (m = 0; src[m]; m++) {
  1281. if (pruned && msg_param_prune(d, src[m], prune)) {
  1282. pruned--;
  1283. if (prune > 1)
  1284. continue;
  1285. }
  1286. if (dup)
  1287. d[n++] = su_strdup(home, src[m]); /* XXX */
  1288. else
  1289. d[n++] = src[m];
  1290. }
  1291. d[n] = NULL;
  1292. return 0;
  1293. }
  1294. /**Join header item lists.
  1295. *
  1296. * Join items from a source header to the destination header. The item are
  1297. * compared with the existing ones. If a match is found, it is not added to
  1298. * the list. If @a duplicate is true, the entries are duplicated while they
  1299. * are added to the list.
  1300. *
  1301. * @param home memory home
  1302. * @param dst destination header
  1303. * @param src source header
  1304. * @param duplicate if true, allocate and copy items that are added
  1305. *
  1306. * @return
  1307. * @retval >= 0 when successful
  1308. * @retval -1 upon an error
  1309. *
  1310. * @NEW_1_12_5.
  1311. */
  1312. int msg_header_join_items(su_home_t *home,
  1313. msg_common_t *dst,
  1314. msg_common_t const *src,
  1315. int duplicate)
  1316. {
  1317. size_t N, m, M, i, n_before, n_after, total;
  1318. char *dup = NULL;
  1319. msg_param_t *d, **dd, *s;
  1320. msg_param_t t, *temp, temp0[16];
  1321. size_t *len, len0[(sizeof temp0)/(sizeof temp0[0])];
  1322. msg_update_f *update = NULL;
  1323. if (dst == NULL || dst->h_class->hc_params == 0 ||
  1324. src == NULL || src->h_class->hc_params == 0)
  1325. return -1;
  1326. s = *(msg_param_t **)((char *)src + src->h_class->hc_params);
  1327. if (s == NULL)
  1328. return 0;
  1329. for (M = 0; s[M]; M++)
  1330. {}
  1331. if (M == 0)
  1332. return 0;
  1333. if (M <= (sizeof temp0) / (sizeof temp0[0])) {
  1334. temp = temp0, len = len0;
  1335. }
  1336. else {
  1337. temp = malloc(M * (sizeof *temp) + M * (sizeof *len));
  1338. if (!temp) return -1;
  1339. len = (void *)(temp + M);
  1340. }
  1341. dd = (msg_param_t **)((char *)dst + dst->h_class->hc_params);
  1342. d = *dd;
  1343. for (N = 0; d && d[N]; N++)
  1344. {}
  1345. for (m = 0, M = 0, total = 0; s[m]; m++) {
  1346. t = s[m];
  1347. for (i = 0; i < N; i++)
  1348. if (strcmp(t, d[i]) == 0)
  1349. break;
  1350. if (i < N)
  1351. continue;
  1352. for (i = 0; i < M; i++)
  1353. if (strcmp(t, temp[i]) == 0)
  1354. break;
  1355. if (i < M)
  1356. continue;
  1357. temp[M] = t;
  1358. len[M] = strlen(t);
  1359. total += len[M++] + 1;
  1360. }
  1361. if (M == 0)
  1362. goto success;
  1363. dup = su_alloc(home, total); if (!dup) goto error;
  1364. n_before = MSG_PARAMS_NUM(N + 1);
  1365. n_after = MSG_PARAMS_NUM(N + M + 1);
  1366. if (d == NULL || n_before != n_after) {
  1367. d = su_alloc(home, n_after * sizeof(*d)); if (!d) goto error;
  1368. if (N)
  1369. memcpy(d, *dd, N * sizeof(*d));
  1370. *dd = d;
  1371. }
  1372. update = dst->h_class->hc_update;
  1373. for (m = 0; m < M; m++) {
  1374. d[N++] = memcpy(dup, temp[m], len[m] + 1);
  1375. if (update)
  1376. update(dst, dup, len[m], dup + len[m]);
  1377. dup += len[m] + 1;
  1378. }
  1379. d[N] = NULL;
  1380. success:
  1381. if (temp != temp0)
  1382. free(temp);
  1383. return 0;
  1384. error:
  1385. if (temp != temp0)
  1386. free(temp);
  1387. su_free(home, dup);
  1388. return -1;
  1389. }
  1390. /**Compare parameter lists.
  1391. *
  1392. * Compares parameter lists.
  1393. *
  1394. * @param a pointer to a parameter list
  1395. * @param b pointer to a parameter list
  1396. *
  1397. * @retval an integer less than zero if @a is less than @a b
  1398. * @retval an integer zero if @a match with @a b
  1399. * @retval an integer greater than zero if @a is greater than @a b
  1400. */
  1401. int msg_params_cmp(char const * const a[], char const * const b[])
  1402. {
  1403. int c;
  1404. size_t nlen;
  1405. if (a == NULL || b == NULL)
  1406. return (a != NULL) - (b != NULL);
  1407. for (;;) {
  1408. if (*a == NULL || *b == NULL)
  1409. return (*a != NULL) - (*b != NULL);
  1410. nlen = strcspn(*a, "=");
  1411. if ((c = su_strncasecmp(*a, *b, nlen)))
  1412. return c;
  1413. if ((c = strcmp(*a + nlen, *b + nlen)))
  1414. return c;
  1415. a++, b++;
  1416. }
  1417. }
  1418. /** Unquote string
  1419. *
  1420. * Duplicates the string @a q in unquoted form.
  1421. */
  1422. char *msg_unquote_dup(su_home_t *home, char const *q)
  1423. {
  1424. char *d;
  1425. size_t total, n, m;
  1426. /* First, easy case */
  1427. if (q[0] == '"')
  1428. q++;
  1429. n = strcspn(q, "\"\\");
  1430. if (q[n] == '\0' || q[n] == '"')
  1431. return su_strndup(home, q, n);
  1432. /* Hairy case - backslash-escaped chars */
  1433. total = n;
  1434. for (;;) {
  1435. if (q[n] == '\0' || q[n] == '"' || q[n + 1] == '\0')
  1436. break;
  1437. m = strcspn(q + n + 2, "\"\\");
  1438. total += m + 1;
  1439. n += m + 2;
  1440. }
  1441. if (!(d = su_alloc(home, total + 1)))
  1442. return NULL;
  1443. for (n = 0;;) {
  1444. m = strcspn(q, "\"\\");
  1445. memcpy(d + n, q, m);
  1446. n += m, q += m;
  1447. if (q[0] == '\0' || q[0] == '"' || q[1] == '\0')
  1448. break;
  1449. d[n++] = q[1];
  1450. q += 2;
  1451. }
  1452. assert(total == n);
  1453. d[n] = '\0';
  1454. return d;
  1455. }
  1456. /** Unquote string */
  1457. char *msg_unquote(char *dst, char const *s)
  1458. {
  1459. int copy = dst != NULL;
  1460. char *d = dst;
  1461. if (*s++ != '"')
  1462. return NULL;
  1463. for (;;) {
  1464. size_t n = strcspn(s, "\"\\");
  1465. if (copy)
  1466. memmove(d, s, n);
  1467. s += n;
  1468. d += n;
  1469. if (*s == '\0')
  1470. return NULL;
  1471. else if (*s == '"') {
  1472. if (copy) *d = '\0';
  1473. return dst;
  1474. }
  1475. else {
  1476. /* Copy quoted char */
  1477. if ((copy ? (*d++ = *++s) : *++s) == '\0')
  1478. return NULL;
  1479. s++;
  1480. }
  1481. }
  1482. }
  1483. /** Quote string */
  1484. issize_t msg_unquoted_e(char *b, isize_t bsiz, char const *s)
  1485. {
  1486. isize_t e = 0;
  1487. if (b == NULL)
  1488. bsiz = 0;
  1489. if (0 < bsiz)
  1490. *b = '"';
  1491. e++;
  1492. for (;*s;) {
  1493. size_t n = strcspn(s, "\"\\");
  1494. if (n == 0) {
  1495. if (b && e + 2 <= bsiz)
  1496. b[e] = '\\', b[e + 1] = s[0];
  1497. e += 2;
  1498. s++;
  1499. }
  1500. else {
  1501. if (b && (e + n <= bsiz))
  1502. memcpy(b + e, s, n);
  1503. e += n;
  1504. s += n;
  1505. }
  1506. }
  1507. if (b && e < bsiz)
  1508. b[e] = '"';
  1509. e++;
  1510. return e;
  1511. }
  1512. /** Calculate a simple hash over a string. */
  1513. unsigned long msg_hash_string(char const *id)
  1514. {
  1515. unsigned long hash = 0;
  1516. if (id)
  1517. for (; *id; id++) {
  1518. hash += (unsigned)*id;
  1519. hash *= 38501U;
  1520. }
  1521. else
  1522. hash *= 38501U;
  1523. if (hash == 0)
  1524. hash = (unsigned long)-1;
  1525. return hash;
  1526. }
  1527. /** Calculate the size of a duplicate of a header structure. */
  1528. isize_t msg_header_size(msg_header_t const *h)
  1529. {
  1530. if (h == NULL || h == MSG_HEADER_NONE)
  1531. return 0;
  1532. else
  1533. return h->sh_class->hc_dxtra(h, h->sh_class->hc_size);
  1534. }
  1535. /** Encode a message to the buffer.
  1536. *
  1537. * The function msg_encode_e encodes a message to a given buffer.
  1538. * It returns the length of the message to be encoded, even if the
  1539. * buffer is too small (just like snprintf() is supposed to do).
  1540. *
  1541. * @param b buffer (may be NULL)
  1542. * @param size size of buffer
  1543. * @param mo public message structure (#sip_t, #http_t)
  1544. * @param flags see #
  1545. */
  1546. issize_t msg_object_e(char b[], isize_t size, msg_pub_t const *mo, int flags)
  1547. {
  1548. size_t rv = 0;
  1549. ssize_t n;
  1550. msg_header_t const *h;
  1551. if (mo->msg_request)
  1552. h = mo->msg_request;
  1553. else
  1554. h = mo->msg_status;
  1555. for (; h; h = h->sh_succ) {
  1556. n = msg_header_e(b, size, h, flags);
  1557. if (n < 0)
  1558. return -1;
  1559. if ((size_t)n < size)
  1560. b += n, size -= n;
  1561. else
  1562. b = NULL, size = 0;
  1563. rv += n;
  1564. }
  1565. return rv;
  1566. }
  1567. /** Encode header contents. */
  1568. issize_t msg_header_field_e(char b[], isize_t bsiz, msg_header_t const *h, int flags)
  1569. {
  1570. assert(h); assert(h->sh_class);
  1571. return h->sh_class->hc_print(b, bsiz, h, flags);
  1572. }
  1573. /** Get offset of header @a h from structure @a mo. */
  1574. msg_header_t **
  1575. msg_header_offset(msg_t const *msg, msg_pub_t const *mo, msg_header_t const *h)
  1576. {
  1577. if (h == NULL || h->sh_class == NULL)
  1578. return NULL;
  1579. return msg_hclass_offset(msg->m_class, mo, h->sh_class);
  1580. }
  1581. /**Get a header from the public message structure.
  1582. *
  1583. * Gets a pointer to header from a message structure.
  1584. *
  1585. * @param pub public message structure from which header is obtained
  1586. * @param hc header class
  1587. */
  1588. msg_header_t *
  1589. msg_header_access(msg_pub_t const *pub, msg_hclass_t *hc)
  1590. {
  1591. msg_header_t * const * hh;
  1592. if (pub == NULL || hc == NULL)
  1593. return NULL;
  1594. hh = msg_hclass_offset((void *)pub->msg_ident, (msg_pub_t *)pub, hc);
  1595. if (hh)
  1596. return *hh;
  1597. else
  1598. return NULL;
  1599. }
  1600. #include <sofia-sip/su_uniqueid.h>
  1601. /** Generates a random token.
  1602. *
  1603. */
  1604. issize_t msg_random_token(char token[], isize_t tlen,
  1605. void const *rmemp, isize_t rsize)
  1606. {
  1607. uint32_t random = 0, rword;
  1608. uint8_t rbyte;
  1609. uint8_t const *rmem = rmemp;
  1610. size_t i;
  1611. ssize_t n;
  1612. static char const token_chars[33] =
  1613. /* Create aesthetically pleasing raNDom capS LooK */
  1614. "aBcDeFgHjKmNpQrStUvXyZ0123456789";
  1615. if (rmem == NULL && rsize == 0)
  1616. rsize = UINT_MAX;
  1617. if (rsize == 0) {
  1618. if (token && tlen > 0)
  1619. strcpy(token, "+");
  1620. return 1;
  1621. }
  1622. if (token == NULL) {
  1623. if (rsize >= tlen * 5 / 8)
  1624. return tlen;
  1625. else
  1626. return rsize / 5 * 8;
  1627. }
  1628. for (i = 0, n = 0; i < tlen;) {
  1629. if (n < 5) {
  1630. if (rsize == 0)
  1631. ;
  1632. else if (rmem) {
  1633. rbyte = *rmem++, rsize--;
  1634. random = random | (rbyte << n);
  1635. n += 8;
  1636. } else {
  1637. rword = su_random();
  1638. random = (rword >> 13) & 31;
  1639. n = 6;
  1640. }
  1641. }
  1642. token[i] = token_chars[random & 31];
  1643. random >>= 5;
  1644. i++, n -= 5;
  1645. if (n < 0 || (n == 0 && rsize == 0))
  1646. break;
  1647. }
  1648. token[i] = 0;
  1649. return i;
  1650. }
  1651. /** Parse a message.
  1652. *
  1653. * Parse a text message with parser @a mc. The @a data is copied and it is
  1654. * not modified or referenced by the parsed message.
  1655. *
  1656. * @par Example
  1657. * Parse a SIP message fragment (e.g., payload of NOTIFY sent in response to
  1658. * REFER):
  1659. * @code
  1660. * msg_t *m = msg_make(sip_default_mclass(), 0, pl->pl_data, pl->pl_len);
  1661. * sip_t *frag = sip_object(m);
  1662. * @endcode
  1663. *
  1664. * @param mc message class (parser table)
  1665. * @param flags message flags (see #msg_flg_user)
  1666. * @param data message text
  1667. * @param len size of message text (if -1, use strlen(data))
  1668. *
  1669. * @retval A pointer to a freshly allocated and parsed message.
  1670. *
  1671. * Upon parsing error, the header structure may be left incomplete. The
  1672. * #MSG_FLG_ERROR is set in @a msg_object(msg)->msg_flags.
  1673. *
  1674. * @since New in @VERSION_1_12_4
  1675. *
  1676. * @sa msg_as_string(), msg_extract()
  1677. */
  1678. msg_t *msg_make(msg_mclass_t const *mc, int flags,
  1679. void const *data, ssize_t len)
  1680. {
  1681. msg_t *msg;
  1682. msg_iovec_t iovec[2];
  1683. if (len == -1)
  1684. len = strlen(data);
  1685. if (len == 0)
  1686. return NULL;
  1687. msg = msg_create(mc, flags);
  1688. if (msg == NULL)
  1689. return NULL;
  1690. su_home_preload(msg_home(msg), 1, len + 1024);
  1691. if (msg_recv_iovec(msg, iovec, 2, len, 1) < 0) {
  1692. perror("msg_recv_iovec");
  1693. }
  1694. assert((ssize_t)iovec->mv_len == len);
  1695. memcpy(iovec->mv_base, data, len);
  1696. msg_recv_commit(msg, len, 1);
  1697. if (msg_extract(msg) < 0)
  1698. msg->m_object->msg_flags |= MSG_FLG_ERROR;
  1699. return msg;
  1700. }