cpl_parser.c 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2001-2003 FhG Fokus
  5. *
  6. * This file is part of ser, a free SIP server.
  7. *
  8. * ser is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version
  12. *
  13. * For a license to use the ser software under conditions
  14. * other than those described here, or to purchase support for this
  15. * software, please contact iptel.org by e-mail at the following addresses:
  16. * [email protected]
  17. *
  18. * ser is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with this program; if not, write to the Free Software
  25. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  26. */
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <stdlib.h>
  30. #include <sys/types.h>
  31. #include <sys/stat.h>
  32. #include <fcntl.h>
  33. #include <errno.h>
  34. #include <unistd.h>
  35. #include <libxml/xmlmemory.h>
  36. #include <libxml/parser.h>
  37. #include "../../parser/parse_uri.h"
  38. #include "../../dprint.h"
  39. #include "../../str.h"
  40. #include "../../ut.h"
  41. #include "CPL_tree.h"
  42. #include "sub_list.h"
  43. #include "cpl_log.h"
  44. static struct node *list = 0;
  45. static xmlDtdPtr dtd; /* DTD file */
  46. static xmlValidCtxt cvp; /* validating context */
  47. typedef unsigned short length_type ;
  48. typedef length_type* length_type_ptr;
  49. enum {EMAIL_TO,EMAIL_HDR_NAME,EMAIL_KNOWN_HDR_BODY,EMAIL_UNKNOWN_HDR_BODY};
  50. #define ENCONDING_BUFFER_SIZE 65536
  51. #define FOR_ALL_ATTR(_node,_attr) \
  52. for( (_attr)=(_node)->properties ; (_attr) ; (_attr)=(_attr)->next)
  53. /* right and left space trimming */
  54. #define trimlr(_s_) \
  55. do{\
  56. for(;(_s_).s[(_s_).len-1]==' ';(_s_).s[--(_s_).len]=0);\
  57. for(;(_s_).s[0]==' ';(_s_).s=(_s_).s+1,(_s_).len--);\
  58. }while(0);
  59. #define check_overflow(_p_,_offset_,_end_,_error_) \
  60. do{\
  61. if ((_p_)+(_offset_)>=(_end_)) { \
  62. LOG(L_ERR,"ERROR:cpl-c:%s:%d: overflow -> buffer to small\n",\
  63. __FILE__,__LINE__);\
  64. goto _error_;\
  65. }\
  66. }while(0)\
  67. #define set_attr_type(_p_,_type_,_end_,_error_) \
  68. do{\
  69. check_overflow(_p_,sizeof(length_type),_end_,_error_);\
  70. *((length_type_ptr)(_p_)) = htons((length_type)(_type_));\
  71. (_p_) += sizeof(length_type);\
  72. }while(0)\
  73. #define append_short_attr(_p_,_n_,_end_,_error_) \
  74. do{\
  75. check_overflow(_p_,sizeof(length_type),_end_,_error_);\
  76. *((length_type_ptr)(_p_)) = htons((length_type)(_n_));\
  77. (_p_) += sizeof(length_type);\
  78. }while(0)
  79. #define append_str_attr(_p_,_s_,_end_,_error_) \
  80. do{\
  81. check_overflow(_p_,(_s_).len + 1*((((_s_).len)&0x0001)==1),\
  82. _end_,_error_);\
  83. *((length_type_ptr)(_p_)) = htons((length_type)(_s_).len);\
  84. (_p_) += sizeof(length_type);\
  85. memcpy( (_p_), (_s_).s, (_s_).len);\
  86. (_p_) += (_s_).len + 1*((((_s_).len)&0x0001)==1);\
  87. }while(0)
  88. #define append_double_str_attr(_p_,_s1_,_s2_,_end_,_error_) \
  89. do{\
  90. check_overflow(_p_,(_s1_).len + (_s2_).len +\
  91. 1*((((_s2_).len+(_s2_).len)&0x0001)==1), _end_, _error_);\
  92. *((length_type_ptr)(_p_))=htons((length_type)((_s1_).len)+(_s2_).len);\
  93. (_p_) += sizeof(length_type);\
  94. memcpy( (_p_), (_s1_).s, (_s1_).len);\
  95. (_p_) += (_s1_).len;\
  96. memcpy( (_p_), (_s2_).s, (_s2_).len);\
  97. (_p_) += (_s2_).len + 1*((((_s1_).len+(_s2_).len)&0x0001)==1);\
  98. }while(0)
  99. #define get_attr_val(_attr_name_,_val_,_error_) \
  100. do { \
  101. (_val_).s = (char*)xmlGetProp(node,(_attr_name_));\
  102. (_val_).len = strlen((_val_).s);\
  103. /* remove all spaces from begin and end */\
  104. trimlr( (_val_) );\
  105. if ((_val_).len==0) {\
  106. LOG(L_ERR,"ERROR:cpl_c:%s:%d: attribute <%s> has an "\
  107. "empty value\n",__FILE__,__LINE__,(_attr_name_));\
  108. goto _error_;\
  109. }\
  110. }while(0)\
  111. #define MAX_EMAIL_HDR_SIZE 7 /*we are looking only for SUBJECT and BODY ;-)*/
  112. #define MAX_EMAIL_BODY_SIZE 512
  113. #define MAX_EMAIL_SUBJECT_SIZE 32
  114. static inline char *decode_mail_url(char *p, char *p_end, char *url,
  115. unsigned char *nr_attr)
  116. {
  117. static char buf[ MAX_EMAIL_HDR_SIZE ];
  118. char c;
  119. char foo;
  120. unsigned short hdr_len;
  121. unsigned short *len;
  122. int max_len;
  123. int status;
  124. /* init */
  125. hdr_len = 0;
  126. max_len = 0;
  127. status = EMAIL_TO;
  128. (*nr_attr) ++;
  129. set_attr_type(p, TO_ATTR, p_end, error); /* attr type */
  130. len = ((unsigned short*)(p)); /* attr val's len */
  131. *len = 0; /* init the len */
  132. p += 2;
  133. /* parse the whole url */
  134. do {
  135. /* extract a char from the encoded url */
  136. if (*url=='+') {
  137. /* substitute a blank for a plus */
  138. c=' ';
  139. url++;
  140. /* Look for a hex encoded character */
  141. } else if ( (*url=='%') && *(url+1) && *(url+2) ) {
  142. /* hex encoded - convert to a char */
  143. c = hex2int(url[1]);
  144. foo = hex2int(url[2]);
  145. if (c==-1 || foo==-1) {
  146. LOG(L_ERR, "ERROR:cpl_c:decode_mail_url: non-ASCII escaped "
  147. "character in mail url [%.*s]\n", 3, url);
  148. goto error;
  149. }
  150. c = c<<4 | foo;
  151. url += 3;
  152. } else {
  153. /* normal character - just copy it without changing */
  154. c = *url;
  155. url++;
  156. }
  157. /* finally we got a character !! */
  158. switch (c) {
  159. case '?':
  160. switch (status) {
  161. case EMAIL_TO:
  162. if (*len==0) {
  163. LOG(L_ERR,"ERROR:cpl_c:decode_mail_url: empty TO "
  164. "address found in MAIL node!\n");
  165. goto error;
  166. }
  167. if (((*len)&0x0001)==1) p++;
  168. *len = htons(*len);
  169. hdr_len = 0;
  170. status = EMAIL_HDR_NAME;
  171. break;
  172. default: goto parse_error;
  173. }
  174. break;
  175. case '=':
  176. switch (status) {
  177. case EMAIL_HDR_NAME:
  178. DBG("DEBUG:cpl_c:decode_mail_url: hdr [%.*s] found\n",
  179. hdr_len,buf);
  180. if ( hdr_len==BODY_EMAILHDR_LEN &&
  181. strncasecmp(buf,BODY_EMAILHDR_STR,hdr_len)==0 ) {
  182. /* BODY hdr found */
  183. set_attr_type( p, BODY_ATTR, p_end, error);
  184. max_len = MAX_EMAIL_BODY_SIZE;
  185. } else if ( hdr_len==SUBJECT_EMAILHDR_LEN &&
  186. strncasecmp(buf,SUBJECT_EMAILHDR_STR,hdr_len)==0 ) {
  187. /* SUBJECT hdr found */
  188. set_attr_type( p, SUBJECT_ATTR, p_end, error);
  189. max_len = MAX_EMAIL_SUBJECT_SIZE;
  190. } else {
  191. DBG("DEBUG:cpl_c:decode_mail_url: unknown hdr ->"
  192. " ignoring\n");
  193. status = EMAIL_UNKNOWN_HDR_BODY;
  194. break;
  195. }
  196. (*nr_attr) ++;
  197. len = ((unsigned short*)(p)); /* attr val's len */
  198. *len = 0; /* init the len */
  199. p += 2;
  200. status = EMAIL_KNOWN_HDR_BODY;
  201. break;
  202. default: goto parse_error;
  203. }
  204. break;
  205. case '&':
  206. switch (status) {
  207. case EMAIL_KNOWN_HDR_BODY:
  208. if (((*len)&0x0001)==1) p++;
  209. *len = htons(*len);
  210. case EMAIL_UNKNOWN_HDR_BODY:
  211. hdr_len = 0;
  212. status = EMAIL_HDR_NAME;
  213. break;
  214. default: goto parse_error;
  215. }
  216. break;
  217. case 0:
  218. switch (status) {
  219. case EMAIL_TO:
  220. if (*len==0) {
  221. LOG(L_ERR,"ERROR:cpl_c:decode_mail_url: empty TO "
  222. "address found in MAIL node!\n");
  223. goto error;
  224. }
  225. case EMAIL_KNOWN_HDR_BODY:
  226. if (((*len)&0x0001)==1) p++;
  227. *len = htons(*len);
  228. case EMAIL_UNKNOWN_HDR_BODY:
  229. break;
  230. default: goto parse_error;
  231. }
  232. break;
  233. default:
  234. switch (status) {
  235. case EMAIL_TO:
  236. (*len)++;
  237. *(p++) = c;
  238. if (*len==URL_MAILTO_LEN &&
  239. !strncasecmp(p-(*len),URL_MAILTO_STR,(*len))) {
  240. DBG("DEBUG:cpl_c:decode_mail_url: MAILTO: found at"
  241. " the beginning of TO -> removed\n");
  242. p -= (*len);
  243. *len = 0;
  244. }
  245. break;
  246. case EMAIL_KNOWN_HDR_BODY:
  247. if ((*len)<max_len) (*len)++;
  248. *(p++) = c;
  249. break;
  250. case EMAIL_HDR_NAME:
  251. if (hdr_len<MAX_EMAIL_HDR_SIZE) hdr_len++;
  252. buf[hdr_len-1] = c;
  253. break;
  254. case EMAIL_UNKNOWN_HDR_BODY:
  255. /* do nothing */
  256. break;
  257. default : goto parse_error;
  258. }
  259. }
  260. }while(c!=0);
  261. return p;
  262. parse_error:
  263. LOG(L_ERR,"ERROR:cpl_c:decode_mail_url: unexpected char [%c] in state %d"
  264. " in email url \n",*url,status);
  265. error:
  266. return 0;
  267. }
  268. /* Attr. encoding for ADDRESS node:
  269. * | attr_t(2) attr_len(2) attr_val(2*x) | IS/CONTAINS/SUBDOMAIN_OF attr (NT)
  270. */
  271. static inline int encode_address_attr(xmlNodePtr node, char *node_ptr, char *buf_end)
  272. {
  273. xmlAttrPtr attr;
  274. char *p, *p_orig;
  275. unsigned char *nr_attr;
  276. str val;
  277. nr_attr = &(NR_OF_ATTR(node_ptr));
  278. *nr_attr = 0;
  279. p = p_orig = ATTR_PTR(node_ptr);
  280. FOR_ALL_ATTR(node,attr) {
  281. (*nr_attr)++;
  282. switch (attr->name[0]) {
  283. case 'i': case 'I':
  284. set_attr_type(p, IS_ATTR, buf_end, error);
  285. break;
  286. case 'c': case 'C':
  287. set_attr_type(p, CONTAINS_ATTR, buf_end, error);
  288. break;
  289. case 's': case 'S':
  290. set_attr_type(p, SUBDOMAIN_OF_ATTR, buf_end, error);
  291. break;
  292. default:
  293. LOG(L_ERR,"ERROR:cpl_c:encode_address_attr: unknown attribute "
  294. "<%s>\n",attr->name);
  295. goto error;
  296. }
  297. /* get the value of the attribute */
  298. get_attr_val( attr->name , val, error);
  299. /* copy also the \0 from the end of string */
  300. val.len++;
  301. append_str_attr(p, val, buf_end, error);
  302. }
  303. return p-p_orig;
  304. error:
  305. return -1;
  306. }
  307. /* Attr. encoding for ADDRESS_SWITCH node:
  308. * | attr1_t(2) attr1_val(2) | FIELD attr
  309. * [| attr2_t(2) attr2_val(2) |]? SUBFILED attr
  310. */
  311. static inline int encode_address_switch_attr(xmlNodePtr node, char *node_ptr,
  312. char *buf_end)
  313. {
  314. xmlAttrPtr attr;
  315. char *p, *p_orig;
  316. unsigned char *nr_attr;
  317. str val;
  318. nr_attr = &(NR_OF_ATTR(node_ptr));
  319. *nr_attr = 0;
  320. p = p_orig = ATTR_PTR(node_ptr);
  321. FOR_ALL_ATTR(node,attr) {
  322. (*nr_attr)++;
  323. /* get the value of the attribute */
  324. get_attr_val( attr->name , val, error);
  325. switch(attr->name[0]) {
  326. case 'F': case 'f':
  327. set_attr_type(p, FIELD_ATTR, buf_end, error);
  328. if (val.s[0]=='D' || val.s[0]=='d')
  329. append_short_attr(p, DESTINATION_VAL, buf_end, error);
  330. else if (val.s[6]=='A' || val.s[6]=='a')
  331. append_short_attr(p,ORIGINAL_DESTINATION_VAL,buf_end,error);
  332. else if (!val.s[6])
  333. append_short_attr(p, ORIGIN_VAL, buf_end, error);
  334. else {
  335. LOG(L_ERR,"ERROR:cpl_c:encode_address_switch_attr: unknown"
  336. " value <%s> for FIELD attr\n",val.s);
  337. goto error;
  338. };
  339. break;
  340. case 'S': case 's':
  341. set_attr_type(p, SUBFIELD_ATTR, buf_end, error);
  342. switch (val.s[0]) {
  343. case 'u': case 'U':
  344. append_short_attr(p, USER_VAL, buf_end, error);
  345. break;
  346. case 'h': case 'H':
  347. append_short_attr(p, HOST_VAL, buf_end, error);
  348. break;
  349. case 'p': case 'P':
  350. append_short_attr(p, PORT_VAL, buf_end, error);
  351. break;
  352. case 't': case 'T':
  353. append_short_attr(p, TEL_VAL, buf_end, error);
  354. break;
  355. case 'd': case 'D':
  356. /*append_short_attr(p, DISPLAY_VAL, buf_end, error);
  357. break;*/ /* NOT YET SUPPORTED BY INTERPRETER */
  358. case 'a': case 'A':
  359. /*append_short_attr(p, ADDRESS_TYPE_VAL, buf_end,error);
  360. break;*/ /* NOT YET SUPPORTED BY INTERPRETER */
  361. default:
  362. LOG(L_ERR,"ERROR:cpl_c:encode_address_switch_attr: "
  363. "unknown value <%s> for SUBFIELD attr\n",val.s);
  364. goto error;
  365. }
  366. break;
  367. default:
  368. LOG(L_ERR,"ERROR:cpl_c:encode_address_switch_attr: unknown"
  369. " attribute <%s>\n",attr->name);
  370. goto error;
  371. }
  372. }
  373. return p-p_orig;
  374. error:
  375. return -1;
  376. }
  377. /* Attr. encoding for LANGUAGE node:
  378. * | attr_t(2) attr_len(2) attr_val(2*x) | MATCHES attr (NNT)
  379. */
  380. static inline int encode_lang_attr(xmlNodePtr node, char *node_ptr, char *buf_end)
  381. {
  382. xmlAttrPtr attr;
  383. char *p, *p_orig;
  384. unsigned char *nr_attr;
  385. char *end;
  386. char *val_bk;
  387. str val;
  388. nr_attr = &(NR_OF_ATTR(node_ptr));
  389. *nr_attr = 0;
  390. p = p_orig = ATTR_PTR(node_ptr);
  391. FOR_ALL_ATTR(node,attr) {
  392. /* there is only one attribute -> MATCHES */
  393. if (attr->name[0]!='M' && attr->name[0]!='m') {
  394. LOG(L_ERR,"ERROR:cpl_c:encode_lang_attr: unknown attribute "
  395. "<%s>\n",attr->name);
  396. goto error;
  397. }
  398. val.s = val_bk = (char*)xmlGetProp(node,attr->name);
  399. /* parse the language-tag */
  400. for(end=val.s,val.len=0;;end++) {
  401. /* trim all spaces from the beginning of the tag */
  402. if (!val.len && (*end==' ' || *end=='\t')) continue;
  403. /* we cannot have more than 2 attrs - LANG_TAG and LANG_SUBTAG */
  404. if ((*nr_attr)>=2) goto lang_error;
  405. if (((*end)|0x20)>='a' && ((*end)|0x20)<='z') {
  406. val.len++; continue;
  407. } else if (*end=='*' && val.len==0 && (*nr_attr)==0 &&
  408. (*end==' '|| *end=='\t' || *end==0)) {
  409. val.len++;
  410. set_attr_type(p, MATCHES_TAG_ATTR, buf_end, error);
  411. } else if (val.len && (*nr_attr)==0 && *end=='-' ) {
  412. set_attr_type(p, MATCHES_TAG_ATTR, buf_end, error);
  413. } else if (val.len && ((*nr_attr)==0 || (*nr_attr)==1) &&
  414. (*end==' '|| *end=='\t' || *end==0)) {
  415. set_attr_type(p,
  416. (!(*nr_attr))?MATCHES_TAG_ATTR:MATCHES_SUBTAG_ATTR,
  417. buf_end, error );
  418. } else goto lang_error;
  419. (*nr_attr)++;
  420. /*DBG("----> language tag=%d; %d [%.*s]\n",*(p-1),
  421. val.len,val.len,end-val.len);*/
  422. val.s = end-val.len;
  423. append_str_attr(p, val, buf_end, error);
  424. val.len = 0;
  425. if (*end==0) break;
  426. }
  427. }
  428. return p-p_orig;
  429. lang_error:
  430. LOG(L_ERR,"ERROR:cpl-c:encode_lang_attr: bad value for language_tag <%s>\n",
  431. val_bk);
  432. error:
  433. return -1;
  434. }
  435. /* Attr. encoding for PRIORITY node:
  436. * | attr1_t(2) attr1_val(2) | LESS/GREATER/EQUAL attr
  437. * [| attr2_t(2) attr2_len(2) attr_val(2*x) |]? PRIOSTR attr (NT)
  438. */
  439. static inline int encode_priority_attr(xmlNodePtr node, char *node_ptr, char *buf_end)
  440. {
  441. xmlAttrPtr attr;
  442. char *p, *p_orig;
  443. unsigned char *nr_attr;
  444. str val;
  445. nr_attr = &(NR_OF_ATTR(node_ptr));
  446. *nr_attr = 0;
  447. p = p_orig = ATTR_PTR(node_ptr);
  448. FOR_ALL_ATTR(node,attr) {
  449. (*nr_attr)++;
  450. /* attribute's name */
  451. switch(attr->name[0]) {
  452. case 'L': case 'l':
  453. set_attr_type(p, LESS_ATTR, buf_end, error);
  454. break;
  455. case 'G': case 'g':
  456. set_attr_type(p, GREATER_ATTR, buf_end, error);
  457. break;
  458. case 'E': case 'e':
  459. set_attr_type(p, EQUAL_ATTR, buf_end, error);
  460. break;
  461. default:
  462. LOG(L_ERR,"ERROR:cpl_c:encode_priority_attr: unknown attribute "
  463. "<%s>\n",attr->name);
  464. goto error;
  465. }
  466. /* attribute's encoded value */
  467. get_attr_val( attr->name , val, error);
  468. if ( val.len==EMERGENCY_STR_LEN &&
  469. !strncasecmp(val.s,EMERGENCY_STR,val.len) ) {
  470. append_short_attr(p, EMERGENCY_VAL, buf_end, error);
  471. } else if ( val.len==URGENT_STR_LEN &&
  472. !strncasecmp(val.s,URGENT_STR,val.len) ) {
  473. append_short_attr(p, URGENT_VAL, buf_end, error);
  474. } else if ( val.len==NORMAL_STR_LEN &&
  475. !strncasecmp(val.s,NORMAL_STR,val.len) ) {
  476. append_short_attr(p, NORMAL_VAL, buf_end, error);
  477. } else if ( val.len==NON_URGENT_STR_LEN &&
  478. !strncasecmp(val.s,NON_URGENT_STR,val.len) ) {
  479. append_short_attr(p, NON_URGENT_VAL, buf_end, error);
  480. } else {
  481. append_short_attr(p, UNKNOWN_PRIO_VAL, buf_end, error);
  482. set_attr_type(p, PRIOSTR_ATTR, buf_end, error);
  483. val.len++; /* append \0 also */
  484. append_str_attr(p, val, buf_end, error);
  485. }
  486. }
  487. return p-p_orig;
  488. error:
  489. return -1;
  490. }
  491. /* Attr. encoding for STRING_SWITCH node:
  492. * [| attr1_t(2) attr1_len(2) attr_val(2*x) |]? IS attr (NT)
  493. * [| attr2_t(2) attr2_len(2) attr_val(2*x) |]? CONTAINS attr (NT)
  494. */
  495. static inline int encode_string_switch_attr(xmlNodePtr node, char *node_ptr,
  496. char *buf_end)
  497. {
  498. xmlAttrPtr attr;
  499. char *p, *p_orig;
  500. unsigned char *nr_attr;
  501. str val;
  502. nr_attr = &(NR_OF_ATTR(node_ptr));
  503. *nr_attr = 0;
  504. p = p_orig = ATTR_PTR(node_ptr);
  505. FOR_ALL_ATTR(node,attr) {
  506. (*nr_attr)++;
  507. /* there is only one attribute -> MATCHES */
  508. if (attr->name[0]!='F' && attr->name[0]!='f') {
  509. LOG(L_ERR,"ERROR:cpl_c:encode_string_switch_attr: unknown "
  510. "attribute <%s>\n",attr->name);
  511. goto error;
  512. }
  513. set_attr_type(p, FIELD_ATTR, buf_end, error);
  514. /* attribute's encoded value */
  515. get_attr_val( attr->name , val, error);
  516. switch (val.s[0]) {
  517. case 'S': case 's':
  518. append_short_attr(p, SUBJECT_VAL, buf_end, error);
  519. break;
  520. case 'O': case 'o':
  521. append_short_attr(p, ORGANIZATION_VAL, buf_end, error);
  522. break;
  523. case 'U': case 'u':
  524. append_short_attr(p, USER_AGENT_VAL, buf_end, error);
  525. break;
  526. case 'D': case 'd':
  527. append_short_attr(p, DISPLAY_VAL, buf_end, error);
  528. break;
  529. default:
  530. LOG(L_ERR,"ERROR:cpl_c:encode_string_switch_attr: unknown "
  531. "value <%s> for FIELD\n",attr->name);
  532. goto error;
  533. }
  534. }
  535. return p-p_orig;
  536. error:
  537. return -1;
  538. }
  539. /* Attr. encoding for STRING node:
  540. * [| attr1_t(2) attr1_len(2) attr_val(2*x) |]? IS attr (NT)
  541. * [| attr2_t(2) attr2_len(2) attr_val(2*x) |]? CONTAINS attr (NT)
  542. */
  543. static inline int encode_string_attr(xmlNodePtr node, char *node_ptr, char *buf_end)
  544. {
  545. xmlAttrPtr attr;
  546. char *p, *p_orig;
  547. unsigned char *nr_attr;
  548. str val;
  549. nr_attr = &(NR_OF_ATTR(node_ptr));
  550. *nr_attr = 0;
  551. p = p_orig = ATTR_PTR(node_ptr);
  552. FOR_ALL_ATTR(node,attr) {
  553. (*nr_attr)++;
  554. switch(attr->name[0]) {
  555. case 'I': case 'i':
  556. set_attr_type(p, IS_ATTR, buf_end, error);
  557. break;
  558. case 'C': case 'c':
  559. set_attr_type(p, CONTAINS_ATTR, buf_end, error);
  560. break;
  561. default:
  562. LOG(L_ERR,"ERROR:cpl_c:encode_string_attr: unknown "
  563. "attribute <%s>\n",attr->name);
  564. goto error;
  565. }
  566. /* attribute's encoded value */
  567. get_attr_val( attr->name , val, error);
  568. val.len++; /* grab also the \0 */
  569. append_str_attr(p,val, buf_end, error);
  570. }
  571. return p-p_orig;
  572. error:
  573. return -1;
  574. }
  575. /* Attr. encoding for TIME_SWITCH node:
  576. * [| attr1_t(2) attr1_len(2) attr_val(2*x) |]? TZID attr (NT)
  577. * [| attr2_t(2) attr2_len(2) attr_val(2*x) |]? TZURL attr (NT)
  578. */
  579. static inline int encode_time_switch_attr(xmlNodePtr node, char *node_ptr,
  580. char *buf_end)
  581. {
  582. static str tz_str = STR_STATIC_INIT("TZ=");
  583. xmlAttrPtr attr;
  584. char *p, *p_orig;
  585. unsigned char *nr_attr;
  586. str val;
  587. nr_attr = &(NR_OF_ATTR(node_ptr));
  588. *nr_attr = 0;
  589. p = p_orig = ATTR_PTR(node_ptr);
  590. FOR_ALL_ATTR(node,attr) {
  591. (*nr_attr)++;
  592. switch(attr->name[2]) {
  593. case 'I': case 'i':
  594. set_attr_type(p, TZID_ATTR, buf_end, error);
  595. /* attribute's encoded value */
  596. get_attr_val( attr->name , val, error);
  597. val.len++; /* grab also the \0 */
  598. append_double_str_attr(p,tz_str,val, buf_end, error);
  599. break;
  600. case 'U': case 'u':
  601. /* set_attr_type(p, TZURL_ATTR, buf_end, error);
  602. * is a waste of space to copy the url - the interpreter doesn't
  603. * use it at all ;-) */
  604. break;
  605. default:
  606. LOG(L_ERR,"ERROR:cpl_c:encode_time_switch_attr: unknown "
  607. "attribute <%s>\n",attr->name);
  608. goto error;
  609. }
  610. }
  611. return p-p_orig;
  612. error:
  613. return -1;
  614. }
  615. /* Attr. encoding for TIME node:
  616. * | attr1_t(2) attr1_len(2) attr1_val(2*x) | DSTART attr (NT)
  617. * [| attr2_t(2) attr2_len(2) attr2_val(2*x) |]? DTEND attr (NT)
  618. * [| attr3_t(2) attr3_len(2) attr3_val(2*x) |]? DURATION attr (NT)
  619. * [| attr4_t(2) attr4_len(2) attr4_val(2*x) |]? FREQ attr (NT)
  620. * [| attr5_t(2) attr5_len(2) attr5_val(2*x) |]? WKST attr (NT)
  621. * [| attr6_t(2) attr6_len(2) attr6_val(2*x) |]? BYYEARDAY attr (NT)
  622. * [| attr7_t(2) attr7_len(2) attr7_val(2*x) |]? COUNT attr (NT)
  623. * [| attr8_t(2) attr8_len(2) attr8_val(2*x) |]? BYSETPOS attr (NT)
  624. * [| attr9_t(2) attr9_len(2) attr9_val(2*x) |]? BYMONTH attr (NT)
  625. * [| attr10_t(2) attr10_len(2) attr_val10(2*x) |]? BYMONTHDAY attr (NT)
  626. * [| attr11_t(2) attr11_len(2) attr_val11(2*x) |]? BYMINUTE attr (NT)
  627. * [| attr12_t(2) attr12_len(2) attr_val12(2*x) |]? INTERVAL attr (NT)
  628. * [| attr13_t(2) attr13_len(2) attr_val13(2*x) |]? UNTIL attr (NT)
  629. * [| attr14_t(2) attr14_len(2) attr_val14(2*x) |]? BYSECOND attr (NT)
  630. * [| attr15_t(2) attr15_len(2) attr_val15(2*x) |]? BYHOUR attr (NT)
  631. * [| attr16_t(2) attr16_len(2) attr_val16(2*x) |]? BYDAY attr (NT)
  632. * [| attr17_t(2) attr17_len(2) attr_val17(2*x) |]? BYWEEKNO attr (NT)
  633. */
  634. static inline int encode_time_attr(xmlNodePtr node, char *node_ptr,
  635. char *buf_end)
  636. {
  637. xmlAttrPtr attr;
  638. char *p, *p_orig;
  639. unsigned char *nr_attr;
  640. str val;
  641. nr_attr = &(NR_OF_ATTR(node_ptr));
  642. *nr_attr = 0;
  643. p = p_orig = ATTR_PTR(node_ptr);
  644. FOR_ALL_ATTR(node,attr) {
  645. (*nr_attr)++;
  646. switch (attr->name[4]) {
  647. case 0:
  648. if (attr->name[0]=='F' || attr->name[0]=='f')
  649. set_attr_type(p, FREQ_ATTR, buf_end, error);
  650. else if (attr->name[0]=='W' || attr->name[0]=='w')
  651. set_attr_type(p, WKST_ATTR, buf_end, error);
  652. break;
  653. case 'a': case 'A':
  654. if (attr->name[0]=='D' || attr->name[0]=='d')
  655. set_attr_type(p, DTSTART_ATTR, buf_end, error);
  656. else if (attr->name[0]=='B' || attr->name[0]=='b')
  657. set_attr_type(p, BYYEARDAY_ATTR, buf_end, error);
  658. break;
  659. case 't': case 'T':
  660. if (attr->name[0]=='D' || attr->name[0]=='d')
  661. set_attr_type(p, DURATION_ATTR, buf_end, error);
  662. else if (attr->name[0]=='C' || attr->name[0]=='c')
  663. set_attr_type(p, COUNT_ATTR, buf_end, error);
  664. else if (attr->name[0]=='B' || attr->name[0]=='b')
  665. set_attr_type(p, BYSETPOS_ATTR, buf_end, error);
  666. break;
  667. case 'n': case 'N':
  668. if (!attr->name[0])
  669. set_attr_type(p, BYMONTH_ATTR, buf_end, error);
  670. else if (attr->name[0]=='D' || attr->name[0]=='d')
  671. set_attr_type(p, BYMONTHDAY_ATTR, buf_end, error);
  672. else if (attr->name[0]=='e' || attr->name[0]=='E')
  673. set_attr_type(p, BYMINUTE_ATTR, buf_end, error);
  674. break;
  675. case 'd': case 'D':
  676. set_attr_type(p, DTEND_ATTR, buf_end, error);
  677. break;
  678. case 'r': case 'R':
  679. set_attr_type(p, INTERVAL_ATTR, buf_end, error);
  680. break;
  681. case 'l': case 'L':
  682. set_attr_type(p, UNTIL_ATTR, buf_end, error);
  683. break;
  684. case 'c': case 'C':
  685. set_attr_type(p, BYSECOND_ATTR, buf_end, error);
  686. break;
  687. case 'u': case 'U':
  688. set_attr_type(p, BYHOUR_ATTR, buf_end, error);
  689. break;
  690. case 'y': case 'Y':
  691. set_attr_type(p, BYDAY_ATTR, buf_end, error);
  692. break;
  693. case 'e': case 'E':
  694. set_attr_type(p, BYWEEKNO_ATTR, buf_end, error);
  695. break;
  696. default:
  697. LOG(L_ERR,"ERROR:cpl_c:encode_time_attr: unknown "
  698. "attribute <%s>\n",attr->name);
  699. goto error;
  700. }
  701. /* attribute's encoded value */
  702. get_attr_val( attr->name , val, error);
  703. val.len++; /* grab also the \0 */
  704. append_str_attr(p,val, buf_end, error);
  705. }
  706. return p-p_orig;
  707. error:
  708. return -1;
  709. }
  710. /* Attr. encoding for LOOKUP node:
  711. * | attr1_t(2) attr1_len(2) attr1_val(2*x) | SOURCE attr (NT)
  712. * [| attr2_t(2) attr2_val(2) |]? CLEAR attr
  713. */
  714. static inline int encode_lookup_attr(xmlNodePtr node, char *node_ptr,
  715. char *buf_end)
  716. {
  717. xmlAttrPtr attr;
  718. char *p, *p_orig;
  719. unsigned char *nr_attr;
  720. str val;
  721. nr_attr = &(NR_OF_ATTR(node_ptr));
  722. *nr_attr = 0;
  723. p = p_orig = ATTR_PTR(node_ptr);
  724. FOR_ALL_ATTR(node,attr) {
  725. /* get attribute's value */
  726. get_attr_val( attr->name , val, error);
  727. if ( !strcasecmp((const char*)attr->name,"source") ) {
  728. /* this param will not be copied, since it has only one value ;-)*/
  729. if ( val.len!=SOURCE_REG_STR_LEN ||
  730. strncasecmp( val.s, SOURCE_REG_STR, val.len) ) {
  731. LOG(L_ERR,"ERROR:cpl_c:encode_lookup_attr: unsupported value"
  732. " <%.*s> in SOURCE param\n",val.len,val.s);
  733. goto error;
  734. }
  735. } else if ( !strcasecmp((const char*)attr->name,"clear") ) {
  736. (*nr_attr)++;
  737. set_attr_type(p, CLEAR_ATTR, buf_end, error);
  738. if ( val.len==3 && !strncasecmp(val.s,"yes",3) )
  739. append_short_attr(p, YES_VAL, buf_end, error);
  740. else if ( val.len==2 && !strncasecmp(val.s,"no",2) )
  741. append_short_attr(p, NO_VAL, buf_end, error);
  742. else {
  743. LOG(L_ERR,"ERROR:cpl_c:encode_lookup_attr: unknown value "
  744. "<%.*s> for attribute CLEAR\n",val.len,val.s);
  745. goto error;
  746. }
  747. } else if ( !strcasecmp((const char*)attr->name,"timeout") ) {
  748. LOG(L_WARN,"WARNING:cpl_c:encode_lookup_attr: unsupported param "
  749. "TIMEOUT; skipping\n");
  750. } else {
  751. LOG(L_ERR,"ERROR:cpl_c:encode_lookup_attr: unknown attribute "
  752. "<%s>\n",attr->name);
  753. goto error;
  754. }
  755. }
  756. return p-p_orig;
  757. error:
  758. return -1;
  759. }
  760. /* Attr. encoding for LOCATION node:
  761. * | attr1_t(2) attr1_len(2) attr1_val(2*x) | URL attr (NT)
  762. * [| attr2_t(2) attr2_val(2) |]? PRIORITY attr
  763. * [| attr3_t(2) attr3_val(2) |]? CLEAR attr
  764. */
  765. static inline int encode_location_attr(xmlNodePtr node, char *node_ptr,
  766. char *buf_end)
  767. {
  768. struct sip_uri uri;
  769. xmlAttrPtr attr;
  770. char *p, *p_orig;
  771. unsigned char *nr_attr;
  772. unsigned short nr;
  773. str val;
  774. nr_attr = &(NR_OF_ATTR(node_ptr));
  775. *nr_attr = 0;
  776. p = p_orig = ATTR_PTR(node_ptr);
  777. FOR_ALL_ATTR(node,attr) {
  778. (*nr_attr)++;
  779. /* get attribute's value */
  780. get_attr_val( attr->name , val, error);
  781. switch(attr->name[0]) {
  782. case 'U': case 'u':
  783. set_attr_type(p, URL_ATTR, buf_end, error);
  784. /* check if it's a valid SIP URL -> just call
  785. * parse uri function and see if returns error ;-) */
  786. if (parse_uri( val.s, val.len, &uri)!=0) {
  787. LOG(L_ERR,"ERROR:cpl-c:encrypt_location_attr: <%s> is "
  788. "not a valid SIP URL\n",val.s);
  789. goto error;
  790. }
  791. val.len++; /*copy also the \0 */
  792. append_str_attr(p,val, buf_end, error);
  793. break;
  794. case 'P': case 'p':
  795. set_attr_type(p, PRIORITY_ATTR, buf_end, error);
  796. if (val.s[0]=='0') nr=0;
  797. else if (val.s[0]=='1') nr=10;
  798. else goto prio_error;
  799. if (val.s[1]!='.') goto prio_error;
  800. if (val.s[2]<'0' || val.s[2]>'9') goto prio_error;
  801. nr += val.s[2] - '0';
  802. if (nr>10)
  803. goto prio_error;
  804. append_short_attr(p, nr, buf_end, error);
  805. break;
  806. case 'C': case 'c':
  807. set_attr_type(p, CLEAR_ATTR, buf_end, error);
  808. if (val.s[0]=='y' || val.s[0]=='Y')
  809. append_short_attr(p, YES_VAL, buf_end, error);
  810. else
  811. append_short_attr(p, NO_VAL, buf_end, error);
  812. break;
  813. default:
  814. LOG(L_ERR,"ERROR:cpl_c:encode_location_attr: unknown attribute "
  815. "<%s>\n",attr->name);
  816. goto error;
  817. }
  818. }
  819. return p-p_orig;
  820. prio_error:
  821. LOG(L_ERR,"ERROR:cpl_c:encode_location_attr: invalid priority <%s>\n",
  822. val.s);
  823. error:
  824. return -1;
  825. }
  826. /* Attr. encoding for REMOVE_LOCATION node:
  827. * [| attr1_t(2) attr1_len(2) attr1_val(2*x) |]? LOCATION attr (NT)
  828. */
  829. static inline int encode_rmvloc_attr(xmlNodePtr node, char *node_ptr, char *buf_end)
  830. {
  831. struct sip_uri uri;
  832. xmlAttrPtr attr;
  833. char *p, *p_orig;
  834. unsigned char *nr_attr;
  835. str val;
  836. nr_attr = &(NR_OF_ATTR(node_ptr));
  837. *nr_attr = 0;
  838. p = p_orig = ATTR_PTR(node_ptr);
  839. FOR_ALL_ATTR(node,attr) {
  840. (*nr_attr)++;
  841. switch(attr->name[0]) {
  842. case 'L': case 'l':
  843. set_attr_type(p, LOCATION_ATTR, buf_end, error);
  844. /* get the value of the attribute */
  845. get_attr_val( attr->name , val, error);
  846. /* check if it's a valid SIP URL -> just call
  847. * parse uri function and see if returns error ;-) */
  848. if (parse_uri( val.s, val.len, &uri)!=0) {
  849. LOG(L_ERR,"ERROR:cpl-c:encrypt_rmvloc_attr: <%s> is "
  850. "not a valid SIP URL\n",val.s);
  851. goto error;
  852. }
  853. val.len++; /*copy also the \0 */
  854. append_str_attr(p,val, buf_end, error);
  855. break;
  856. case 'P': case 'p':
  857. case 'V': case 'v':
  858. /* as the interpreter ignores PARAM and VALUE attributes, we will
  859. * do the same ;-) */
  860. break;
  861. default:
  862. LOG(L_ERR,"ERROR:cpl_c:encode_rmvloc_attr: unknown attribute "
  863. "<%s>\n",attr->name);
  864. goto error;
  865. }
  866. }
  867. return p-p_orig;
  868. error:
  869. return -1;
  870. }
  871. /* Attr. encoding for PROXY node:
  872. * [| attr1_t(2) attr1_val(2) |]? RECURSE attr
  873. * [| attr2_t(2) attr2_val(2) |]? TIMEOUT attr
  874. * [| attr3_t(2) attr3_val(2) |]? ORDERING attr
  875. */
  876. static inline int encode_proxy_attr(xmlNodePtr node, char *node_ptr,
  877. char *buf_end)
  878. {
  879. xmlAttrPtr attr;
  880. char *p, *p_orig;
  881. unsigned char *nr_attr;
  882. unsigned int nr;
  883. str val;
  884. nr_attr = &(NR_OF_ATTR(node_ptr));
  885. *nr_attr = 0;
  886. p = p_orig = ATTR_PTR(node_ptr);
  887. FOR_ALL_ATTR(node,attr) {
  888. (*nr_attr)++;
  889. /* get the value of the attribute */
  890. get_attr_val( attr->name , val, error);
  891. switch(attr->name[0]) {
  892. case 'R': case 'r':
  893. set_attr_type(p, RECURSE_ATTR, buf_end, error);
  894. if (val.s[0]=='y' || val.s[0]=='Y')
  895. append_short_attr(p, YES_VAL, buf_end, error);
  896. else if (val.s[0]=='n' || val.s[0]=='N')
  897. append_short_attr(p, NO_VAL, buf_end, error);
  898. else {
  899. LOG(L_ERR,"ERROR:cpl_c:encode_proxy_attr: unknown value "
  900. "<%s> for attribute RECURSE\n",val.s);
  901. goto error;
  902. }
  903. break;
  904. case 'T': case 't':
  905. set_attr_type(p, TIMEOUT_ATTR, buf_end, error);
  906. if (str2int(&val,&nr)==-1) {
  907. LOG(L_ERR,"ERROR:cpl_c:encode_proxy_attr: bad value <%.*s>"
  908. " for attribute TIMEOUT\n",val.len,val.s);
  909. goto error;
  910. }
  911. append_short_attr(p, (unsigned short)nr, buf_end, error);
  912. break;
  913. case 'O': case 'o':
  914. set_attr_type(p, ORDERING_ATTR, buf_end, error);
  915. switch (val.s[0]) {
  916. case 'p': case'P':
  917. append_short_attr(p, PARALLEL_VAL, buf_end, error);
  918. break;
  919. case 'S': case 's':
  920. append_short_attr(p, SEQUENTIAL_VAL, buf_end, error);
  921. break;
  922. case 'F': case 'f':
  923. append_short_attr(p, FIRSTONLY_VAL, buf_end, error);
  924. break;
  925. default:
  926. LOG(L_ERR,"ERROR:cpl_c:encode_proxy_attr: unknown "
  927. "value <%s> for attribute ORDERING\n",val.s);
  928. goto error;
  929. }
  930. break;
  931. default:
  932. LOG(L_ERR,"ERROR:cpl_c:encode_proxy_attr: unknown attribute "
  933. "<%s>\n",attr->name);
  934. goto error;
  935. }
  936. }
  937. return p-p_orig;
  938. error:
  939. return -1;
  940. }
  941. /* Attr. encoding for REJECT node:
  942. * | attr1_t(2) attr1_val(2) | STATUS attr
  943. * [| attr2_t(2) attr2_len(2) attr2_val(2*x)|]? REASON attr (NT)
  944. */
  945. static inline int encode_reject_attr(xmlNodePtr node, char *node_ptr, char *buf_end)
  946. {
  947. xmlAttrPtr attr;
  948. char *p, *p_orig;
  949. unsigned char *nr_attr;
  950. unsigned int nr;
  951. str val;
  952. nr_attr = &(NR_OF_ATTR(node_ptr));
  953. *nr_attr = 0;
  954. p = p_orig = ATTR_PTR(node_ptr);
  955. FOR_ALL_ATTR(node,attr) {
  956. (*nr_attr)++;
  957. /* get the value of the attribute */
  958. get_attr_val( attr->name , val, error);
  959. switch(attr->name[0]) {
  960. case 'R': case 'r':
  961. set_attr_type(p, REASON_ATTR, buf_end, error);
  962. val.len++; /* grab also the /0 */
  963. append_str_attr(p, val, buf_end, error);
  964. break;
  965. case 'S': case 's':
  966. set_attr_type(p, STATUS_ATTR, buf_end, error);
  967. if (str2int(&val,&nr)==-1) {
  968. /*it was a non numeric value */
  969. if (val.len==BUSY_STR_LEN &&
  970. !strncasecmp(val.s,BUSY_STR,val.len)) {
  971. append_short_attr(p, BUSY_VAL, buf_end, error);
  972. } else if (val.len==NOTFOUND_STR_LEN &&
  973. !strncasecmp(val.s,NOTFOUND_STR,val.len)) {
  974. append_short_attr(p, NOTFOUND_VAL, buf_end, error);
  975. } else if (val.len==ERROR_STR_LEN &&
  976. !strncasecmp(val.s,ERROR_STR,val.len)) {
  977. append_short_attr(p, ERROR_VAL, buf_end, error);
  978. } else if (val.len==REJECT_STR_LEN &&
  979. !strncasecmp(val.s,REJECT_STR,val.len)) {
  980. append_short_attr(p, REJECT_VAL, buf_end, error);
  981. } else {
  982. LOG(L_ERR,"ERROR:cpl_c:encode_priority_attr: bad "
  983. "val. <%s> for STATUS\n",val.s);
  984. goto error;
  985. }
  986. } else if (nr<400 || nr>700) {
  987. LOG(L_ERR,"ERROR:cpl_c:encode_priority_attr: bad "
  988. "code <%d> for STATUS\n",nr);
  989. goto error;
  990. } else {
  991. append_short_attr(p, nr, buf_end, error);
  992. }
  993. break;
  994. default:
  995. LOG(L_ERR,"ERROR:cpl_c:encode_priority_attr: unknown attribute "
  996. "<%s>\n",attr->name);
  997. goto error;
  998. }
  999. }
  1000. return p-p_orig;
  1001. error:
  1002. return -1;
  1003. }
  1004. /* Attr. encoding for REDIRECT node:
  1005. * | attr1_t(2) attr1_val(2) | STATUS attr
  1006. * [| attr2_t(2) attr2_len(2) attr2_val(2*x)|]? REASON attr (NT)
  1007. */
  1008. static inline int encode_redirect_attr(xmlNodePtr node, char *node_ptr, char *buf_end)
  1009. {
  1010. xmlAttrPtr attr;
  1011. char *p, *p_orig;
  1012. unsigned char *nr_attr;
  1013. str val;
  1014. nr_attr = &(NR_OF_ATTR(node_ptr));
  1015. *nr_attr = 0;
  1016. p = p_orig = ATTR_PTR(node_ptr);
  1017. FOR_ALL_ATTR(node,attr) {
  1018. (*nr_attr)++;
  1019. if (attr->name[0]=='p' || attr->name[0]=='P') {
  1020. set_attr_type(p, PERMANENT_ATTR, buf_end, error);
  1021. /* get the value */
  1022. get_attr_val( attr->name , val, error);
  1023. if (val.s[0]=='y' || val.s[0]=='Y')
  1024. append_short_attr( p, YES_VAL, buf_end, error);
  1025. else if (val.s[0]=='n' || val.s[0]=='N')
  1026. append_short_attr( p, NO_VAL, buf_end, error);
  1027. else {
  1028. LOG(L_ERR,"ERROR:cpl_c:encode_redirect_attr: bad "
  1029. "val. <%s> for PERMANENT\n",val.s);
  1030. goto error;
  1031. }
  1032. } else {
  1033. LOG(L_ERR,"ERROR:cpl_c:encode_redirect_attr: unknown attribute "
  1034. "<%s>\n",attr->name);
  1035. goto error;
  1036. }
  1037. }
  1038. return p-p_orig;
  1039. error:
  1040. return -1;
  1041. }
  1042. /* Attr. encoding for LOG node:
  1043. * [| attr1_t(2) attr1_len(2) attr1_val(2*x) |]? NAME attr (NT)
  1044. * [| attr2_t(2) attr2_len(2) attr2_val(2*x) |]? COMMENT attr (NT)
  1045. */
  1046. static inline int encode_log_attr(xmlNodePtr node, char *node_ptr, char *buf_end)
  1047. {
  1048. xmlAttrPtr attr;
  1049. char *p, *p_orig;
  1050. unsigned char *nr_attr;
  1051. str val;
  1052. nr_attr = &(NR_OF_ATTR(node_ptr));
  1053. *nr_attr = 0;
  1054. p = p_orig = ATTR_PTR(node_ptr);
  1055. FOR_ALL_ATTR(node,attr) {
  1056. (*nr_attr)++;
  1057. /* get the value of the attribute */
  1058. get_attr_val( attr->name , val, error);
  1059. switch (attr->name[0] ) {
  1060. case 'n': case 'N':
  1061. if (val.len>MAX_NAME_SIZE) val.len=MAX_NAME_SIZE;
  1062. set_attr_type(p, NAME_ATTR, buf_end, error);
  1063. break;
  1064. case 'c': case 'C':
  1065. if (val.len>MAX_COMMENT_SIZE) val.len=MAX_COMMENT_SIZE;
  1066. set_attr_type(p, COMMENT_ATTR, buf_end, error);
  1067. break;
  1068. default:
  1069. LOG(L_ERR,"ERROR:cpl_c:encode_log_attr: unknown attribute "
  1070. "<%s>\n",attr->name);
  1071. goto error;
  1072. }
  1073. /* be sure there is a \0 at the end of string */
  1074. val.s[val.len++]=0;
  1075. append_str_attr(p,val, buf_end, error);
  1076. }
  1077. return p-p_orig;
  1078. error:
  1079. return -1;
  1080. }
  1081. /* Attr. encoding for MAIL node:
  1082. * | attr1_t(2) attr1_len(2) attr1_val(2*x) | TO_ATTR attr (NNT)
  1083. * [| attr2_t(2) attr2_len(2) attr2_val(2*x) |]? SUBJECT_ATTR attr (NNT)
  1084. * [| attr3_t(2) attr3_len(2) attr3_val(2*x) |]? BODY_ATTR attr (NNT)
  1085. */
  1086. static inline int encode_mail_attr(xmlNodePtr node, char *node_ptr, char *buf_end)
  1087. {
  1088. xmlAttrPtr attr;
  1089. char *p, *p_orig;
  1090. unsigned char *nr_attr;
  1091. nr_attr = &(NR_OF_ATTR(node_ptr));
  1092. *nr_attr = 0;
  1093. p = p_orig = ATTR_PTR(node_ptr);
  1094. FOR_ALL_ATTR(node,attr) {
  1095. /* there is only one attribute -> URL */
  1096. if (attr->name[0]!='u' && attr->name[0]!='U') {
  1097. LOG(L_ERR,"ERROR:cpl_c:encode_node_attr: unknown attribute "
  1098. "<%s>\n",attr->name);
  1099. goto error;
  1100. }
  1101. p = decode_mail_url( p, buf_end,
  1102. (char*)xmlGetProp(node,attr->name), nr_attr);
  1103. if (p==0)
  1104. goto error;
  1105. }
  1106. return p-p_orig;
  1107. error:
  1108. return -1;
  1109. }
  1110. /* Attr. encoding for SUBACTION node:
  1111. */
  1112. static inline int encode_subaction_attr(xmlNodePtr node, char *node_ptr,
  1113. char *buf_end)
  1114. {
  1115. xmlAttrPtr attr;
  1116. str val;
  1117. FOR_ALL_ATTR(node,attr) {
  1118. /* there is only one attribute -> ID */
  1119. if ((attr->name[0]|0x20)=='i' && ((attr->name[1]|0x20)=='d') &&
  1120. attr->name[2]==0 ) {
  1121. /* get the value of the attribute */
  1122. get_attr_val( attr->name , val, error);
  1123. if ((list = append_to_list(list, node_ptr,val.s))==0) {
  1124. LOG(L_ERR,"ERROR:cpl_c:encode_subaction_attr: failed to add "
  1125. "subaction into list -> pkg_malloc failed?\n");
  1126. goto error;
  1127. }
  1128. } else {
  1129. LOG(L_ERR,"ERROR:cpl_c:encode_subaction_attr: unknown attribute "
  1130. "<%s>\n",attr->name);
  1131. goto error;
  1132. }
  1133. }
  1134. return 0;
  1135. error:
  1136. return -1;
  1137. }
  1138. /* Attr. encoding for SUB node:
  1139. * | attr1_t(2) attr1_val(2) | REF_ATTR attr
  1140. */
  1141. static inline int encode_sub_attr(xmlNodePtr node, char *node_ptr, char *buf_end)
  1142. {
  1143. xmlAttrPtr attr;
  1144. char *p, *p_orig;
  1145. unsigned char *nr_attr;
  1146. char *sub_ptr;
  1147. str val;
  1148. nr_attr = &(NR_OF_ATTR(node_ptr));
  1149. *nr_attr = 0;
  1150. p = p_orig = ATTR_PTR(node_ptr);
  1151. FOR_ALL_ATTR(node,attr) {
  1152. (*nr_attr)++;
  1153. /* there is only one attribute -> REF */
  1154. if ( strcasecmp("ref",(char*)attr->name)!=0 ) {
  1155. LOG(L_ERR,"ERROR:cpl_c:encode_sub_attr: unknown attribute "
  1156. "<%s>\n",attr->name);
  1157. goto error;
  1158. }
  1159. set_attr_type(p, REF_ATTR, buf_end, error);
  1160. /* get the value of the attribute */
  1161. get_attr_val( attr->name , val, error);
  1162. if ( (sub_ptr=search_the_list(list, val.s))==0 ) {
  1163. LOG(L_ERR,"ERROR:cpl_c:encode_sub_attr: unable to find declaration "
  1164. "of subaction <%s>\n",val.s);
  1165. goto error;
  1166. }
  1167. append_short_attr(p,(unsigned short)(node_ptr-sub_ptr),buf_end,error);
  1168. }
  1169. return p-p_orig;
  1170. error:
  1171. return -1;
  1172. }
  1173. /* Returns : -1 - error
  1174. * >0 - subtree size of the given node
  1175. */
  1176. int encode_node( xmlNodePtr node, char *p, char *p_end)
  1177. {
  1178. xmlNodePtr kid;
  1179. unsigned short sub_tree_size;
  1180. int attr_size;
  1181. int kid_size;
  1182. int foo;
  1183. /* counting the kids */
  1184. for(kid=node->children,foo=0;kid;kid=kid->next)
  1185. if (kid->type==XML_ELEMENT_NODE) foo++;
  1186. check_overflow(p,GET_NODE_SIZE(foo),p_end,error);
  1187. NR_OF_KIDS(p) = foo;
  1188. /* size of the encoded attributes */
  1189. attr_size = 0;
  1190. /* init the number of attributes */
  1191. NR_OF_ATTR(p) = 0;
  1192. /* encode node name */
  1193. switch (node->name[0]) {
  1194. case 'a':case 'A':
  1195. switch (node->name[7]) {
  1196. case 0:
  1197. NODE_TYPE(p) = ADDRESS_NODE;
  1198. attr_size = encode_address_attr( node, p, p_end);
  1199. break;
  1200. case '-':
  1201. NODE_TYPE(p) = ADDRESS_SWITCH_NODE;
  1202. attr_size = encode_address_switch_attr( node, p, p_end);
  1203. break;
  1204. default:
  1205. NODE_TYPE(p) = ANCILLARY_NODE;
  1206. break;
  1207. }
  1208. break;
  1209. case 'B':case 'b':
  1210. NODE_TYPE(p) = BUSY_NODE;
  1211. break;
  1212. case 'c':case 'C':
  1213. NODE_TYPE(p) = CPL_NODE;
  1214. break;
  1215. case 'd':case 'D':
  1216. NODE_TYPE(p) = DEFAULT_NODE;
  1217. break;
  1218. case 'f':case 'F':
  1219. NODE_TYPE(p) = FAILURE_NODE;
  1220. break;
  1221. case 'i':case 'I':
  1222. NODE_TYPE(p) = INCOMING_NODE;
  1223. break;
  1224. case 'l':case 'L':
  1225. switch (node->name[2]) {
  1226. case 'g':case 'G':
  1227. NODE_TYPE(p) = LOG_NODE;
  1228. attr_size = encode_log_attr( node, p, p_end);
  1229. break;
  1230. case 'o':case 'O':
  1231. NODE_TYPE(p) = LOOKUP_NODE;
  1232. attr_size = encode_lookup_attr( node, p, p_end);
  1233. break;
  1234. case 'c':case 'C':
  1235. NODE_TYPE(p) = LOCATION_NODE;
  1236. attr_size = encode_location_attr( node, p, p_end);
  1237. break;
  1238. default:
  1239. if (node->name[8]) {
  1240. NODE_TYPE(p) = LANGUAGE_SWITCH_NODE;
  1241. } else {
  1242. NODE_TYPE(p) = LANGUAGE_NODE;
  1243. attr_size = encode_lang_attr( node, p, p_end);
  1244. }
  1245. break;
  1246. }
  1247. break;
  1248. case 'm':case 'M':
  1249. NODE_TYPE(p) = MAIL_NODE;
  1250. attr_size = encode_mail_attr( node, p, p_end);
  1251. break;
  1252. case 'n':case 'N':
  1253. switch (node->name[3]) {
  1254. case 'F':case 'f':
  1255. NODE_TYPE(p) = NOTFOUND_NODE;
  1256. break;
  1257. case 'N':case 'n':
  1258. NODE_TYPE(p) = NOANSWER_NODE;
  1259. break;
  1260. default:
  1261. NODE_TYPE(p) = NOT_PRESENT_NODE;
  1262. break;
  1263. }
  1264. break;
  1265. case 'o':case 'O':
  1266. if (node->name[1]=='t' || node->name[1]=='T') {
  1267. NODE_TYPE(p) = OTHERWISE_NODE;
  1268. } else {
  1269. NODE_TYPE(p) = OUTGOING_NODE;
  1270. }
  1271. break;
  1272. case 'p':case 'P':
  1273. if (node->name[2]=='o' || node->name[2]=='O') {
  1274. NODE_TYPE(p) = PROXY_NODE;
  1275. attr_size = encode_proxy_attr( node, p, p_end);
  1276. } else if (node->name[8]) {
  1277. NODE_TYPE(p) = PRIORITY_SWITCH_NODE;
  1278. } else {
  1279. NODE_TYPE(p) = PRIORITY_NODE;
  1280. attr_size = encode_priority_attr( node, p, p_end);
  1281. }
  1282. break;
  1283. case 'r':case 'R':
  1284. switch (node->name[2]) {
  1285. case 'j':case 'J':
  1286. NODE_TYPE(p) = REJECT_NODE;
  1287. attr_size = encode_reject_attr( node, p, p_end);
  1288. break;
  1289. case 'm':case 'M':
  1290. NODE_TYPE(p) = REMOVE_LOCATION_NODE;
  1291. attr_size = encode_rmvloc_attr( node, p, p_end);
  1292. break;
  1293. default:
  1294. if (node->name[8]) {
  1295. NODE_TYPE(p) = REDIRECTION_NODE;
  1296. } else {
  1297. NODE_TYPE(p) = REDIRECT_NODE;
  1298. attr_size = encode_redirect_attr( node, p, p_end);
  1299. }
  1300. break;
  1301. }
  1302. break;
  1303. case 's':case 'S':
  1304. switch (node->name[3]) {
  1305. case 0:
  1306. NODE_TYPE(p) = SUB_NODE;
  1307. attr_size = encode_sub_attr( node, p, p_end);
  1308. break;
  1309. case 'c':case 'C':
  1310. NODE_TYPE(p) = SUCCESS_NODE;
  1311. break;
  1312. case 'a':case 'A':
  1313. NODE_TYPE(p) = SUBACTION_NODE;
  1314. attr_size = encode_subaction_attr( node, p, p_end);
  1315. break;
  1316. default:
  1317. if (node->name[6]) {
  1318. NODE_TYPE(p) = STRING_SWITCH_NODE;
  1319. attr_size = encode_string_switch_attr( node, p, p_end);
  1320. } else {
  1321. NODE_TYPE(p) = STRING_NODE;
  1322. attr_size = encode_string_attr( node, p, p_end);
  1323. }
  1324. break;
  1325. }
  1326. break;
  1327. case 't':case 'T':
  1328. if (node->name[4]) {
  1329. NODE_TYPE(p) = TIME_SWITCH_NODE;
  1330. attr_size = encode_time_switch_attr( node, p, p_end);
  1331. } else {
  1332. NODE_TYPE(p) = TIME_NODE;
  1333. attr_size = encode_time_attr( node, p, p_end);
  1334. }
  1335. break;
  1336. default:
  1337. LOG(L_ERR,"ERROR:cpl-c:encode_node: unknown node <%s>\n",
  1338. node->name);
  1339. goto error;
  1340. }
  1341. /* compute the total length of the node (including attributes) */
  1342. if (attr_size<0)
  1343. goto error;
  1344. sub_tree_size = SIMPLE_NODE_SIZE(p) + (unsigned short)attr_size;
  1345. /* encrypt all the kids */
  1346. for(kid = node->children,foo=0;kid;kid=kid->next) {
  1347. if (kid->type!=XML_ELEMENT_NODE) continue;
  1348. SET_KID_OFFSET( p, foo, sub_tree_size);
  1349. kid_size = encode_node( kid, p+sub_tree_size, p_end);
  1350. if (kid_size<=0)
  1351. goto error;
  1352. sub_tree_size += (unsigned short)kid_size;
  1353. foo++;
  1354. }
  1355. return sub_tree_size;
  1356. error:
  1357. return -1;
  1358. }
  1359. #define BAD_XML "CPL script is not a valid XML document"
  1360. #define BAD_XML_LEN (sizeof(BAD_XML)-1)
  1361. #define BAD_CPL "CPL script doesn't respect CPL grammar"
  1362. #define BAD_CPL_LEN (sizeof(BAD_CPL)-1)
  1363. #define NULL_CPL "Empty CPL script"
  1364. #define NULL_CPL_LEN (sizeof(NULL_CPL)-1)
  1365. #define ENC_ERR "Encoding of the CPL script failed"
  1366. #define ENC_ERR_LEN (sizeof(ENC_ERR)-1)
  1367. int encodeCPL( str *xml, str *bin, str *log)
  1368. {
  1369. static char buf[ENCONDING_BUFFER_SIZE];
  1370. xmlDocPtr doc;
  1371. xmlNodePtr cur;
  1372. doc = 0;
  1373. list = 0;
  1374. /* reset all the logs (if any) to catch some possible err/warn/notice
  1375. * from the parser/validater/encoder */
  1376. reset_logs();
  1377. /* parse the xml */
  1378. doc = xmlParseDoc( (unsigned char*)xml->s );
  1379. if (!doc) {
  1380. append_log( 1, MSG_ERR BAD_XML LF, MSG_ERR_LEN+BAD_XML_LEN+LF_LEN);
  1381. LOG(L_ERR,"ERROR:cpl:encodeCPL:" BAD_XML "\n");
  1382. goto error;
  1383. }
  1384. /* check the xml against dtd */
  1385. if (xmlValidateDtd(&cvp, doc, dtd)!=1) {
  1386. append_log( 1, MSG_ERR BAD_CPL LF, MSG_ERR_LEN+BAD_CPL_LEN+LF_LEN);
  1387. LOG(L_ERR,"ERROR:cpl-c:encodeCPL: " BAD_CPL "\n");
  1388. goto error;
  1389. }
  1390. cur = xmlDocGetRootElement(doc);
  1391. if (!cur) {
  1392. append_log( 1, MSG_ERR NULL_CPL LF, MSG_ERR_LEN+NULL_CPL_LEN+LF_LEN);
  1393. LOG(L_ERR,"ERROR:cpl-c:encodeCPL: " NULL_CPL "\n");
  1394. goto error;
  1395. }
  1396. bin->len = encode_node( cur, buf, buf+ENCONDING_BUFFER_SIZE);
  1397. if (bin->len<0) {
  1398. append_log( 1, MSG_ERR ENC_ERR LF, MSG_ERR_LEN+ENC_ERR_LEN+LF_LEN);
  1399. LOG(L_ERR,"ERROR:cpl-c:encodeCPL: " ENC_ERR "\n");
  1400. goto error;
  1401. }
  1402. xmlFreeDoc(doc);
  1403. if (list) delete_list(list);
  1404. /* compile the log buffer */
  1405. compile_logs( log );
  1406. bin->s = buf;
  1407. return 1;
  1408. error:
  1409. if (doc) xmlFreeDoc(doc);
  1410. if (list) delete_list(list);
  1411. /* compile the log buffer */
  1412. compile_logs( log );
  1413. return 0;
  1414. }
  1415. #if 0
  1416. static void err_print(void *ctx, const char *msg, ...)
  1417. {
  1418. va_list ap;
  1419. //char *t;
  1420. va_start( ap, msg);
  1421. LOG(L_ERR,"->>>> my errr <%s>\n",msg);
  1422. //while ( (t=va_arg(ap, char *))!=0) {
  1423. // LOG(L_ERR," -> <%s>\n",t);
  1424. //}
  1425. vfprintf(stderr,msg,ap);
  1426. //append_log( 2, ERR, ERR_LEN, msg, strlen(msg) );
  1427. va_end(ap);
  1428. }
  1429. #endif
  1430. /* loads and parse the dtd file; a validating context is created */
  1431. int init_CPL_parser( char* DTD_filename )
  1432. {
  1433. dtd = xmlParseDTD( NULL, (unsigned char*)DTD_filename);
  1434. if (!dtd) {
  1435. LOG(L_ERR,"ERROR:cpl-c:init_CPL_parser: DTD not parsed successfully\n");
  1436. return -1;
  1437. }
  1438. cvp.userData = (void *) stderr;
  1439. cvp.error = (xmlValidityErrorFunc) /*err_print*/ fprintf;
  1440. cvp.warning = (xmlValidityWarningFunc) /*err_print*/ fprintf;
  1441. return 1;
  1442. }