cpl_switches.h 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111
  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. * History:
  28. * -------
  29. * 2003-06-27: file created (bogdan)
  30. */
  31. #include "cpl_time.h"
  32. #include "../../parser/parse_from.h"
  33. #include "../../parser/parse_uri.h"
  34. /* UPDATED + CHECKED
  35. */
  36. static inline char *run_address_switch( struct cpl_interpreter *intr )
  37. {
  38. static str def_port_str = STR_STATIC_INIT("5060");
  39. unsigned short field, subfield;
  40. char *p;
  41. char *kid;
  42. unsigned short attr_name;
  43. unsigned short n;
  44. int i;
  45. int k;
  46. str cpl_val;
  47. str *msg_val;
  48. str *uri;
  49. struct sip_uri parsed_uri;
  50. field = subfield = UNDEF_CHAR;
  51. msg_val = 0;
  52. p=ATTR_PTR(intr->ip);
  53. /* parse the attributes */
  54. for( i=NR_OF_ATTR(intr->ip) ; i>0 ; i-- ) {
  55. get_basic_attr( p, attr_name, n, intr, script_error);
  56. switch (attr_name) {
  57. case FIELD_ATTR:
  58. if (field!=UNDEF_CHAR) {
  59. LOG(L_ERR,"ERROR:cpl-c:run_address_switch: multiple FIELD "
  60. "attrs found\n");
  61. goto script_error;
  62. }
  63. field = n;
  64. break;
  65. case SUBFIELD_ATTR:
  66. if (subfield!=UNDEF_CHAR) {
  67. LOG(L_ERR,"ERROR:cpl-c:run_address_switch: multiple SUBFIELD"
  68. " attrs found\n");
  69. goto script_error;
  70. }
  71. subfield = n; break;
  72. default:
  73. LOG(L_ERR,"ERROR:cpl_c:run_address_switch: unknown attribute "
  74. "(%d) in ADDRESS_SWITCH node\n",*p);
  75. goto script_error;
  76. }
  77. }
  78. if (field==UNDEF_CHAR) {
  79. LOG(L_ERR,"ERROR:cpl_c:run_address_switch: mandatory param FIELD "
  80. "no found\n");
  81. goto script_error;
  82. }
  83. /* test the condition from all the sub-nodes */
  84. for( i=0 ; i<NR_OF_KIDS(intr->ip) ; i++ ) {
  85. kid = intr->ip + KID_OFFSET(intr->ip,i);
  86. check_overflow_by_ptr( kid+SIMPLE_NODE_SIZE(kid), intr, script_error);
  87. switch ( NODE_TYPE(kid) ) {
  88. case NOT_PRESENT_NODE:
  89. DBG("DEBUG:run_address_switch: NOT_PRESENT node found ->"
  90. "skipping (useless in this case)\n");
  91. break;
  92. case OTHERWISE_NODE :
  93. if (i!=NR_OF_KIDS(intr->ip)-1) {
  94. LOG(L_ERR,"ERROR:run_address_switch: OTHERWISE node "
  95. "not found as the last sub-node!\n");
  96. goto script_error;
  97. }
  98. DBG("DEBUG:run_address_switch: matching on OTHERWISE node\n");
  99. return get_first_child(kid);
  100. case ADDRESS_NODE :
  101. /* check the number of attributes */
  102. if (NR_OF_ATTR(kid)!=1) {
  103. LOG(L_ERR,"ERROR:run_address_switch: incorrect nr of attrs "
  104. "(%d) in ADDRESS node\n",NR_OF_ATTR(kid));
  105. goto script_error;
  106. }
  107. /* get the attribute name */
  108. p = ATTR_PTR(kid);
  109. get_basic_attr( p, attr_name, cpl_val.len, intr, script_error);
  110. if (attr_name!=IS_ATTR && attr_name!=CONTAINS_ATTR &&
  111. attr_name!=SUBDOMAIN_OF_ATTR) {
  112. LOG(L_ERR,"ERROR:run_address_switch: unknown attribute "
  113. "(%d) in ADDRESS node\n",attr_name);
  114. goto script_error;
  115. }
  116. /* get attribute value */
  117. get_str_attr( p, cpl_val.s, cpl_val.len, intr, script_error,1);
  118. DBG("DEBUG:run_address_switch: testing ADDRESS branch "
  119. " attr_name=%d attr_val=[%.*s](%d)..\n",
  120. attr_name,cpl_val.len,cpl_val.s,cpl_val.len);
  121. /* extract the needed value from the message */
  122. if (!msg_val) {
  123. switch (field) {
  124. case ORIGIN_VAL: /* FROM */
  125. if (!intr->from) {
  126. /* get the header */
  127. if (parse_from_header( intr->msg )==-1)
  128. goto runtime_error;
  129. intr->from = &(get_from(intr->msg)->uri);
  130. }
  131. uri = intr->from;
  132. break;
  133. case DESTINATION_VAL: /* RURI */
  134. if (!intr->ruri)
  135. intr->ruri = GET_RURI( intr->msg );
  136. uri = intr->ruri;
  137. break;
  138. case ORIGINAL_DESTINATION_VAL: /* TO */
  139. if (!intr->to) {
  140. /* get and parse the header */
  141. if (!intr->msg->to &&
  142. (parse_headers(intr->msg,HDR_TO_F,0)==-1 ||
  143. !intr->msg->to)) {
  144. LOG(L_ERR,"ERROR:run_address_switch: bad "
  145. "msg or missing TO header\n");
  146. goto runtime_error;
  147. }
  148. intr->to = &(get_to(intr->msg)->uri);
  149. }
  150. uri = intr->to;
  151. break;
  152. default:
  153. LOG(L_ERR,"ERROR:run_address_switch: unknown "
  154. "attribute (%d) in ADDRESS node\n",field);
  155. goto script_error;
  156. }
  157. DBG("DEBUG:run_address_switch: extracted uri is <%.*s>\n",
  158. uri->len, uri->s);
  159. switch (subfield) {
  160. case UNDEF_CHAR:
  161. msg_val = uri;
  162. break;
  163. case USER_VAL:
  164. if (parse_uri( uri->s, uri->len, &parsed_uri)<0)
  165. goto runtime_error;
  166. msg_val = &(parsed_uri.user);
  167. break;
  168. case HOST_VAL:
  169. if (parse_uri( uri->s, uri->len, &parsed_uri)<0)
  170. goto runtime_error;
  171. msg_val = &(parsed_uri.host);
  172. break;
  173. case PORT_VAL:
  174. if (parse_uri( uri->s, uri->len, &parsed_uri)<0)
  175. goto runtime_error;
  176. if (parsed_uri.port.len!=0)
  177. msg_val = &(parsed_uri.port);
  178. else
  179. msg_val = &def_port_str;
  180. break;
  181. case TEL_VAL:
  182. if (parse_uri( uri->s, uri->len, &parsed_uri)<0)
  183. goto runtime_error;
  184. if (parsed_uri.user_param_val.len==5 &&
  185. memcmp(parsed_uri.user_param_val.s,"phone",5)==0)
  186. msg_val = &(parsed_uri.user);
  187. break;
  188. case ADDRESS_TYPE_VAL:
  189. case DISPLAY_VAL:
  190. default:
  191. LOG(L_ERR,"ERROR:run_address_switch: unsupported "
  192. "value attribute (%d) in ADDRESS node\n",
  193. subfield);
  194. goto script_error;
  195. }
  196. DBG("DEBUG:run_address_switch: extracted val. is <%.*s>\n",
  197. (msg_val==0)?0:msg_val->len, (msg_val==0)?0:msg_val->s);
  198. }
  199. /* does the value from script match the one from message? */
  200. switch (attr_name) {
  201. case IS_ATTR:
  202. if ( (!msg_val && !cpl_val.s) ||
  203. (msg_val && msg_val->len==cpl_val.len &&
  204. strncasecmp(msg_val->s,cpl_val.s,cpl_val.len)==0)) {
  205. DBG("DEBUG:run_address_switch: matching on "
  206. "ADDRESS node (IS)\n");
  207. return get_first_child(kid);
  208. }
  209. break;
  210. case CONTAINS_ATTR:
  211. if (subfield!=DISPLAY_VAL) {
  212. LOG(L_WARN,"WARNING:run_address_switch: operator "
  213. "CONTAINS applies only to DISPLAY -> ignored\n");
  214. } else {
  215. if ( msg_val && cpl_val.len<=msg_val->len &&
  216. strcasestr_str(msg_val, &cpl_val)!=0 ) {
  217. DBG("DEBUG:run_address_switch: matching on "
  218. "ADDRESS node (CONTAINS)\n");
  219. return get_first_child(kid);
  220. }
  221. }
  222. break;
  223. case SUBDOMAIN_OF_ATTR:
  224. switch (subfield) {
  225. case HOST_VAL:
  226. k = msg_val->len - cpl_val.len;
  227. if (k>=0 && (k==0 || msg_val->s[k-1]=='.') &&
  228. !strncasecmp(cpl_val.s,msg_val->s+k,cpl_val.len)
  229. ) {
  230. DBG("DEBUG:run_address_switch: matching on "
  231. "ADDRESS node (SUBDOMAIN_OF)\n");
  232. return get_first_child(kid);
  233. }
  234. break;
  235. case TEL_VAL:
  236. if (msg_val==0) break;
  237. if (msg_val->len>=cpl_val.len && !strncasecmp(
  238. cpl_val.s,msg_val->s,cpl_val.len)) {
  239. DBG("DEBUG:run_address_switch: matching on "
  240. "ADDRESS node (SUBDOMAIN_OF)\n");
  241. return get_first_child(kid);
  242. }
  243. break;
  244. default:
  245. LOG(L_WARN,"WARNING:run_address_switch: operator"
  246. " SUBDOMAIN_OF applies only to HOST or TEL "
  247. "-> ignored\n");
  248. }
  249. break;
  250. }
  251. break;
  252. default:
  253. LOG(L_ERR,"ERROR:run_address_switch: unknown output node type "
  254. "(%d) for ADDRESS_SWITCH node\n",NODE_TYPE(kid));
  255. goto script_error;
  256. }
  257. }
  258. /* none of the branches of ADDRESS_SWITCH matched -> go for default */
  259. return DEFAULT_ACTION;
  260. runtime_error:
  261. return CPL_RUNTIME_ERROR;
  262. script_error:
  263. return CPL_SCRIPT_ERROR;
  264. }
  265. /* UPDATED + CHECKED
  266. */
  267. static inline char *run_string_switch( struct cpl_interpreter *intr )
  268. {
  269. unsigned short field;
  270. char *p;
  271. char *kid;
  272. char *not_present_node;
  273. unsigned short attr_name;
  274. int i;
  275. str cpl_val;
  276. str msg_val;
  277. not_present_node = 0;
  278. msg_val.s = 0;
  279. msg_val.len = 0;
  280. /* parse the attribute */
  281. if (NR_OF_ATTR(intr->ip)!=1) {
  282. LOG(L_ERR,"ERROR:cpl_c:run_string_switch: node should have 1 attr, not"
  283. " (%d)\n",NR_OF_ATTR(intr->ip));
  284. goto script_error;
  285. }
  286. p=ATTR_PTR(intr->ip);
  287. get_basic_attr( p, attr_name, field, intr, script_error);
  288. if (attr_name!=FIELD_ATTR) {
  289. LOG(L_ERR,"ERROR:cpl_c:run_string_switch: unknown param type (%d)"
  290. " for STRING_SWITCH node\n",*p);
  291. goto script_error;
  292. }
  293. for( i=0 ; i<NR_OF_KIDS(intr->ip) ; i++ ) {
  294. kid = intr->ip + KID_OFFSET(intr->ip,i);
  295. check_overflow_by_ptr( kid+SIMPLE_NODE_SIZE(kid), intr, script_error);
  296. switch ( NODE_TYPE(kid) ) {
  297. case NOT_PRESENT_NODE:
  298. if (not_present_node) {
  299. LOG(L_ERR,"ERROR:run_string_switch: NOT_PRESENT node "
  300. "found twice!\n");
  301. goto script_error;
  302. }
  303. not_present_node = kid;
  304. break;
  305. case OTHERWISE_NODE :
  306. if (i!=NR_OF_KIDS(intr->ip)-1) {
  307. LOG(L_ERR,"ERROR:run_string_switch: OTHERWISE node "
  308. "not found as the last sub-node!\n");
  309. goto script_error;
  310. }
  311. DBG("DEBUG:run_string_switch: matching on OTHERWISE node\n");
  312. return get_first_child(kid);
  313. case STRING_NODE :
  314. /* check the number of attributes */
  315. if (NR_OF_ATTR(kid)!=1) {
  316. LOG(L_ERR,"ERROR:run_string_switch: incorrect nr of attrs "
  317. "(%d) in STRING node (expected 1)\n",NR_OF_ATTR(kid));
  318. goto script_error;
  319. }
  320. /* get the attribute name */
  321. p = ATTR_PTR(kid);
  322. get_basic_attr( p, attr_name, cpl_val.len, intr, script_error);
  323. if (attr_name!=IS_ATTR && attr_name!=CONTAINS_ATTR ) {
  324. LOG(L_ERR,"ERROR:run_string_switch: unknown attribute "
  325. "(%d) in STRING node\n",attr_name);
  326. goto script_error;
  327. }
  328. /* get attribute value */
  329. get_str_attr( p, cpl_val.s, cpl_val.len, intr, script_error,1);
  330. DBG("DEBUG:run_string_switch: testing STRING branch "
  331. "attr_name=%d attr_val=[%.*s](%d)..\n",
  332. attr_name,cpl_val.len,cpl_val.s,cpl_val.len);
  333. if (!msg_val.s) {
  334. switch (field) {
  335. case SUBJECT_VAL: /* SUBJECT */
  336. if (intr->subject==STR_NOT_FOUND)
  337. goto not_present;
  338. if (!intr->subject) {
  339. /* get the subject header */
  340. if (!intr->msg->subject) {
  341. if (parse_headers(intr->msg,
  342. HDR_SUBJECT_F,0)==-1) {
  343. LOG(L_ERR,"ERROR:run_string_switch: "
  344. "bad SUBJECT header\n");
  345. goto runtime_error;
  346. } else if (!intr->msg->subject) {
  347. /* hdr not present */
  348. intr->subject = STR_NOT_FOUND;
  349. goto not_present;
  350. }
  351. }
  352. intr->subject =
  353. &(intr->msg->subject->body);
  354. }
  355. trim_len( msg_val.len,msg_val.s,
  356. *(intr->subject));
  357. break;
  358. case ORGANIZATION_VAL: /* ORGANIZATION */
  359. if (intr->organization==STR_NOT_FOUND)
  360. goto not_present;
  361. if (!intr->organization) {
  362. /* get the organization header */
  363. if (!intr->msg->organization) {
  364. if (parse_headers(intr->msg,
  365. HDR_ORGANIZATION_F,0)==-1) {
  366. LOG(L_ERR,"ERROR:run_string_switch: "
  367. "bad ORGANIZATION hdr\n");
  368. goto runtime_error;
  369. } else if (!intr->msg->organization) {
  370. /* hdr not present */
  371. intr->organization = STR_NOT_FOUND;
  372. goto not_present;
  373. }
  374. }
  375. intr->organization =
  376. &(intr->msg->organization->body);
  377. }
  378. trim_len( msg_val.len,msg_val.s,
  379. *(intr->organization));
  380. break;
  381. case USER_AGENT_VAL: /* User Agent */
  382. if (intr->user_agent==STR_NOT_FOUND)
  383. goto not_present;
  384. if (!intr->user_agent) {
  385. /* get the header */
  386. if (!intr->msg->user_agent) {
  387. if (parse_headers(intr->msg,
  388. HDR_USERAGENT_F,0)==-1) {
  389. LOG(L_ERR,"ERROR:run_string_switch: "
  390. "bad USERAGENT hdr\n");
  391. goto runtime_error;
  392. } else if (!intr->msg->user_agent) {
  393. /* hdr not present */
  394. intr->user_agent = STR_NOT_FOUND;
  395. goto not_present;
  396. }
  397. }
  398. intr->user_agent =
  399. &(intr->msg->user_agent->body);
  400. }
  401. trim_len( msg_val.len,msg_val.s,
  402. *(intr->user_agent));
  403. break;
  404. default:
  405. LOG(L_ERR,"ERROR:run_string_switch: unknown "
  406. "attribute (%d) in STRING node\n",field);
  407. goto script_error;
  408. }
  409. DBG("DEBUG:run_string_switch: extracted msg string is "
  410. "<%.*s>\n",msg_val.len, msg_val.s);
  411. }
  412. /* does the value from script match the one from message? */
  413. switch (attr_name) {
  414. case IS_ATTR:
  415. if ( (!msg_val.s && !cpl_val.s) ||
  416. (msg_val.len==cpl_val.len &&
  417. strncasecmp(msg_val.s,cpl_val.s,cpl_val.len)==0)) {
  418. DBG("DEBUG:run_string_switch: matching on "
  419. "STRING node (IS)\n");
  420. return get_first_child(kid);
  421. }
  422. break;
  423. case CONTAINS_ATTR:
  424. if (cpl_val.len<=msg_val.len &&
  425. strcasestr_str(&msg_val, &cpl_val)!=0 ) {
  426. DBG("DEBUG:run_string_switch: matching on "
  427. "STRING node (CONTAINS)\n");
  428. return get_first_child(kid);
  429. }
  430. break;
  431. }
  432. break;
  433. default:
  434. LOG(L_ERR,"ERROR:run_string_switch: unknown output node type "
  435. "(%d) for STRING_SWITCH node\n",NODE_TYPE(kid));
  436. goto script_error;
  437. }
  438. }
  439. /* none of the branches of STRING_SWITCH matched -> go for default */
  440. return DEFAULT_ACTION;
  441. not_present:
  442. DBG("DEBUG:run_string_switch: required hdr not present in sip msg\n");
  443. if (not_present_node)
  444. return get_first_child(not_present_node);
  445. /* look for the NOT_PRESENT node */
  446. DBG("DEBUG:run_string_switch: searching for NOT_PRESENT sub-node..\n");
  447. for(; i<NR_OF_KIDS(intr->ip) ; i++ ) {
  448. kid = intr->ip + KID_OFFSET(intr->ip,i);
  449. check_overflow_by_ptr( kid+SIMPLE_NODE_SIZE(kid), intr, script_error);
  450. if (NODE_TYPE(kid)==NOT_PRESENT_NODE)
  451. return get_first_child(kid);
  452. }
  453. return DEFAULT_ACTION;
  454. runtime_error:
  455. return CPL_RUNTIME_ERROR;
  456. script_error:
  457. return CPL_SCRIPT_ERROR;
  458. }
  459. /* UPDATED + CHECKED
  460. */
  461. static inline char *run_priority_switch( struct cpl_interpreter *intr )
  462. {
  463. static str default_val=STR_STATIC_INIT("normal");
  464. unsigned short n;
  465. char *p;
  466. char *kid;
  467. char *not_present_node;
  468. unsigned short attr_name;
  469. unsigned short attr_val;
  470. unsigned short msg_attr_val;
  471. unsigned short msg_prio;
  472. int i;
  473. str cpl_val = STR_NULL;
  474. str msg_val = STR_NULL;
  475. not_present_node = 0;
  476. msg_attr_val = NORMAL_VAL;
  477. for( i=0 ; i<NR_OF_KIDS(intr->ip) ; i++ ) {
  478. kid = intr->ip + KID_OFFSET(intr->ip,i);
  479. check_overflow_by_ptr( kid+SIMPLE_NODE_SIZE(kid), intr, script_error);
  480. switch ( NODE_TYPE(kid) ) {
  481. case NOT_PRESENT_NODE:
  482. if (not_present_node) {
  483. LOG(L_ERR,"ERROR:run_priority_switch: NOT_PRESENT node "
  484. "found twice!\n");
  485. goto script_error;
  486. }
  487. not_present_node = kid;
  488. break;
  489. case OTHERWISE_NODE :
  490. if (i!=NR_OF_KIDS(intr->ip)-1) {
  491. LOG(L_ERR,"ERROR:run_priority_switch: OTHERWISE node "
  492. "not found as the last sub-node!\n");
  493. goto script_error;
  494. }
  495. DBG("DEBUG:run_priority_switch: matching on OTHERWISE node\n");
  496. return get_first_child(kid);
  497. case PRIORITY_NODE :
  498. if (NR_OF_ATTR(kid)!=1)
  499. goto script_error;
  500. /* get the attribute */
  501. p = ATTR_PTR(kid);
  502. get_basic_attr( p, attr_name, attr_val, intr, script_error);
  503. if (attr_name!=LESS_ATTR && attr_name!=GREATER_ATTR &&
  504. attr_name!=EQUAL_ATTR){
  505. LOG(L_ERR,"ERROR:run_priority_switch: unknown attribute "
  506. "(%d) in PRIORITY node\n",attr_name);
  507. goto script_error;
  508. }
  509. /* attribute's encoded value */
  510. if (attr_val!=EMERGENCY_VAL && attr_val!=URGENT_VAL &&
  511. attr_val!=NORMAL_VAL && attr_val!=NON_URGENT_VAL &&
  512. attr_val!=UNKNOWN_PRIO_VAL) {
  513. LOG(L_ERR,"ERROR:run_priority_switch: unknown encoded "
  514. "value (%d) for attribute (*d) in PRIORITY node\n",*p);
  515. goto script_error;
  516. }
  517. if (attr_val==UNKNOWN_PRIO_VAL) {
  518. if (attr_name!=EQUAL_ATTR) {
  519. LOG(L_ERR,"ERROR:cpl_c:run_priority_switch:bad PRIORITY"
  520. " branch: attr=EQUAL doesn't match val=UNKNOWN\n");
  521. goto script_error;
  522. }
  523. /* if the attr is UNKNOWN, its string value is present */
  524. get_basic_attr(p, n,cpl_val.len, intr, script_error);
  525. if (n!=PRIOSTR_ATTR) {
  526. LOG(L_ERR,"ERROR:run_priority_switch: expected PRIOSTR"
  527. "(%d) attr, found (%d)\n",PRIOSTR_ATTR,n);
  528. goto script_error;
  529. }
  530. get_str_attr(p, cpl_val.s, cpl_val.len,intr,script_error,1);
  531. }
  532. DBG("DEBUG:run_priority_switch: testing PRIORITY branch "
  533. "(attr=%d,val=%d) [%.*s](%d)..\n",
  534. attr_name,attr_val,cpl_val.len,cpl_val.s,cpl_val.len);
  535. if (!msg_val.s) {
  536. if (!intr->priority) {
  537. /* get the PRIORITY header from message */
  538. if (!intr->msg->priority) {
  539. if (parse_headers(intr->msg,HDR_PRIORITY_F,0)==-1){
  540. LOG(L_ERR,"ERROR:run_priority_switch: bad "
  541. "sip msg or PRIORITY header !\n");
  542. goto runtime_error;
  543. } else if (!intr->msg->priority) {
  544. LOG(L_NOTICE,"NOTICE:run_priority_switch: "
  545. "missing PRIORITY header -> using "
  546. "default value \"normal\"!\n");
  547. intr->priority = &default_val;
  548. } else {
  549. intr->priority =
  550. &(intr->msg->priority->body);
  551. }
  552. } else {
  553. intr->priority =
  554. &(intr->msg->priority->body);
  555. }
  556. }
  557. trim_len( msg_val.len, msg_val.s, *(intr->priority));
  558. /* encode attribute's value from SIP message */
  559. if ( msg_val.len==EMERGENCY_STR_LEN &&
  560. !strncasecmp(msg_val.s,EMERGENCY_STR,msg_val.len) ) {
  561. msg_attr_val = EMERGENCY_VAL;
  562. } else if ( msg_val.len==URGENT_STR_LEN &&
  563. !strncasecmp(msg_val.s,URGENT_STR,msg_val.len) ) {
  564. msg_attr_val = URGENT_VAL;
  565. } else if ( msg_val.len==NORMAL_STR_LEN &&
  566. !strncasecmp(msg_val.s,NORMAL_STR,msg_val.len) ) {
  567. msg_attr_val = NORMAL_VAL;
  568. } else if ( msg_val.len==NON_URGENT_STR_LEN &&
  569. !strncasecmp(msg_val.s,NON_URGENT_STR,msg_val.len) ) {
  570. msg_attr_val = NON_URGENT_VAL;
  571. } else {
  572. msg_attr_val = UNKNOWN_PRIO_VAL;
  573. }
  574. DBG("DEBUG:run_priority_switch: extracted msg priority is "
  575. "<%.*s> decoded as [%d]\n",
  576. msg_val.len,msg_val.s,msg_attr_val);
  577. }
  578. DBG("DEBUG:run_priority_switch: using msg string <%.*s>\n",
  579. msg_val.len, msg_val.s);
  580. /* attr_val (from cpl) cannot be UNKNOWN - we already
  581. * check it -> check only for msg_attr_val for non-EQUAL op */
  582. if (msg_attr_val==UNKNOWN_PRIO_VAL && attr_name!=EQUAL_ATTR) {
  583. LOG(L_NOTICE,"NOTICE:run_priority_switch: UNKNOWN "
  584. "value found in sip_msg when string a LESS/GREATER "
  585. "cmp -> force the value to default \"normal\"\n");
  586. msg_prio = NORMAL_VAL;
  587. } else {
  588. msg_prio = msg_attr_val;
  589. }
  590. /* does the value from script match the one from message? */
  591. switch (attr_name) {
  592. case LESS_ATTR:
  593. switch (attr_val) {
  594. case EMERGENCY_VAL:
  595. if (msg_prio!=EMERGENCY_VAL) break; /*OK*/
  596. else continue; /* for cycle for all kids */
  597. case URGENT_VAL:
  598. if (msg_prio!=EMERGENCY_VAL &&
  599. msg_prio!=URGENT_VAL) break; /* OK */
  600. else continue; /* for cycle for all kids */
  601. case NORMAL_VAL:
  602. if (msg_prio==NON_URGENT_VAL) break; /*OK*/
  603. else continue; /* for cycle for all kids */
  604. case NON_URGENT_VAL:
  605. continue; /* for cycle for all kids */
  606. }
  607. break;
  608. case GREATER_ATTR:
  609. switch (attr_val) {
  610. case EMERGENCY_VAL:
  611. continue; /* for cycle for all kids */
  612. case URGENT_VAL:
  613. if (msg_prio!=EMERGENCY_VAL) break; /*OK*/
  614. else continue; /* for cycle for all kids */
  615. case NORMAL_VAL:
  616. if (msg_prio!=NON_URGENT_VAL &&
  617. msg_prio!=NORMAL_VAL) break; /*OK*/
  618. else continue; /* for cycle for all kids */
  619. case NON_URGENT_VAL:
  620. if (msg_prio!=NON_URGENT_VAL) break; /*OK*/
  621. else continue; /* for cycle for all kids */
  622. }
  623. break;
  624. case EQUAL_ATTR:
  625. if ( attr_val==msg_prio ) {
  626. if (attr_val==UNKNOWN_PRIO_VAL) {
  627. if ( msg_val.len==cpl_val.len &&
  628. !strncasecmp(msg_val.s,cpl_val.s,msg_val.len)){
  629. break; /* OK */
  630. }
  631. } else {
  632. break; /* OK */
  633. }
  634. }
  635. continue; /* for cycle for all kids */
  636. break;
  637. } /* end switch for attr_name */
  638. DBG("DEBUG:run_priority_switch: matching current "
  639. "PRIORITY node\n");
  640. return get_first_child(kid);
  641. break;
  642. default:
  643. LOG(L_ERR,"ERROR:run_priority_switch: unknown output node type"
  644. " (%d) for PRIORITY_SWITCH node\n",NODE_TYPE(kid));
  645. goto script_error;
  646. } /* end switch for NODE_TYPE */
  647. } /* end for for all kids */
  648. /* none of the branches of PRIORITY_SWITCH matched -> go for default */
  649. return DEFAULT_ACTION;
  650. runtime_error:
  651. return CPL_RUNTIME_ERROR;
  652. script_error:
  653. return CPL_SCRIPT_ERROR;
  654. }
  655. inline static int set_TZ(char *tz_env)
  656. {
  657. DBG("DEBUG:cpl-c:set_TZ: switching TZ as \"%s\"\n",tz_env);
  658. if (putenv( tz_env )==-1) {
  659. LOG(L_ERR,"ERROR:cpl-c:set_TZ: setenv failed -> unable to set TZ "
  660. " \"%s\"\n",tz_env);
  661. return -1;
  662. }
  663. tzset(); /* just to be sure */
  664. return 0;
  665. }
  666. /* UPDATED + CHECKED
  667. */
  668. static inline char *run_time_switch( struct cpl_interpreter *intr )
  669. {
  670. char *p;
  671. char *kid;
  672. char *attr_str;
  673. unsigned short attr_name;
  674. unsigned short attr_len;
  675. unsigned char flags = 0;
  676. int nr_attrs;
  677. int i,j;
  678. str user_tz = STR_NULL;
  679. ac_tm_t att;
  680. tmrec_t trt;
  681. DBG("DEBUG:cpl-c:run_time_switch: checking recv. time stamp <%d>\n",
  682. intr->recv_time);
  683. switch (NR_OF_ATTR(intr->ip)) {
  684. case 1:
  685. p = ATTR_PTR(intr->ip);
  686. get_basic_attr( p, attr_name, user_tz.len, intr, script_error);
  687. if (attr_name!=TZID_ATTR) {
  688. LOG(L_ERR,"ERROR:cpl-c:run_time_switch: bad attribute -> "
  689. " expected=%d, found=%d\n",TZID_ATTR,attr_name);
  690. goto script_error;
  691. }
  692. get_str_attr( p, user_tz.s, user_tz.len, intr, script_error, 1);
  693. case 0:
  694. break;
  695. default:
  696. LOG(L_ERR,"ERROR:cpl-c:run_time_switch: incorrect number of attr ->"
  697. " found=%d expected=(0,1)\n",NR_OF_ATTR(intr->ip));
  698. goto script_error;
  699. }
  700. if (user_tz.s && user_tz.len) {
  701. if (set_TZ(user_tz.s)==-1)
  702. goto runtime_error;
  703. flags |= (1<<7);
  704. }
  705. for( i=0 ; i<NR_OF_KIDS(intr->ip) ; i++ ) {
  706. kid = intr->ip + KID_OFFSET(intr->ip,i);
  707. check_overflow_by_ptr( kid+SIMPLE_NODE_SIZE(kid), intr, script_error);
  708. switch ( NODE_TYPE(kid) ) {
  709. case NOT_PRESENT_NODE:
  710. DBG("DEBUG:cpl-c:run_time_switch: NOT_PRESENT node found ->"
  711. "skipping (useless in this case)\n");
  712. break;
  713. case OTHERWISE_NODE :
  714. if (i!=NR_OF_KIDS(intr->ip)-1) {
  715. LOG(L_ERR,"ERROR:cpl-c:run_time_switch: OTHERWISE node "
  716. "not found as the last sub-node!\n");
  717. goto script_error;
  718. }
  719. DBG("DEBUG:cpl-c:run_time_switch: matching on "
  720. "OTHERWISE node\n");
  721. return get_first_child(kid);
  722. case TIME_NODE :
  723. /* init structures */
  724. memset( &att, 0, sizeof(att));
  725. memset( &trt, 0, sizeof(trt));
  726. if(ac_tm_set_time( &att, intr->recv_time))
  727. goto runtime_error;
  728. /* let's see how many attributes we have */
  729. nr_attrs = NR_OF_ATTR(kid);
  730. /* get the attributes */
  731. p = ATTR_PTR(kid);
  732. for(j=0;j<nr_attrs;j++) {
  733. /* get the attribute */
  734. get_basic_attr( p, attr_name, attr_len, intr, script_error);
  735. get_str_attr( p, attr_str, attr_len, intr, script_error,1);
  736. /* process the attribute */
  737. DBG("DEBUG:cpl_c:run_time_node: attribute [%d] found :"
  738. "[%s]\n",attr_name, attr_str);
  739. switch (attr_name) {
  740. case DTSTART_ATTR:
  741. if( !attr_str || tr_parse_dtstart(&trt, attr_str))
  742. goto parse_err;
  743. flags ^= (1<<0);
  744. break;
  745. case DTEND_ATTR:
  746. if( !attr_str || tr_parse_dtend(&trt, attr_str))
  747. goto parse_err;
  748. flags ^= (1<<1);
  749. break;
  750. case DURATION_ATTR:
  751. if( !attr_str || tr_parse_duration(&trt, attr_str))
  752. goto parse_err;
  753. flags ^= (1<<1);
  754. break;
  755. case FREQ_ATTR:
  756. if( attr_str && tr_parse_freq(&trt, attr_str))
  757. goto parse_err;
  758. break;
  759. case UNTIL_ATTR:
  760. if( attr_str && tr_parse_until(&trt, attr_str))
  761. goto parse_err;
  762. break;
  763. case INTERVAL_ATTR:
  764. if( attr_str && tr_parse_interval(&trt, attr_str))
  765. goto parse_err;
  766. break;
  767. case BYDAY_ATTR:
  768. if( attr_str && tr_parse_byday(&trt, attr_str))
  769. goto parse_err;
  770. break;
  771. case BYMONTHDAY_ATTR:
  772. if( attr_str && tr_parse_bymday(&trt, attr_str))
  773. goto parse_err;
  774. break;
  775. case BYYEARDAY_ATTR:
  776. if( attr_str && tr_parse_byyday(&trt, attr_str))
  777. goto parse_err;
  778. break;
  779. case BYMONTH_ATTR:
  780. if( attr_str && tr_parse_bymonth(&trt, attr_str))
  781. goto parse_err;
  782. break;
  783. case BYWEEKNO_ATTR:
  784. if( attr_str && tr_parse_byweekno(&trt, attr_str))
  785. goto parse_err;
  786. break;
  787. case WKST_ATTR:
  788. if( attr_str && tr_parse_wkst(&trt, attr_str))
  789. goto parse_err;
  790. break;
  791. default:
  792. LOG(L_ERR,"ERROR:cpl_c:run_time_switch: "
  793. "unsupported attribute [%d] found in TIME "
  794. "node\n",attr_name);
  795. goto script_error;
  796. } /* end attribute switch */
  797. } /* end for*/
  798. /* check the mandatory attributes */
  799. if ( (flags&0x03)!=((1<<0)|(1<<1)) ) {
  800. LOG(L_ERR,"ERROR:cpl_c:run_time_switch: attribute DTSTART"
  801. ",DTEND,DURATION missing or multi-present\n");
  802. goto script_error;
  803. }
  804. /* does the recv_time match the specified interval? */
  805. j = check_tmrec( &trt, &att, 0);
  806. /* restore the orig TZ */
  807. if ( flags&(1<<7) )
  808. set_TZ(cpl_env.orig_tz.s);
  809. /* free structs that I don't need any more */
  810. ac_tm_free( &att );
  811. tmrec_free( &trt );
  812. /* let's see the result ;-) */
  813. switch (j) {
  814. case 0:
  815. DBG("DEBUG:run_time_switch: matching current "
  816. "TIME node\n");
  817. return get_first_child(kid);
  818. case -1:
  819. LOG(L_ERR,"ERROR:cpl_c:run_time_switch: check_tmrec "
  820. "ret. err. when testing time cond. !\n");
  821. goto runtime_error;
  822. break;
  823. case 1:
  824. DBG("DEBUG:cpl_c:run_time_switch: time cond. doesn't"
  825. " match !\n");
  826. break;
  827. }
  828. break;
  829. default:
  830. LOG(L_ERR,"ERROR:cpl-c:run_priority_switch: unknown output node"
  831. " type (%d) for PRIORITY_SWITCH node\n",NODE_TYPE(kid));
  832. goto script_error;
  833. } /* end switch for NODE_TYPE */
  834. } /* end for for all kids */
  835. /* none of the branches of TIME_SWITCH matched -> go for default */
  836. ac_tm_free( &att );
  837. tmrec_free( &trt );
  838. return DEFAULT_ACTION;
  839. runtime_error:
  840. if ( flags&(1<<7) )
  841. set_TZ(cpl_env.orig_tz.s);
  842. ac_tm_free( &att );
  843. tmrec_free( &trt );
  844. return CPL_RUNTIME_ERROR;
  845. parse_err:
  846. LOG(L_ERR,"ERROR:cpl-c:run_priority_switch: error parsing attr [%d][%s]\n",
  847. attr_name,attr_str?(char*)attr_str:"NULL");
  848. script_error:
  849. if ( flags&(1<<7) )
  850. set_TZ(cpl_env.orig_tz.s);
  851. ac_tm_free( &att );
  852. tmrec_free( &trt );
  853. return CPL_SCRIPT_ERROR;
  854. }
  855. inline static int is_lang_tag_matching(str *range,str *cpl_tag,str *cpl_subtag)
  856. {
  857. char *c;
  858. char *end;
  859. str tag = STR_NULL;
  860. str subtag = STR_NULL;
  861. c = range->s;
  862. end = range->s + range->len;
  863. while(c<end) {
  864. /* eat all spaces to first letter */
  865. while(c<end && (*c==' ' || *c=='\t')) c++;
  866. if (c==end) goto error;
  867. /* init tag and subtag */
  868. tag.len = 0;
  869. subtag.len = 0;
  870. /* get the tag */
  871. tag.s = c;
  872. if (*c=='*' && (c+1==end||*(c+1)!='-')) {
  873. tag.len++;
  874. c++;
  875. } else while (c<end && ((*c)|0x20)>='a' && ((*c)|0x20)<='z' ) {
  876. /*DBG("--- tag ---> <%c>[%d]\n",*c,*c);*/
  877. tag.len++;
  878. c++;
  879. }
  880. if (tag.len==0) goto error;
  881. if (c<end && *c=='-') {
  882. /* go for the subtag */
  883. subtag.s = ++c;
  884. while (c<end && ((*c)|0x20)>='a' && ((*c)|0x20)<='z' ) {
  885. /*DBG("--- subtag ---> <%c>[%d]\n",*c,*c);*/
  886. subtag.len++;
  887. c++;
  888. }
  889. if (subtag.len==0) goto error;
  890. } else {
  891. subtag.s = 0;
  892. }
  893. if (c<end && *c==';') {
  894. /* eat all the params to the ',' */
  895. while(c<end && *c!=',') c++;
  896. if (c==end) goto no_matche;
  897. }
  898. while(c<end && (*c==' '||*c=='\t')) c++;
  899. if (c==end || *c==',') {
  900. /* do compare */
  901. DBG("DEBUG:cpl-c:is_lang_tag_matching: testing range [%.*s]-[%.*s]"
  902. " against tag [%.*s]-[%.*s]\n",
  903. tag.len,tag.s,subtag.len,subtag.s,
  904. cpl_tag->len,cpl_tag->s,cpl_subtag->len,cpl_subtag->s);
  905. /* language range of "*" is ignored for the purpose of matching*/
  906. if ( !(tag.len==1 && *tag.s=='*') ) {
  907. /* does the language tag matches ? */
  908. if (tag.len==cpl_tag->len && !strncasecmp(tag.s,cpl_tag->s,
  909. tag.len)) {
  910. DBG("cucu bau \n");
  911. /* if the subtag of the range is void -> matche */
  912. if (subtag.len==0)
  913. return 1;
  914. /* the subtags equals -> matche */
  915. if (subtag.len==cpl_subtag->len &&
  916. !strncasecmp(subtag.s,cpl_subtag->s,subtag.len) )
  917. return 1;
  918. }
  919. }
  920. /* if ',' go for the next language range */
  921. if (*c==',') c++;
  922. } else {
  923. goto error;
  924. }
  925. }
  926. no_matche:
  927. return 0;
  928. error:
  929. LOG(L_ERR,"ERROR:cpl-c:is_lang_tag_matching: parse error in Accept-"
  930. "Language body <%.*s> at char <%c>[%d] offset %ld!\n",
  931. range->len,range->s,*c,*c,(long)(c-range->s));
  932. return -1;
  933. }
  934. /* UPDATED + CHECKED
  935. */
  936. static inline char *run_language_switch( struct cpl_interpreter *intr )
  937. {
  938. char *p;
  939. char *kid;
  940. char *not_present_node;
  941. unsigned short attr_name;
  942. int nr_attr;
  943. int i,j;
  944. str attr = STR_NULL;
  945. str msg_val = STR_NULL;
  946. str lang_tag = STR_NULL;
  947. str lang_subtag = STR_NULL;
  948. not_present_node = 0;
  949. for( i=0 ; i<NR_OF_KIDS(intr->ip) ; i++ ) {
  950. kid = intr->ip + KID_OFFSET(intr->ip,i);
  951. check_overflow_by_ptr( kid+SIMPLE_NODE_SIZE(kid), intr, script_error);
  952. switch ( NODE_TYPE(kid) ) {
  953. case NOT_PRESENT_NODE:
  954. if (not_present_node) {
  955. LOG(L_ERR,"ERROR:run_language_switch: NOT_PRESENT node "
  956. "found twice!\n");
  957. goto script_error;
  958. }
  959. not_present_node = kid;
  960. break;
  961. case OTHERWISE_NODE :
  962. if (i!=NR_OF_KIDS(intr->ip)-1) {
  963. LOG(L_ERR,"ERROR:run_language_switch: OTHERWISE node "
  964. "not found as the last sub-node!\n");
  965. goto script_error;
  966. }
  967. DBG("DEBUG:run_language_switch: matching on OTHERWISE node\n");
  968. return get_first_child(kid);
  969. case LANGUAGE_NODE :
  970. /* check the number of attributes */
  971. nr_attr = NR_OF_ATTR(kid);
  972. if (nr_attr<1 || nr_attr>2) {
  973. LOG(L_ERR,"ERROR:run_string_switch: incorrect nr of attrs "
  974. "(%d) in LANGUAGE node (1 or 2)\n",NR_OF_ATTR(kid));
  975. goto script_error;
  976. }
  977. /* get the attributes */
  978. p = ATTR_PTR(kid);
  979. lang_tag.s = lang_subtag.s = 0;
  980. lang_tag.len = lang_subtag.len = 0;
  981. for(j=0;j<nr_attr;j++) {
  982. get_basic_attr( p, attr_name, attr.len, intr, script_error);
  983. get_str_attr( p, attr.s, attr.len, intr, script_error,0);
  984. if (attr_name==MATCHES_TAG_ATTR ) {
  985. lang_tag = attr;
  986. DBG("DEBUG:cpl-c:run_language_string: language-tag is"
  987. " [%.*s]\n",attr.len,attr.s);
  988. }else if (attr_name==MATCHES_SUBTAG_ATTR) {
  989. lang_subtag = attr;
  990. DBG("DEBUG:cpl-c:run_language_string: language-subtag"
  991. " is [%.*s]\n",attr.len,attr.s);
  992. }else {
  993. LOG(L_ERR,"ERROR:run_language_switch: unknown attribute"
  994. " (%d) in LANGUAGE node\n",attr_name);
  995. goto script_error;
  996. }
  997. }
  998. /* get the value from the SIP message -> if not yet, do it now
  999. * and remember it for the next times */
  1000. if (!msg_val.s) {
  1001. if (intr->accept_language==STR_NOT_FOUND)
  1002. goto not_present;
  1003. if (!intr->accept_language) {
  1004. /* get the accept_language header */
  1005. if (!intr->msg->accept_language) {
  1006. if (parse_headers(intr->msg,
  1007. HDR_ACCEPTLANGUAGE_F,0)==-1) {
  1008. LOG(L_ERR,"ERROR:run_language_switch: "
  1009. "bad ACCEPT_LANGUAGE header\n");
  1010. goto runtime_error;
  1011. } else if (!intr->msg->accept_language) {
  1012. /* hdr not present */
  1013. intr->accept_language = STR_NOT_FOUND;
  1014. goto not_present;
  1015. }
  1016. }
  1017. intr->subject =
  1018. &(intr->msg->accept_language->body);
  1019. }
  1020. }
  1021. trim_len( msg_val.len,msg_val.s, *(intr->subject));
  1022. DBG("DEBUG:run_language_switch: extracted msg string is "
  1023. "<%.*s>\n",msg_val.len, msg_val.s);
  1024. /* does the value from script match the one from message? */
  1025. if (msg_val.len && msg_val.s) {
  1026. j = is_lang_tag_matching(&msg_val,&lang_tag,&lang_subtag);
  1027. if (j==1) {
  1028. DBG("DEBUG:run_language_switch: matching on "
  1029. "LANGUAGE node\n");
  1030. return get_first_child(kid);
  1031. }else if (j==-1) {
  1032. goto runtime_error;
  1033. }
  1034. }
  1035. break;
  1036. default:
  1037. LOG(L_ERR,"ERROR:cpl_c:run_language_switch: unknown output "
  1038. "node type (%d) for LANGUAGE_SWITCH node\n",
  1039. NODE_TYPE(kid));
  1040. goto script_error;
  1041. } /* end switch for NODE_TYPE */
  1042. } /* end for for all kids */
  1043. return DEFAULT_ACTION;
  1044. not_present:
  1045. DBG("DEBUG:run_string_switch: required hdr not present in sip msg\n");
  1046. if (not_present_node)
  1047. return get_first_child(not_present_node);
  1048. /* look for the NOT_PRESENT node */
  1049. DBG("DEBUG:run_string_switch: searching for NOT_PRESENT sub-node..\n");
  1050. for(; i<NR_OF_KIDS(intr->ip) ; i++ ) {
  1051. kid = intr->ip + KID_OFFSET(intr->ip,i);
  1052. check_overflow_by_ptr( kid+SIMPLE_NODE_SIZE(kid), intr, script_error);
  1053. if (NODE_TYPE(kid)==NOT_PRESENT_NODE)
  1054. return get_first_child(kid);
  1055. }
  1056. return DEFAULT_ACTION;
  1057. runtime_error:
  1058. return CPL_RUNTIME_ERROR;
  1059. script_error:
  1060. return CPL_SCRIPT_ERROR;
  1061. }