00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 #include "../../comp_defs.h"
00064 #include "../../action.h"
00065 #include "../../sr_module.h"
00066 #include "../../dprint.h"
00067 #include "../../data_lump.h"
00068 #include "../../data_lump_rpl.h"
00069 #include "../../error.h"
00070 #include "../../mem/mem.h"
00071 #include "../../re.h"
00072 #include "../../parser/parse_uri.h"
00073 #include "../../parser/parse_hname2.h"
00074 #include "../../onsend.h"
00075 #include "../../ut.h"
00076 #include "../../select.h"
00077 #include "../xlog/xl_lib.h"
00078 #include "../../script_cb.h"
00079 #include "../../select_buf.h"
00080 #include "../../ser_time.h"
00081 #include "../../dset.h"
00082 #include <stdio.h>
00083 #include <stdlib.h>
00084 #include <string.h>
00085 #include <sys/types.h>
00086 #include <regex.h>
00087 #include <time.h>
00088 #include <sys/time.h>
00089
00090 MODULE_VERSION
00091
00092
00093
00094
00095
00096
00097
00098 #define TIME_FORMAT "Date: %a, %d %b %Y %H:%M:%S GMT"
00099 #define MAX_TIME 64
00100
00101 static int xlbuf_size = 4096;
00102
00103
00104 static int search_f(struct sip_msg*, char*, char*);
00105 static int replace_f(struct sip_msg*, char*, char*);
00106 static int subst_f(struct sip_msg*, char*, char*);
00107 static int subst_uri_f(struct sip_msg*, char*, char*);
00108 static int subst_user_f(struct sip_msg*, char*, char*);
00109 static int remove_hf_f(struct sip_msg* msg, char* str_hf, char* foo);
00110 static int remove_hf_re_f(struct sip_msg* msg, char* str_hf, char* foo);
00111 static int is_present_hf_f(struct sip_msg* msg, char* str_hf, char* foo);
00112 static int replace_all_f(struct sip_msg* msg, char* key, char* str);
00113 static int search_append_f(struct sip_msg*, char*, char*);
00114 static int append_to_reply_f(struct sip_msg* msg, char* key, char* str);
00115 static int append_hf(struct sip_msg* msg, char* str1, char* str2);
00116 static int append_urihf(struct sip_msg* msg, char* str1, char* str2);
00117 static int append_time_f(struct sip_msg* msg, char* , char *);
00118
00119 static int incexc_hf_value_f(struct sip_msg* msg, char* , char *);
00120 static int include_hf_value_fixup(void**, int);
00121 static int exclude_hf_value_fixup(void**, int);
00122 static int hf_value_exists_fixup(void**, int);
00123
00124 static int insupddel_hf_value_f(struct sip_msg* msg, char* _hname, char* _val);
00125 static int append_hf_value_fixup(void** param, int param_no);
00126 static int insert_hf_value_fixup(void** param, int param_no);
00127 static int remove_hf_value_fixup(void** param, int param_no);
00128 static int assign_hf_value_fixup(void** param, int param_no);
00129 static int remove_hf_value2_fixup(void** param, int param_no);
00130 static int assign_hf_value2_fixup(void** param, int param_no);
00131 static int fixup_xlstr(void** param, int param_no);
00132 static int fixup_regex_xlstr(void** param, int param_no);
00133
00134 static int fixup_substre(void**, int);
00135
00136 extern select_row_t sel_declaration[];
00137
00138 static int mod_init(void);
00139
00140
00141 static cmd_export_t cmds[]={
00142 {"search", search_f, 1, fixup_regex_1,
00143 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|ONSEND_ROUTE},
00144 {"search_append", search_append_f, 2, fixup_regex_xlstr,
00145 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE},
00146 {"replace", replace_f, 2, fixup_regex_xlstr,
00147 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE},
00148 {"replace_all", replace_all_f, 2, fixup_regex_xlstr,
00149 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE},
00150 {"append_to_reply", append_to_reply_f, 1, fixup_xlstr,
00151 REQUEST_ROUTE},
00152 {"append_hf", append_hf, 1, fixup_xlstr,
00153 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE | BRANCH_ROUTE},
00154 {"append_urihf", append_urihf, 2, fixup_xlstr,
00155 REQUEST_ROUTE|FAILURE_ROUTE},
00156
00157 {"remove_hf", remove_hf_f, 1, fixup_var_str_1,
00158 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE},
00159 {"remove_hf_re", remove_hf_re_f, 1, fixup_regex_12,
00160 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE},
00161
00162 {"is_present_hf", is_present_hf_f, 1, fixup_var_str_1,
00163 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE},
00164 {"subst", subst_f, 1, fixup_substre,
00165 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE},
00166 {"subst_uri", subst_uri_f, 1, fixup_substre,
00167 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE},
00168 {"subst_user", subst_user_f, 1, fixup_substre,
00169 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE},
00170 {"append_time", append_time_f, 0, 0,
00171 REQUEST_ROUTE },
00172
00173
00174 {"append_hf_value", insupddel_hf_value_f, 2, append_hf_value_fixup,
00175 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
00176 {"insert_hf_value", insupddel_hf_value_f, 2, insert_hf_value_fixup,
00177 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
00178 {"remove_hf_value", insupddel_hf_value_f, 1, remove_hf_value_fixup,
00179 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
00180 {"assign_hf_value", insupddel_hf_value_f, 2, assign_hf_value_fixup,
00181 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
00182 {"remove_hf_value2", insupddel_hf_value_f, 1, remove_hf_value2_fixup,
00183 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
00184 {"assign_hf_value2", insupddel_hf_value_f, 2, assign_hf_value2_fixup,
00185 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
00186 {"include_hf_value", incexc_hf_value_f, 2, include_hf_value_fixup,
00187 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
00188 {"exclude_hf_value", incexc_hf_value_f, 2, exclude_hf_value_fixup,
00189 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
00190 {"hf_value_exists", incexc_hf_value_f, 2, hf_value_exists_fixup,
00191 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
00192
00193 {0,0,0,0,0}
00194 };
00195
00196 static param_export_t params[]={
00197 {"xlbuf_size", PARAM_INT, &xlbuf_size},
00198
00199 {0,0,0}
00200 };
00201
00202 struct module_exports exports= {
00203 "textops",
00204 cmds,
00205 0,
00206 params,
00207 mod_init,
00208 0,
00209 0,
00210 0,
00211 0,
00212 };
00213
00214 static int mod_init(void)
00215 {
00216 DBG("%s - initializing\n", exports.name);
00217 register_select_table(sel_declaration);
00218 return 0;
00219 }
00220
00221 struct xlstr {
00222 str s;
00223 xl_elog_t* xlfmt;
00224 };
00225
00226 static xl_print_log_f* xl_print = NULL;
00227 static xl_parse_format_f* xl_parse = NULL;
00228
00229 #define NO_SCRIPT -1
00230
00231 static int fixup_xlstr(void** param, int param_no) {
00232 struct xlstr* s;
00233 s = pkg_malloc(sizeof(*s));
00234 if (!s) return E_OUT_OF_MEM;
00235 s->s.s = *param;
00236 s->s.len = strlen(s->s.s);
00237 s->xlfmt = 0;
00238 if (strchr(s->s.s, '%')) {
00239 if (!xl_print) {
00240 xl_print=(xl_print_log_f*)find_export("xprint", NO_SCRIPT, 0);
00241 if (!xl_print) {
00242 LOG(L_CRIT,"ERROR: textops: cannot find \"xprint\", is module xlog loaded?\n");
00243 return E_UNSPEC;
00244 }
00245 }
00246
00247 if (!xl_parse) {
00248 xl_parse=(xl_parse_format_f*)find_export("xparse", NO_SCRIPT, 0);
00249 if (!xl_parse) {
00250 LOG(L_CRIT,"ERROR: textops: cannot find \"xparse\", is module xlog loaded?\n");
00251 return E_UNSPEC;
00252 }
00253 }
00254 if(xl_parse(s->s.s, &s->xlfmt) < 0) {
00255 LOG(L_ERR, "ERROR: textops: wrong format '%s'\n", s->s.s);
00256 return E_UNSPEC;
00257 }
00258 }
00259 *param = s;
00260 return 0;
00261 }
00262
00263 static int eval_xlstr(struct sip_msg* msg, struct xlstr* val, str* s) {
00264 static char *xlbuf = NULL;
00265 if (val) {
00266 if (val->xlfmt) {
00267 if (!xlbuf) {
00268 xlbuf = pkg_malloc(xlbuf_size);
00269 if (!xlbuf) {
00270 LOG(L_ERR, "ERROR: out of memory\n");
00271 return E_OUT_OF_MEM;
00272 }
00273 }
00274 s->len = xlbuf_size-1;
00275 if (xl_print(msg, val->xlfmt, xlbuf, &s->len) < 0) {
00276 LOG(L_ERR, "ERROR: textops: eval_xlstr: Error while formating result '%.*s'\n", val->s.len, val->s.s);
00277 s->len = 0;
00278 return E_UNSPEC;
00279 }
00280 s->s = xlbuf;
00281 }
00282 else {
00283 *s = val->s;
00284 }
00285 }
00286 else
00287 s->len = 0;
00288 return 1;
00289 }
00290
00291 static int fixup_regex_xlstr(void** param, int param_no) {
00292 if (param_no == 1)
00293 return fixup_regex_1(param, param_no);
00294 else if (param_no == 2)
00295 return fixup_xlstr(param, param_no);
00296 else
00297 return 0;
00298 }
00299
00300 static char *get_header(struct sip_msg *msg)
00301 {
00302 return SIP_MSG_START(msg)+msg->first_line.len;
00303 }
00304
00305 static int search_f(struct sip_msg* msg, char* key, char* str2)
00306 {
00307
00308 regmatch_t pmatch;
00309 char* buf;
00310 struct onsend_info* snd_inf;
00311
00312 if ((snd_inf=get_onsend_info())!=0)
00313 buf=snd_inf->buf;
00314 else
00315 buf=msg->buf;
00316
00317 if (regexec(((fparam_t*)key)->v.regex, buf, 1, &pmatch, 0)!=0) return -1;
00318 return 1;
00319 }
00320
00321 static int search_append_f(struct sip_msg* msg, char* key, char* _str)
00322 {
00323 struct lump* l;
00324 regmatch_t pmatch;
00325 str str;
00326 char* s;
00327 char *begin;
00328 int off;
00329
00330 begin=get_header(msg);
00331 off=begin-msg->buf;
00332
00333 if (regexec(((fparam_t*)key)->v.regex, begin, 1, &pmatch, 0)!=0) return -1;
00334 if (pmatch.rm_so!=-1){
00335 if (eval_xlstr(msg, (void*) _str, &str) < 0) return -1;
00336
00337 if ((l=anchor_lump(msg, off+pmatch.rm_eo, 0, 0))==0)
00338 return -1;
00339 s=pkg_malloc(str.len);
00340 if (s==0){
00341 LOG(L_ERR, "ERROR: search_append_f: mem. allocation failure\n");
00342 return -1;
00343 }
00344 memcpy(s, str.s, str.len);
00345 if (insert_new_lump_after(l, s, str.len, 0)==0){
00346 LOG(L_ERR, "ERROR: could not insert new lump\n");
00347 pkg_free(s);
00348 return -1;
00349 }
00350 return 1;
00351 }
00352 return -1;
00353 }
00354
00355
00356 static int replace_all_f(struct sip_msg* msg, char* key, char* _str)
00357 {
00358 struct lump* l;
00359 regmatch_t pmatch;
00360 char* s;
00361 str str;
00362 char* begin;
00363 int off;
00364 int ret;
00365 int eflags;
00366
00367
00368 parse_headers(msg, HDR_EOH_F, 0);
00369
00370 begin=get_header(msg);
00371 ret=-1;
00372 eflags=0;
00373
00374 if (eval_xlstr(msg, (void*) _str, &str) < 0) return -1;
00375 while (begin<msg->buf+msg->len
00376 && regexec(((fparam_t*)key)->v.regex, begin, 1, &pmatch, eflags)==0) {
00377 off=begin-msg->buf;
00378
00379 eflags|=REG_NOTBOL;
00380 if (pmatch.rm_so==-1){
00381 LOG(L_ERR, "ERROR: replace_all_f: offset unknown\n");
00382 return -1;
00383 }
00384 if ((l=del_lump(msg, pmatch.rm_so+off,
00385 pmatch.rm_eo-pmatch.rm_so, 0))==0) {
00386 LOG(L_ERR, "ERROR: replace_all_f: del_lump failed\n");
00387 return -1;
00388 }
00389 s=pkg_malloc(str.len);
00390 if (s==0){
00391 LOG(L_ERR, "ERROR: replace_all_f: mem. allocation failure\n");
00392 return -1;
00393 }
00394 memcpy(s, str.s, str.len);
00395 if (insert_new_lump_after(l, s, str.len, 0)==0){
00396 LOG(L_ERR, "ERROR: could not insert new lump\n");
00397 pkg_free(s);
00398 return -1;
00399 }
00400
00401 begin=begin+pmatch.rm_eo;
00402 ret=1;
00403 }
00404 return ret;
00405 }
00406
00407 static int replace_f(struct sip_msg* msg, char* key, char* _str)
00408 {
00409 struct lump* l;
00410 regmatch_t pmatch;
00411 char* s;
00412 str str;
00413 char* begin;
00414 int off;
00415
00416
00417 parse_headers(msg, HDR_EOH_F, 0);
00418
00419 begin=get_header(msg);
00420
00421 if (regexec(((fparam_t*)key)->v.regex, begin, 1, &pmatch, 0)!=0) return -1;
00422 off=begin-msg->buf;
00423
00424 if (pmatch.rm_so!=-1){
00425 if (eval_xlstr(msg, (void*) _str, &str) < 0) return -1;
00426
00427 if ((l=del_lump(msg, pmatch.rm_so+off,
00428 pmatch.rm_eo-pmatch.rm_so, 0))==0)
00429 return -1;
00430 s=pkg_malloc(str.len);
00431 if (s==0){
00432 LOG(L_ERR, "ERROR: replace_f: mem. allocation failure\n");
00433 return -1;
00434 }
00435 memcpy(s, str.s, str.len);
00436 if (insert_new_lump_after(l, s, str.len, 0)==0){
00437 LOG(L_ERR, "ERROR: could not insert new lump\n");
00438 pkg_free(s);
00439 return -1;
00440 }
00441
00442 return 1;
00443 }
00444 return -1;
00445 }
00446
00447
00448
00449
00450 static int subst_f(struct sip_msg* msg, char* subst, char* ignored)
00451 {
00452 struct lump* l;
00453 struct replace_lst* lst;
00454 struct replace_lst* rpl;
00455 char* begin;
00456 struct subst_expr* se;
00457 int off;
00458 int ret;
00459 int nmatches;
00460
00461 se=(struct subst_expr*)subst;
00462 begin=get_header(msg);
00463
00464 off=begin-msg->buf;
00465 ret=-1;
00466 if ((lst=subst_run(se, begin, msg, &nmatches))==0)
00467 goto error;
00468 for (rpl=lst; rpl; rpl=rpl->next){
00469 DBG(" %s: subst_f: replacing at offset %d [%.*s] with [%.*s]\n",
00470 exports.name, rpl->offset+off,
00471 rpl->size, rpl->offset+off+msg->buf,
00472 rpl->rpl.len, rpl->rpl.s);
00473 if ((l=del_lump(msg, rpl->offset+off, rpl->size, 0))==0)
00474 goto error;
00475
00476
00477 if (insert_new_lump_after(l, rpl->rpl.s, rpl->rpl.len, 0)==0){
00478 LOG(L_ERR, "ERROR: %s: subst_f: could not insert new lump\n",
00479 exports.name);
00480 goto error;
00481 }
00482
00483
00484 rpl->rpl.s=0;
00485 rpl->rpl.len=0;
00486 }
00487 ret=1;
00488 error:
00489 DBG("subst_f: lst was %p\n", lst);
00490 if (lst) replace_lst_free(lst);
00491 if (nmatches<0)
00492 LOG(L_ERR, "ERROR: %s: subst_run failed\n", exports.name);
00493 return ret;
00494 }
00495
00496
00497
00498
00499
00500 static int subst_uri_f(struct sip_msg* msg, char* subst, char* ignored)
00501 {
00502 char* tmp;
00503 int len;
00504 char c;
00505 struct subst_expr* se;
00506 str* result;
00507
00508 se=(struct subst_expr*)subst;
00509 if (msg->new_uri.s){
00510 len=msg->new_uri.len;
00511 tmp=msg->new_uri.s;
00512 }else{
00513 tmp=msg->first_line.u.request.uri.s;
00514 len =msg->first_line.u.request.uri.len;
00515 };
00516
00517
00518
00519
00520 c=tmp[len];
00521 tmp[len]=0;
00522 result=subst_str(tmp, msg, se, 0);
00523 tmp[len]=c;
00524 if (result){
00525 DBG("%s: subst_uri_f: match - old uri= [%.*s], new uri= [%.*s]\n",
00526 exports.name, len, tmp,
00527 (result->len)?result->len:0,(result->s)?result->s:"");
00528 if (msg->new_uri.s) pkg_free(msg->new_uri.s);
00529 msg->new_uri=*result;
00530 msg->parsed_uri_ok=0;
00531 ruri_mark_new();
00532 pkg_free(result);
00533 return 1;
00534 }
00535 return -1;
00536 }
00537
00538
00539
00540
00541
00542 static int subst_user_f(struct sip_msg* msg, char* subst, char* ignored)
00543 {
00544 int rval;
00545 str* result;
00546 struct subst_expr* se;
00547 struct action act;
00548 str user;
00549 char c;
00550 int nmatches;
00551 struct run_act_ctx ra_ctx;
00552
00553 c=0;
00554 if (parse_sip_msg_uri(msg)<0){
00555 return -1;
00556 }
00557 if (msg->parsed_uri.user.s==0){
00558
00559 user.s="";
00560 user.len=0;
00561 }else{
00562 user=msg->parsed_uri.user;
00563 c=user.s[user.len];
00564 user.s[user.len]=0;
00565 }
00566 se=(struct subst_expr*)subst;
00567 result=subst_str(user.s, msg, se, &nmatches);
00568 if (c) user.s[user.len]=c;
00569 if (result == NULL) {
00570 if (nmatches<0)
00571 LOG(L_ERR, "subst_user(): subst_str() failed\n");
00572 return -1;
00573 }
00574
00575 memset(&act, 0, sizeof(act));
00576 act.type = SET_USER_T;
00577 act.val[0].type = STRING_ST;
00578 act.val[0].u.string = result->s;
00579 init_run_actions_ctx(&ra_ctx);
00580 rval = do_action(&ra_ctx, &act, msg);
00581 if (result->s) pkg_free(result->s);
00582 pkg_free(result);
00583 return rval;
00584 }
00585
00586
00587 static inline int remove_hf(struct sip_msg* msg, char* p1, int by_re)
00588 {
00589 struct hdr_field *hf;
00590 struct lump* l;
00591 int cnt;
00592 str hfn;
00593 regex_t regexp;
00594 regmatch_t matches;
00595 char bkup;
00596 int no_match;
00597
00598 if (by_re) {
00599 if (get_regex_fparam(®exp, msg, (fparam_t*)p1) < 0) {
00600 ERR("remove_hf: Error while obtaining parameter value\n");
00601 return -1;
00602 }
00603 } else {
00604 if (get_str_fparam(&hfn, msg, (fparam_t*)p1) < 0) {
00605 ERR("remove_hf: Error while obtaining parameter value\n");
00606 return -1;
00607 }
00608 }
00609
00610 cnt=0;
00611
00612 parse_headers(msg, HDR_EOH_F, 0);
00613 for (hf=msg->headers; hf; hf=hf->next) {
00614 if (by_re) {
00615
00616 bkup = hf->name.s[hf->name.len];
00617 hf->name.s[hf->name.len] = 0;
00618 no_match = regexec(®exp, hf->name.s, 1, &matches,
00619 0);
00620 hf->name.s[hf->name.len] = bkup;
00621 if (no_match)
00622 continue;
00623 } else {
00624 if (hf->name.len!=hfn.len)
00625 continue;
00626 if (strncasecmp(hf->name.s, hfn.s, hf->name.len)!=0)
00627 continue;
00628 }
00629 l=del_lump(msg, hf->name.s-msg->buf, hf->len, 0);
00630 if (l==0) {
00631 ERR("no memory\n");
00632 return -1;
00633 }
00634 cnt++;
00635 }
00636 return cnt==0 ? -1 : 1;
00637 }
00638
00639 static int remove_hf_f(struct sip_msg* msg, char* p1, char* foo)
00640 {
00641 return remove_hf(msg, p1, 0);
00642 }
00643
00644 static int remove_hf_re_f(struct sip_msg* msg, char* p1, char* foo)
00645 {
00646 return remove_hf(msg, p1, 1);
00647 }
00648
00649 static int is_present_hf_f(struct sip_msg* msg, char* p1, char* foo)
00650 {
00651 struct hdr_field *hf;
00652 str hfn;
00653
00654 if (get_str_fparam(&hfn, msg, (fparam_t*)p1) < 0) {
00655 ERR("is_present_hf: Error while obtaining parameter value\n");
00656 return -1;
00657 }
00658
00659
00660 parse_headers(msg, HDR_EOH_F, 0);
00661 for (hf=msg->headers; hf; hf=hf->next) {
00662 if (hf->name.len!=hfn.len)
00663 continue;
00664 if (strncasecmp(hf->name.s, hfn.s, hf->name.len)!=0)
00665 continue;
00666 return 1;
00667 }
00668 return -1;
00669 }
00670
00671 static int fixup_substre(void** param, int param_no)
00672 {
00673 struct subst_expr* se;
00674 str subst;
00675
00676 DBG("%s module -- fixing %s\n", exports.name, (char*)(*param));
00677 if (param_no!=1) return 0;
00678 subst.s=*param;
00679 subst.len=strlen(*param);
00680 se=subst_parser(&subst);
00681 if (se==0){
00682 LOG(L_ERR, "ERROR: %s: bad subst. re %s\n", exports.name,
00683 (char*)*param);
00684 return E_BAD_RE;
00685 }
00686
00687 pkg_free(*param);
00688
00689 *param=se;
00690 return 0;
00691 }
00692
00693
00694 static int append_time_f(struct sip_msg* msg, char* p1, char *p2)
00695 {
00696
00697
00698 size_t len;
00699 char time_str[MAX_TIME];
00700 time_t now;
00701 struct tm *bd_time;
00702
00703 now=ser_time(0);
00704
00705 bd_time=gmtime(&now);
00706 if (bd_time==NULL) {
00707 LOG(L_ERR, "ERROR: append_time: gmtime failed\n");
00708 return -1;
00709 }
00710
00711 len=strftime(time_str, MAX_TIME, TIME_FORMAT, bd_time);
00712 if (len>MAX_TIME-2 || len==0) {
00713 LOG(L_ERR, "ERROR: append_time: unexpected time length\n");
00714 return -1;
00715 }
00716
00717 time_str[len]='\r';
00718 time_str[len+1]='\n';
00719
00720
00721 if (add_lump_rpl(msg, time_str, len+2, LUMP_RPL_HDR)==0)
00722 {
00723 LOG(L_ERR, "ERROR: append_time: unable to add lump\n");
00724 return -1;
00725 }
00726
00727 return 1;
00728 }
00729
00730 static int append_to_reply_f(struct sip_msg* msg, char* _str, char* dummy)
00731 {
00732 str str;
00733 if (eval_xlstr(msg, (void*) _str, &str) < 0) return -1;
00734
00735 if ( add_lump_rpl( msg, str.s, str.len, LUMP_RPL_HDR)==0 )
00736 {
00737 LOG(L_ERR,"ERROR:append_to_reply : unable to add lump_rl\n");
00738 return -1;
00739 }
00740
00741 return 1;
00742 }
00743
00744
00745
00746
00747 static int append_hf_helper(struct sip_msg* msg, struct xlstr *_str1, struct xlstr *_str2)
00748 {
00749 struct lump* anchor;
00750 char *s;
00751 str str1, str2;
00752 int len;
00753
00754 if (eval_xlstr(msg, _str1, &str1) < 0) return -1;
00755 if (_str2) {
00756 if (eval_xlstr(msg, _str2, &str2) < 0) return -1;
00757 }
00758
00759 if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
00760 LOG(L_ERR, "append_hf(): Error while parsing message\n");
00761 return -1;
00762 }
00763
00764 anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0, 0);
00765 if (anchor == 0) {
00766 LOG(L_ERR, "append_hf(): Can't get anchor\n");
00767 return -1;
00768 }
00769
00770 len=str1.len;
00771 if (_str2) len+= str2.len + REQ_LINE(msg).uri.len;
00772
00773 s = (char*)pkg_malloc(len);
00774 if (!s) {
00775 LOG(L_ERR, "append_hf(): No memory left\n");
00776 return -1;
00777 }
00778
00779 memcpy(s, str1.s, str1.len);
00780 if (_str2) {
00781 memcpy(s+str1.len, REQ_LINE(msg).uri.s, REQ_LINE(msg).uri.len);
00782 memcpy(s+str1.len+REQ_LINE(msg).uri.len, str2.s, str2.len );
00783 }
00784
00785 if (insert_new_lump_before(anchor, s, len, 0) == 0) {
00786 LOG(L_ERR, "append_hf(): Can't insert lump\n");
00787 pkg_free(s);
00788 return -1;
00789 }
00790 return 1;
00791 }
00792
00793 static int append_hf(struct sip_msg *msg, char *str1, char *str2 )
00794 {
00795 return append_hf_helper(msg, (struct xlstr *) str1, (struct xlstr *) 0);
00796 }
00797
00798 static int append_urihf(struct sip_msg *msg, char *str1, char *str2 )
00799 {
00800 return append_hf_helper(msg, (struct xlstr *) str1, (struct xlstr *) str2);
00801 }
00802
00803 #define HNF_ALL 0x01
00804 #define HNF_IDX 0x02
00805
00806 #define MAX_HF_VALUE_STACK 10
00807
00808 enum {hnoInsert, hnoAppend, hnoAssign, hnoRemove, hnoInclude, hnoExclude, hnoIsIncluded, hnoGetValue, hnoGetValueUri, hnoGetValueName, hnoRemove2, hnoAssign2, hnoGetValue2};
00809
00810 struct hname_data {
00811 int oper;
00812 int htype;
00813 str hname;
00814 int flags;
00815 int idx;
00816 str param;
00817 };
00818
00819 #define is_space(_p) ((_p) == '\t' || (_p) == '\n' || (_p) == '\r' || (_p) == ' ')
00820
00821 #define eat_spaces(_p) \
00822 while( is_space(*(_p)) ){\
00823 (_p)++;}
00824
00825 #define is_alphanum(_p) (((_p) >= 'a' && (_p) <= 'z') || ((_p) >= 'A' && (_p) <= 'Z') || ((_p) >= '0' && (_p) <= '9') || (_p) == '_' || (_p) == '-')
00826
00827 #define eat_while_alphanum(_p) \
00828 while ( is_alphanum(*(_p)) ) {\
00829 (_p)++; }
00830
00831
00832 static int fixup_hname_param(char *hname, struct hname_data** h) {
00833 struct hdr_field hdr;
00834 char *savep, savec;
00835
00836 *h = pkg_malloc(sizeof(**h));
00837 if (!*h) return E_OUT_OF_MEM;
00838 memset(*h, 0, sizeof(**h));
00839
00840 memset(&hdr, 0, sizeof(hdr));
00841 eat_spaces(hname);
00842 (*h)->hname.s = hname;
00843 savep = hname;
00844 eat_while_alphanum(hname);
00845 (*h)->hname.len = hname - (*h)->hname.s;
00846 savec = *hname;
00847 *hname = ':';
00848 parse_hname2((*h)->hname.s, (*h)->hname.s+(*h)->hname.len+3, &hdr);
00849 *hname = savec;
00850
00851 if (hdr.type == HDR_ERROR_T) goto err;
00852 (*h)->htype = hdr.type;
00853
00854 eat_spaces(hname);
00855 savep = hname;
00856 if (*hname == '[') {
00857 hname++;
00858 eat_spaces(hname);
00859 savep = hname;
00860 (*h)->flags |= HNF_IDX;
00861 if (*hname == '*') {
00862 (*h)->flags |= HNF_ALL;
00863 hname++;
00864 }
00865 else if (*hname != ']') {
00866 char* c;
00867 (*h)->idx = strtol(hname, &c, 10);
00868 if (hname == c) goto err;
00869 hname = c;
00870 }
00871 eat_spaces(hname);
00872 savep = hname;
00873 if (*hname != ']') goto err;
00874 hname++;
00875 }
00876 eat_spaces(hname);
00877 savep = hname;
00878 if (*hname == '.') {
00879 hname++;
00880 eat_spaces(hname);
00881 savep = hname;
00882 (*h)->param.s = hname;
00883 eat_while_alphanum(hname);
00884 (*h)->param.len = hname-(*h)->param.s;
00885 if ((*h)->param.len == 0) goto err;
00886 }
00887 else {
00888 (*h)->param.s = hname;
00889 }
00890 savep = hname;
00891 if (*hname != '\0') goto err;
00892 (*h)->hname.s[(*h)->hname.len] = '\0';
00893 (*h)->param.s[(*h)->param.len] = '\0';
00894 return 0;
00895 err:
00896 pkg_free(*h);
00897 LOG(L_ERR, "ERROR: textops: cannot parse header near '%s'\n", savep);
00898 return E_CFG;
00899 }
00900
00901 static int fixup_hname_str(void** param, int param_no) {
00902 if (param_no == 1) {
00903 struct hname_data* h;
00904 int res = fixup_hname_param(*param, &h);
00905 if (res < 0) return res;
00906 *param = h;
00907 }
00908 else if (param_no == 2) {
00909 return fixup_xlstr(param, param_no);
00910 }
00911 return 0;
00912 }
00913
00914 static int find_next_hf(struct sip_msg* msg, struct hname_data* hname, struct hdr_field** hf) {
00915 if (!*hf) {
00916 if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
00917 LOG(L_ERR, "ERROR: textops: find_next_hf: Error while parsing message\n");
00918 return -1;
00919 }
00920 *hf = msg->headers;
00921 }
00922 else {
00923 *hf = (*hf)->next;
00924 }
00925 for (; *hf; *hf = (*hf)->next) {
00926 if (hname->htype == HDR_OTHER_T) {
00927 if ((*hf)->name.len==hname->hname.len && strncasecmp((*hf)->name.s, hname->hname.s, (*hf)->name.len)==0)
00928 return 1;
00929 }
00930 else if (hname->htype == (*hf)->type) {
00931 return 1;
00932 }
00933 }
00934 return 0;
00935 }
00936
00937 static int find_next_value(char** start, char* end, str* val, str* lump_val) {
00938 int quoted = 0;
00939 lump_val->s = *start;
00940 while (*start < end && is_space(**start) ) (*start)++;
00941 val->s = *start;
00942 while ( *start < end && (**start != ',' || quoted) ) {
00943 if (**start == '\"' && (!quoted || (*start)[-1]!='\\') )
00944 quoted = ~quoted;
00945 (*start)++;
00946 }
00947 val->len = *start - val->s;
00948 while (val->len > 0 && is_space(val->s[val->len-1])) val->len--;
00949
00950
00951
00952
00953
00954
00955 while (*start < end && **start != ',') (*start)++;
00956 if (*start < end) {
00957 (*start)++;
00958 }
00959 lump_val->len = *start - lump_val->s;
00960 return (*start < end);
00961 }
00962
00963 static void adjust_lump_val_for_delete(struct hdr_field* hf, str* lump_val) {
00964 if ( lump_val->s+lump_val->len == hf->body.s+hf->body.len ) {
00965 if (lump_val->s > hf->body.s) {
00966
00967 lump_val->s--;
00968 lump_val->len++;
00969 }
00970 }
00971 }
00972
00973 static int find_hf_value_idx(struct sip_msg* msg, struct hname_data* hname, struct hdr_field** hf, str* val, str* lump_val) {
00974 int res;
00975 char *p;
00976 if ( hname->flags & HNF_ALL || hname->idx == 0) return -1;
00977 *hf = 0;
00978 if (hname->idx > 0) {
00979 int idx;
00980 idx = hname->idx;
00981 do {
00982 res = find_next_hf(msg, hname, hf);
00983 if (res < 0) return -1;
00984 if (*hf) {
00985 if (val) {
00986 lump_val->len = 0;
00987 p = (*hf)->body.s;
00988 do {
00989 res = find_next_value(&p, (*hf)->body.s+(*hf)->body.len, val, lump_val);
00990 idx--;
00991 } while (res && idx);
00992 }
00993 else {
00994 idx--;
00995 }
00996 }
00997 } while (*hf && idx);
00998 }
00999 else if (hname->idx < 0) {
01000 struct hf_value_stack {
01001 str val, lump_val;
01002 struct hdr_field* hf;
01003 } stack[MAX_HF_VALUE_STACK];
01004 int stack_pos, stack_num;
01005
01006 if ( -hname->idx > MAX_HF_VALUE_STACK ) return -1;
01007 stack_pos = stack_num = 0;
01008 do {
01009 res = find_next_hf(msg, hname, hf);
01010 if (res < 0) return -1;
01011 if (*hf) {
01012 stack[stack_pos].lump_val.len = 0;
01013 p = (*hf)->body.s;
01014 do {
01015 stack[stack_pos].hf = *hf;
01016 if (val)
01017 res = find_next_value(&p, (*hf)->body.s+(*hf)->body.len, &stack[stack_pos].val, &stack[stack_pos].lump_val);
01018 else
01019 res = 0;
01020 stack_pos++;
01021 if (stack_pos >= MAX_HF_VALUE_STACK)
01022 stack_pos = 0;
01023 if (stack_num < MAX_HF_VALUE_STACK)
01024 stack_num++;
01025
01026 } while (res);
01027 }
01028 } while (*hf);
01029
01030 if (-hname->idx <= stack_num) {
01031 stack_pos += hname->idx;
01032 if (stack_pos < 0)
01033 stack_pos += MAX_HF_VALUE_STACK;
01034 *hf = stack[stack_pos].hf;
01035 if (val) {
01036 *val = stack[stack_pos].val;
01037 *lump_val = stack[stack_pos].lump_val;
01038 }
01039 }
01040 else {
01041 *hf = 0;
01042 }
01043 }
01044 else
01045 return -1;
01046 return *hf?1:0;
01047 }
01048
01049 static int find_hf_value_param(struct hname_data* hname, str* param_area, str* value, str* lump_upd, str* lump_del) {
01050 int i, j, found;
01051
01052 i = 0;
01053 while (1) {
01054 lump_del->s = param_area->s + i;
01055 for (; i < param_area->len && is_space(param_area->s[i]); i++);
01056 if (i < param_area->len && param_area->s[i] == ';') {
01057 i++;
01058 for (; i < param_area->len && is_space(param_area->s[i]); i++);
01059 j = i;
01060 for (; i < param_area->len && !is_space(param_area->s[i]) && param_area->s[i]!='=' && param_area->s[i]!=';'; i++);
01061
01062 found = hname->param.len == i-j && !strncasecmp(hname->param.s, param_area->s+j, i-j);
01063 lump_upd->s = param_area->s+i;
01064 value->s = param_area->s+i;
01065 value->len = 0;
01066 for (; i < param_area->len && is_space(param_area->s[i]); i++);
01067 if (i < param_area->len && param_area->s[i]=='=') {
01068 i++;
01069 for (; i < param_area->len && is_space(param_area->s[i]); i++);
01070 value->s = param_area->s+i;
01071 if (i < param_area->len) {
01072 if (param_area->s[i]=='\"') {
01073 i++;
01074 value->s++;
01075 for (; i<param_area->len; i++) {
01076 if (param_area->s[i]=='\"') {
01077 i++;
01078 break;
01079 }
01080 value->len++;
01081 }
01082 }
01083 else {
01084 for (; i<param_area->len && !is_space(param_area->s[i]) && param_area->s[i]!=';'; i++, value->len++);
01085 }
01086 }
01087 }
01088 if (found) {
01089 lump_del->len = param_area->s+i - lump_del->s;
01090 lump_upd->len = param_area->s+i - lump_upd->s;
01091 return 1;
01092 }
01093 }
01094 else {
01095 lump_del->len = 0;
01096 return 0;
01097 }
01098 }
01099 }
01100
01101
01102
01103
01104 static int find_hf_value2_param(struct hname_data* hname, str* param_area, str* value, str* lump_upd, str* lump_del, char* delim) {
01105 int i, j, k, found, comma_flag;
01106
01107 i = 0;
01108 *delim = 0;
01109 lump_del->len = 0;
01110 while (i < param_area->len) {
01111
01112 lump_del->s = param_area->s + i;
01113 while (i<param_area->len && is_space(param_area->s[i])) i++;
01114 comma_flag = i < param_area->len && param_area->s[i] == ',';
01115 if (comma_flag) i++;
01116 while (i<param_area->len && is_space(param_area->s[i])) i++;
01117
01118 if (i < param_area->len && is_alphanum(param_area->s[i])) {
01119 j = i;
01120 if (!*delim) *delim = ' ';
01121 while (i<param_area->len && is_alphanum(param_area->s[i])) i++;
01122
01123 k = i;
01124 while (i<param_area->len && is_space(param_area->s[i])) i++;
01125 lump_upd->s = param_area->s + i;
01126 if (i < param_area->len && param_area->s[i] == '=') {
01127 *delim = ',';
01128 i++;
01129 found = hname->param.len == k-j && !strncasecmp(hname->param.s, param_area->s+j, k-j);
01130 while (i<param_area->len && is_space(param_area->s[i])) i++;
01131
01132 value->s = param_area->s+i;
01133 value->len = 0;
01134 if (i < param_area->len) {
01135 if (param_area->s[i]=='\"') {
01136 i++;
01137 value->s++;
01138 for (; i<param_area->len; i++) {
01139 if (param_area->s[i]=='\"') {
01140 i++;
01141 break;
01142 }
01143 value->len++;
01144 }
01145 }
01146 else {
01147 for (; i<param_area->len && !is_space(param_area->s[i]) && param_area->s[i]!=','; i++, value->len++);
01148 }
01149 }
01150 if (found) {
01151 lump_upd->len = param_area->s+i - lump_upd->s;
01152 lump_del->len = param_area->s+i - lump_del->s;
01153
01154 while (i<param_area->len && is_space(param_area->s[i])) i++;
01155
01156 if (!comma_flag && i < param_area->len && param_area->s[i]==',') {
01157 i++;
01158 lump_del->len = param_area->s+i - lump_del->s;
01159 }
01160 return 1;
01161 }
01162 }
01163 while (i<param_area->len && is_space(param_area->s[i])) i++;
01164 }
01165 else {
01166 while (i<param_area->len && !is_space(param_area->s[i]) && !param_area->s[i]!=',') i++;
01167 }
01168 }
01169 lump_del->s = param_area->s + i;
01170 return 0;
01171 }
01172
01173 static int insert_header_lump(struct sip_msg* msg, char* msg_position, int lump_before, str* hname, str *val) {
01174 struct lump* anchor;
01175 char *s;
01176 int len;
01177
01178 anchor = anchor_lump(msg, msg_position - msg->buf, 0, 0);
01179 if (anchor == 0) {
01180 LOG(L_ERR, "ERROR: textops: insert_header_lump(): Can't get anchor\n");
01181 return -1;
01182 }
01183
01184 len=hname->len+2+val->len+2;
01185
01186 s = (char*)pkg_malloc(len);
01187 if (!s) {
01188 LOG(L_ERR, "ERROR: textops: insert_header_lump(): not enough memory\n");
01189 return -1;
01190 }
01191
01192 memcpy(s, hname->s, hname->len);
01193 s[hname->len] = ':';
01194 s[hname->len+1] = ' ';
01195 memcpy(s+hname->len+2, val->s, val->len);
01196 s[hname->len+2+val->len] = '\r';
01197 s[hname->len+2+val->len+1] = '\n';
01198
01199 if ( (lump_before?insert_new_lump_before(anchor, s, len, 0):insert_new_lump_after(anchor, s, len, 0)) == 0) {
01200 LOG(L_ERR, "ERROR: textops: insert_header_lump(): Can't insert lump\n");
01201 pkg_free(s);
01202 return -1;
01203 }
01204 return 1;
01205 }
01206
01207 static int insert_value_lump(struct sip_msg* msg, struct hdr_field* hf, char* msg_position, int lump_before, str *val) {
01208 struct lump* anchor;
01209 char *s;
01210 int len;
01211
01212 anchor = anchor_lump(msg, msg_position - msg->buf, 0, 0);
01213 if (anchor == 0) {
01214 LOG(L_ERR, "ERROR: textops: insert_value_lump(): Can't get anchor\n");
01215 return -1;
01216 }
01217
01218 len=val->len+1;
01219
01220 s = (char*)pkg_malloc(len);
01221 if (!s) {
01222 LOG(L_ERR, "ERROR: textops: insert_value_lump(): not enough memory\n");
01223 return -1;
01224 }
01225
01226 if (!hf) {
01227 memcpy(s, val->s, val->len);
01228 len--;
01229 }
01230 else if (msg_position == hf->body.s+hf->body.len) {
01231 s[0] = ',';
01232 memcpy(s+1, val->s, val->len);
01233 }
01234 else {
01235 memcpy(s, val->s, val->len);
01236 s[val->len] = ',';
01237 }
01238 if ( (lump_before?insert_new_lump_before(anchor, s, len, 0):insert_new_lump_after(anchor, s, len, 0)) == 0) {
01239 LOG(L_ERR, "ERROR: textops: insert_value_lump(): Can't insert lump\n");
01240 pkg_free(s);
01241 return -1;
01242 }
01243 return 1;
01244 }
01245
01246 static int delete_value_lump(struct sip_msg* msg, struct hdr_field* hf, str *val) {
01247 struct lump* l;
01248
01249 if (hf && val->s == hf->body.s && val->len == hf->body.len)
01250 l=del_lump(msg, hf->name.s-msg->buf, hf->len, 0);
01251 else
01252 l=del_lump(msg, val->s-msg->buf, val->len, 0);
01253 if (l==0) {
01254 LOG(L_ERR, "ERROR: textops: delete_value_lump: not enough memory\n");
01255 return -1;
01256 }
01257 return 1;
01258 }
01259
01260 static int incexc_hf_value_f(struct sip_msg* msg, char* _hname, char* _val) {
01261 struct hname_data* hname = (void*) _hname;
01262 struct hdr_field* hf, *lump_hf;
01263 str val, hval1, hval2;
01264 char *p;
01265 int res = eval_xlstr(msg, (void*) _val, &val);
01266 if (res < 0) return res;
01267 if (!val.len) return -1;
01268 hf = 0;
01269 lump_hf = 0;
01270 while (1) {
01271 if (find_next_hf(msg, hname, &hf) < 0) return -1;
01272 if (!hf) break;
01273 hval2.len = 0;
01274 p = hf->body.s;
01275 do {
01276 res = find_next_value(&p, hf->body.s+hf->body.len, &hval1, &hval2);
01277 if (hval1.len && val.len == hval1.len && strncasecmp(val.s, hval1.s, val.len) == 0) {
01278 switch (hname->oper) {
01279 case hnoIsIncluded:
01280 case hnoInclude:
01281 return 1;
01282 case hnoExclude:
01283 adjust_lump_val_for_delete(hf, &hval2);
01284 delete_value_lump(msg, hf, &hval2);
01285 default:
01286 break;
01287 }
01288 }
01289 } while (res);
01290 switch (hname->oper) {
01291 case hnoInclude:
01292 if (!lump_hf) {
01293 lump_hf = hf;
01294 }
01295 break;
01296 default:
01297 break;
01298 }
01299 }
01300 switch (hname->oper) {
01301 case hnoIsIncluded:
01302 return -1;
01303 case hnoInclude:
01304 if (lump_hf)
01305 return insert_value_lump(msg, lump_hf, lump_hf->body.s+lump_hf->body.len, 1, &val);
01306 else
01307 return insert_header_lump(msg, msg->unparsed, 1, &hname->hname, &val);
01308 default:
01309 return 1;
01310 }
01311 }
01312
01313 #define INCEXC_HF_VALUE_FIXUP(_func,_oper) \
01314 static int _func (void** param, int param_no) {\
01315 char* p = *param; \
01316 int res=fixup_hname_str(param, param_no); \
01317 if (res < 0) return res; \
01318 if (param_no == 1) {\
01319 if ( ((struct hname_data*)*param)->flags & HNF_IDX || ((struct hname_data*)*param)->param.len ) { \
01320 LOG(L_ERR, "ERROR: textops: neither index nor param may be specified in '%s'\n", p);\
01321 return E_CFG;\
01322 }\
01323 ((struct hname_data*)*param)->oper = _oper;\
01324 }\
01325 return 0;\
01326 }
01327
01328 INCEXC_HF_VALUE_FIXUP(include_hf_value_fixup, hnoInclude)
01329 INCEXC_HF_VALUE_FIXUP(exclude_hf_value_fixup, hnoExclude)
01330 INCEXC_HF_VALUE_FIXUP(hf_value_exists_fixup, hnoIsIncluded)
01331
01332 static void get_uri_and_skip_until_params(str *param_area, str *name, str *uri) {
01333 int i, quoted, uri_pos, uri_done;
01334
01335 name->len = 0;
01336 uri->len = 0;
01337 uri_done = 0;
01338 name->s = param_area->s;
01339 for (i=0; i<param_area->len && param_area->s[i]!=';'; ) {
01340
01341 for (quoted=0, uri_pos=i; i<param_area->len; i++) {
01342 if (!quoted) {
01343 if (param_area->s[i] == '\"') {
01344 quoted = 1;
01345 uri_pos = -1;
01346 }
01347 else if (param_area->s[i] == '<' || param_area->s[i] == ';' || is_space(param_area->s[i])) break;
01348 }
01349 else if (param_area->s[i] == '\"' && param_area->s[i-1] != '\\') quoted = 0;
01350 }
01351 if (!name->len)
01352 name->len = param_area->s+i-name->s;
01353 if (uri_pos >= 0 && !uri_done) {
01354 uri->s = param_area->s+uri_pos;
01355 uri->len = param_area->s+i-uri->s;
01356 }
01357
01358 while (i<param_area->len && is_space(param_area->s[i])) i++;
01359 if (i<param_area->len && param_area->s[i]=='<') {
01360 uri->s = param_area->s+i;
01361 uri->len = 0;
01362 for (quoted=0; i<param_area->len; i++) {
01363 if (!quoted) {
01364 if (param_area->s[i] == '\"') quoted = 1;
01365 else if (param_area->s[i] == '>') {
01366 uri->len = param_area->s+i-uri->s+1;
01367 uri_done = 1;
01368 break;
01369 }
01370 }
01371 else if (param_area->s[i] == '\"' && param_area->s[i-1] != '\\') quoted = 0;
01372 }
01373 }
01374 }
01375 param_area->s+= i;
01376 param_area->len-= i;
01377 if (uri->s == name->s)
01378 name->len = 0;
01379 }
01380
01381 static int assign_hf_do_lumping(struct sip_msg* msg,struct hdr_field* hf, struct hname_data* hname, str* value, int upd_del_fl, str* lump_upd, str* lump_del, char delim) {
01382 int len, i;
01383 char *s;
01384 struct lump* anchor;
01385
01386 if (upd_del_fl) {
01387 len = value?lump_upd->len:lump_del->len;
01388 if (len > 0) {
01389 if (!del_lump(msg, (value?lump_upd->s:lump_del->s)-msg->buf, len, 0)) {
01390 LOG(L_ERR, "ERROR: textops: assign_hf_do_lumping: not enough memory\n");
01391 return -1;
01392 }
01393 }
01394 if (value && value->len) {
01395 anchor = anchor_lump(msg, lump_upd->s - msg->buf, 0, 0);
01396 if (anchor == 0) {
01397 LOG(L_ERR, "ERROR: textops: assign_hf_do_lumping: Can't get anchor\n");
01398 return -1;
01399 }
01400
01401 len = 1+value->len;
01402 s = pkg_malloc(len);
01403 if (!s) {
01404 LOG(L_ERR, "ERROR: textops: assign_hf_do_lumping: not enough memory\n");
01405 return -1;
01406 }
01407 s[0]='=';
01408 memcpy(s+1, value->s, value->len);
01409 if ( (insert_new_lump_before(anchor, s, len, 0)) == 0) {
01410 LOG(L_ERR, "ERROR: textops: assign_hf_do_lumping: Can't insert lump\n");
01411 pkg_free(s);
01412 return -1;
01413 }
01414 }
01415 }
01416 else {
01417 if (!value) return -1;
01418
01419 anchor = anchor_lump(msg, lump_del->s - msg->buf, 0, 0);
01420 if (anchor == 0) {
01421 LOG(L_ERR, "ERROR: textops: assign_hf_do_lumping: Can't get anchor\n");
01422 return -1;
01423 }
01424
01425 len = 1+hname->param.len+(value->len?value->len+1:0);
01426 s = pkg_malloc(len);
01427 if (!s) {
01428 LOG(L_ERR, "ERROR: textops: assign_hf_do_lumping: not enough memory\n");
01429 return -1;
01430 }
01431 if (delim) {
01432 s[0] = delim;
01433 i = 1;
01434 }
01435 else {
01436 i = 0;
01437 len--;
01438 }
01439 memcpy(s+i, hname->param.s, hname->param.len);
01440 if (value->len) {
01441 s[hname->param.len+i]='=';
01442 memcpy(s+i+hname->param.len+1, value->s, value->len);
01443 }
01444
01445 if ( (insert_new_lump_before(anchor, s, len, 0)) == 0) {
01446 LOG(L_ERR, "ERROR: textops: assign_hf_do_lumping: Can't insert lump\n");
01447 pkg_free(s);
01448 return -1;
01449 }
01450 }
01451 return 1;
01452 }
01453
01454
01455 static int assign_hf_process_params(struct sip_msg* msg, struct hdr_field* hf, struct hname_data* hname, str* value, str* value_area) {
01456 int r, r2, res=0;
01457 str param_area, lump_upd, lump_del, dummy_val, dummy_name, dummy_uri;
01458 param_area = *value_area;
01459 get_uri_and_skip_until_params(¶m_area, &dummy_name, &dummy_uri);
01460 do {
01461 r = find_hf_value_param(hname, ¶m_area, &dummy_val, &lump_upd, &lump_del);
01462 r2 = assign_hf_do_lumping(msg, hf, hname, value, r, &lump_upd, &lump_del, ';');
01463 if (res == 0)
01464 res = r2;
01465 if (r && !value) {
01466 param_area.len -= lump_del.s+lump_del.len-param_area.s;
01467 param_area.s = lump_del.s+lump_del.len;
01468 }
01469 } while (!value && r);
01470 return res;
01471 }
01472
01473 static int assign_hf_process2_params(struct sip_msg* msg, struct hdr_field* hf, struct hname_data* hname, str* value) {
01474 int r, r2, res = 0;
01475 str param_area, lump_upd, lump_del, dummy_val;
01476 char delim;
01477
01478 param_area = hf->body;
01479
01480 do {
01481 r = find_hf_value2_param(hname, ¶m_area, &dummy_val, &lump_upd, &lump_del, &delim);
01482 r2 = assign_hf_do_lumping(msg, hf, hname, value, r, &lump_upd, &lump_del, delim);
01483 if (res == 0)
01484 res = r2;
01485 if (r && !value) {
01486 param_area.len -= lump_del.s+lump_del.len-param_area.s;
01487 param_area.s = lump_del.s+lump_del.len;
01488 }
01489 } while (!value && r);
01490 return res;
01491
01492 }
01493
01494 static int insupddel_hf_value_f(struct sip_msg* msg, char* _hname, char* _val) {
01495 struct hname_data* hname = (void*) _hname;
01496 struct hdr_field* hf;
01497 str val, hval1, hval2;
01498 int res;
01499
01500 if (_val) {
01501 res = eval_xlstr(msg, (void*) _val, &val);
01502 if (res < 0) return res;
01503 }
01504 switch (hname->oper) {
01505 case hnoAppend:
01506 if ((hname->flags & HNF_IDX) == 0) {
01507 if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
01508 LOG(L_ERR, "ERROR: textops: Error while parsing message\n");
01509 return -1;
01510 }
01511 return insert_header_lump(msg, msg->unparsed, 1, &hname->hname, &val);
01512 }
01513 else {
01514 res = find_hf_value_idx(msg, hname, &hf, &hval1, &hval2);
01515 if (res < 0) return res;
01516 if (hf) {
01517 return insert_value_lump(msg, hf, hval2.s+hval2.len, res , &val);
01518 }
01519 else {
01520 return insert_header_lump(msg, msg->unparsed, 1, &hname->hname, &val);
01521 }
01522 }
01523 case hnoInsert:
01524
01525 res = find_hf_value_idx(msg, hname, &hf, &hval1, &hval2);
01526 if (res < 0) return res;
01527 if (hf && (hname->flags & HNF_IDX) == 0) {
01528 return insert_header_lump(msg, hf->name.s, 1, &hname->hname, &val);
01529 }
01530 else if (!hf && hname->idx == 1) {
01531 return insert_header_lump(msg, msg->unparsed, 1, &hname->hname, &val);
01532 }
01533 else if (hf) {
01534 return insert_value_lump(msg, hf, hval2.s, 1, &val);
01535 }
01536 else
01537 return -1;
01538
01539 case hnoRemove:
01540 case hnoAssign:
01541 if (hname->flags & HNF_ALL) {
01542 struct hdr_field* hf = 0;
01543 int fl = -1;
01544 do {
01545 res = find_next_hf(msg, hname, &hf);
01546 if (res < 0) return res;
01547 if (hf) {
01548 if (!hname->param.len) {
01549 fl = 1;
01550 delete_value_lump(msg, hf, &hf->body);
01551 }
01552 else {
01553 char *p;
01554 hval2.len = 0;
01555 p = hf->body.s;
01556 do {
01557 res = find_next_value(&p, hf->body.s+hf->body.len, &hval1, &hval2);
01558 if (assign_hf_process_params(msg, hf, hname, _val?&val:0, &hval1) > 0)
01559 fl = 1;
01560 } while (res);
01561 }
01562 }
01563 } while (hf);
01564 return fl;
01565 }
01566 else {
01567 res = find_hf_value_idx(msg, hname, &hf, &hval1, &hval2);
01568 if (res < 0) return res;
01569 if (hf) {
01570 if (!hname->param.len) {
01571 if (hname->oper == hnoRemove) {
01572 adjust_lump_val_for_delete(hf, &hval2);
01573 return delete_value_lump(msg, hf, &hval2);
01574 }
01575 else {
01576 res = delete_value_lump(msg, 0 , &hval1);
01577 if (res < 0) return res;
01578 if (val.len) {
01579 return insert_value_lump(msg, 0 , hval1.s, 1, &val);
01580 }
01581 return 1;
01582 }
01583 }
01584 else {
01585 return assign_hf_process_params(msg, hf, hname, _val?&val:0, &hval1);
01586 }
01587 }
01588 }
01589 break;
01590 case hnoRemove2:
01591 case hnoAssign2:
01592 if (hname->flags & HNF_ALL) {
01593 struct hdr_field* hf = 0;
01594 int fl = -1;
01595 do {
01596 res = find_next_hf(msg, hname, &hf);
01597 if (res < 0) return res;
01598 if (hf) {
01599 if (!hname->param.len) {
01600 fl = 1;
01601 delete_value_lump(msg, hf, &hf->body);
01602 }
01603 else {
01604
01605 if (assign_hf_process2_params(msg, hf, hname, _val?&val:0) > 0)
01606 fl = 1;
01607 }
01608 }
01609 } while (hf);
01610 return fl;
01611 }
01612 else {
01613 res = find_hf_value_idx(msg, hname, &hf, 0, 0);
01614 if (res < 0) return res;
01615 if (hf) {
01616 if (!hname->param.len) {
01617 if (hname->oper == hnoRemove2) {
01618 return delete_value_lump(msg, hf, &hf->body);
01619 }
01620 else {
01621 res = delete_value_lump(msg, 0 , &hf->body);
01622 if (res < 0) return res;
01623 if (val.len) {
01624 return insert_value_lump(msg, 0 , hf->body.s, 1, &val);
01625 }
01626 return 1;
01627 }
01628 }
01629 else {
01630 return assign_hf_process2_params(msg, hf, hname, _val?&val:0);
01631 }
01632 }
01633 }
01634 break;
01635 }
01636 return -1;
01637 }
01638
01639 static int append_hf_value_fixup(void** param, int param_no) {
01640 int res=fixup_hname_str(param, param_no);
01641 if (res < 0) return res;
01642 if (param_no == 1) {
01643 if ( ((struct hname_data*)*param)->flags & HNF_ALL ) {
01644 LOG(L_ERR, "ERROR: textops: asterisk not supported\n");
01645 return E_CFG;
01646 } else if ( (((struct hname_data*)*param)->flags & HNF_IDX) == 0 || !((struct hname_data*)*param)->idx ) {
01647 ((struct hname_data*)*param)->idx = -1;
01648 }
01649 if (((struct hname_data*)*param)->idx < -MAX_HF_VALUE_STACK) {
01650 LOG(L_ERR, "ERROR: textops: index cannot be lower than %d\n", -MAX_HF_VALUE_STACK);
01651 return E_CFG;
01652 }
01653 if ( ((struct hname_data*)*param)->param.len ) {
01654 LOG(L_ERR, "ERROR: textops: param not supported\n");
01655 return E_CFG;
01656 }
01657 ((struct hname_data*)*param)->oper = hnoAppend;
01658 }
01659 return 0;
01660 }
01661
01662 static int insert_hf_value_fixup(void** param, int param_no) {
01663 int res=fixup_hname_str(param, param_no);
01664 if (res < 0) return res;
01665 if (param_no == 1) {
01666 if ( ((struct hname_data*)*param)->flags & HNF_ALL ) {
01667 LOG(L_ERR, "ERROR: textops: asterisk not supported\n");
01668 return E_CFG;
01669 } else if ( (((struct hname_data*)*param)->flags & HNF_IDX) == 0 || !((struct hname_data*)*param)->idx ) {
01670 ((struct hname_data*)*param)->idx = 1;
01671 }
01672 if (((struct hname_data*)*param)->idx < -MAX_HF_VALUE_STACK) {
01673 LOG(L_ERR, "ERROR: textops: index cannot be lower than %d\n", -MAX_HF_VALUE_STACK);
01674 return E_CFG;
01675 }
01676 if ( ((struct hname_data*)*param)->param.len ) {
01677 LOG(L_ERR, "ERROR: textops: param not supported\n");
01678 return E_CFG;
01679 }
01680 ((struct hname_data*)*param)->oper = hnoInsert;
01681 }
01682 return 0;
01683 }
01684
01685 static int remove_hf_value_fixup(void** param, int param_no) {
01686 int res=fixup_hname_str(param, param_no);
01687 if (res < 0) return res;
01688 if (param_no == 1) {
01689 if ( (((struct hname_data*)*param)->flags & HNF_IDX) == 0 || !((struct hname_data*)*param)->idx ) {
01690 ((struct hname_data*)*param)->idx = 1;
01691 ((struct hname_data*)*param)->flags |= HNF_IDX;
01692 }
01693 if (((struct hname_data*)*param)->idx < -MAX_HF_VALUE_STACK) {
01694 LOG(L_ERR, "ERROR: textops: index cannot be lower than %d\n", -MAX_HF_VALUE_STACK);
01695 return E_CFG;
01696 }
01697 ((struct hname_data*)*param)->oper = hnoRemove;
01698 }
01699 return 0;
01700 }
01701
01702 static int assign_hf_value_fixup(void** param, int param_no) {
01703 int res=fixup_hname_str(param, param_no);
01704 if (res < 0) return res;
01705 if (param_no == 1) {
01706 if ( (((struct hname_data*)*param)->flags & HNF_ALL) && !((struct hname_data*)*param)->param.len) {
01707 LOG(L_ERR, "ERROR: textops: asterisk not supported without param\n");
01708 return E_CFG;
01709 } else if ( (((struct hname_data*)*param)->flags & HNF_IDX) == 0 || !((struct hname_data*)*param)->idx ) {
01710 ((struct hname_data*)*param)->idx = 1;
01711 ((struct hname_data*)*param)->flags |= HNF_IDX;
01712 }
01713 if (((struct hname_data*)*param)->idx < -MAX_HF_VALUE_STACK) {
01714 LOG(L_ERR, "ERROR: textops: index cannot be lower than %d\n", -MAX_HF_VALUE_STACK);
01715 return E_CFG;
01716 }
01717 ((struct hname_data*)*param)->oper = hnoAssign;
01718 }
01719 return 0;
01720 }
01721
01722 static int remove_hf_value2_fixup(void** param, int param_no) {
01723 int res=remove_hf_value_fixup(param, param_no);
01724 if (res < 0) return res;
01725 if (param_no == 1) {
01726 ((struct hname_data*)*param)->oper = hnoRemove2;
01727 }
01728 return 0;
01729 }
01730
01731 static int assign_hf_value2_fixup(void** param, int param_no) {
01732 int res=assign_hf_value_fixup(param, param_no);
01733 if (res < 0) return res;
01734 if (param_no == 1) {
01735 ((struct hname_data*)*param)->oper = hnoAssign2;
01736 }
01737 return 0;
01738 }
01739
01740 static int sel_hf_value(str* res, select_t* s, struct sip_msg* msg) {
01741 return 0;
01742 }
01743
01744 #define _ALLOC_INC_SIZE 1024
01745
01746 static int sel_hf_value_name(str* res, select_t* s, struct sip_msg* msg) {
01747 struct hname_data* hname;
01748 struct hdr_field* hf;
01749 str val, hval1, hval2, huri, dummy_name;
01750 int r;
01751 if (!msg) {
01752 struct hdr_field hdr;
01753 char buf[50];
01754 int i, n;
01755
01756 if (s->params[1].type == SEL_PARAM_STR) {
01757 hname = pkg_malloc(sizeof(*hname));
01758 if (!hname) return E_OUT_OF_MEM;
01759 memset(hname, 0, sizeof(*hname));
01760
01761 for (i=s->params[1].v.s.len-1; i>0; i--) {
01762 if (s->params[1].v.s.s[i]=='_')
01763 s->params[1].v.s.s[i]='-';
01764 }
01765 i = snprintf(buf, sizeof(buf)-1, "%.*s: X\n", s->params[1].v.s.len, s->params[1].v.s.s);
01766 buf[i] = 0;
01767
01768 hname->hname = s->params[1].v.s;
01769 parse_hname2(buf, buf+i, &hdr);
01770
01771 if (hdr.type == HDR_ERROR_T) return E_CFG;
01772 hname->htype = hdr.type;
01773
01774 s->params[1].v.p = hname;
01775 s->params[1].type = SEL_PARAM_PTR;
01776 }
01777 else {
01778 hname = s->params[1].v.p;
01779 }
01780 n = s->param_offset[select_level+1] - s->param_offset[select_level];
01781 if (n > 2 && s->params[2].type == SEL_PARAM_INT) {
01782 hname->idx = s->params[2].v.i;
01783 hname->flags |= HNF_IDX;
01784 if (hname->idx < -MAX_HF_VALUE_STACK) {
01785 LOG(L_ERR, "ERROR: textops: index cannot be lower than %d\n", -MAX_HF_VALUE_STACK);
01786 return E_CFG;
01787 }
01788 if (hname->idx == 0)
01789 hname->idx = 1;
01790 i = 3;
01791 }
01792 else {
01793 i = 2;
01794 hname->idx = 1;
01795 }
01796 if (n > i && s->params[i].type == SEL_PARAM_STR) {
01797 hname->param = s->params[i].v.s;
01798 for (i=hname->param.len-1; i>0; i--) {
01799 if (hname->param.s[i]=='_')
01800 hname->param.s[i]='-';
01801 }
01802
01803 }
01804 s->params[1].v.p = hname;
01805 s->params[1].type = SEL_PARAM_PTR;
01806 hname->oper = hnoGetValue;
01807
01808 return 0;
01809 }
01810
01811 res->len = 0;
01812 res->s = 0;
01813 hname = s->params[1].v.p;
01814
01815 switch (hname->oper) {
01816 case hnoGetValueUri:
01817 if (hname->flags & HNF_ALL || (hname->flags & HNF_IDX) == 0) {
01818 char *buf = NULL;
01819 int buf_len = 0;
01820
01821 hf = 0;
01822 do {
01823 r = find_next_hf(msg, hname, &hf);
01824 if (r < 0) break;
01825 if (hf) {
01826 char *p;
01827 str huri;
01828 hval2.len = 0;
01829 p = hf->body.s;
01830 do {
01831 r = find_next_value(&p, hf->body.s+hf->body.len, &hval1, &hval2);
01832 get_uri_and_skip_until_params(&hval1, &dummy_name, &huri);
01833 if (huri.len) {
01834
01835 if (*huri.s == '<') {
01836 huri.s++;
01837 huri.len -= 2;
01838 }
01839 }
01840 if (res->len == 0) {
01841 *res = huri;
01842 }
01843 else {
01844 if (buf) {
01845 if (res->len+huri.len+1 > buf_len) {
01846 buf_len = res->len+huri.len+1+_ALLOC_INC_SIZE;
01847 res->s = pkg_realloc(buf, buf_len);
01848 if (!res->s) {
01849 pkg_free(buf);
01850 LOG(L_ERR, "ERROR: textops: cannot realloc buffer\n");
01851 res->len = 0;
01852 return E_OUT_OF_MEM;
01853 }
01854 buf = res->s;
01855 }
01856 }
01857 else {
01858
01859 buf_len = res->len+huri.len+1+_ALLOC_INC_SIZE;
01860 buf = pkg_malloc(buf_len);
01861 if (!buf) {
01862 LOG(L_ERR, "ERROR: testops: out of memory\n");
01863 res->len = 0;
01864 return E_OUT_OF_MEM;
01865 }
01866
01867 memcpy(buf, res->s, res->len);
01868 res->s = buf;
01869 }
01870 res->s[res->len] = ',';
01871 res->len++;
01872 if (huri.len) {
01873 memcpy(res->s+res->len, huri.s, huri.len);
01874 res->len += huri.len;
01875 }
01876 }
01877
01878 } while (r);
01879 }
01880 } while (hf);
01881 if (buf) {
01882 res->s = get_static_buffer(res->len);
01883 if (!res->s) {
01884 pkg_free(buf);
01885 res->len = 0;
01886 LOG(L_ERR, "ERROR: testops: cannot allocate static buffer\n");
01887 return E_OUT_OF_MEM;
01888 }
01889 memcpy(res->s, buf, res->len);
01890 pkg_free(buf);
01891 }
01892 }
01893 else {
01894 r = find_hf_value_idx(msg, hname, &hf, &hval1, &hval2);
01895 if (r > 0) {
01896 get_uri_and_skip_until_params(&hval1, &dummy_name, res);
01897 if (res->len && *res->s == '<') {
01898 res->s++;
01899 res->len-=2;
01900 }
01901 }
01902 }
01903 break;
01904 case hnoGetValueName:
01905 if ((hname->flags & HNF_ALL) == 0) {
01906 r = find_hf_value_idx(msg, hname, &hf, &hval1, &hval2);
01907 if (r > 0) {
01908 get_uri_and_skip_until_params(&hval1, res, &dummy_name);
01909 if (res->len >= 2 && res->s[0] == '\"' && res->s[res->len-1]=='\"' ) {
01910 res->s++;
01911 res->len-=2;
01912 }
01913 }
01914 }
01915 break;
01916 case hnoGetValue:
01917 if (hname->flags & HNF_ALL || (hname->flags & HNF_IDX) == 0) {
01918 char *buf = NULL;
01919 int buf_len = 0;
01920
01921 hf = 0;
01922 do {
01923 r = find_next_hf(msg, hname, &hf);
01924
01925 if (r < 0) break;
01926 if (hf) {
01927 char *p;
01928 hval2.len = 0;
01929 p = hf->body.s;
01930 do {
01931 r = find_next_value(&p, hf->body.s+hf->body.len, &hval1, &hval2);
01932 if (res->len == 0) {
01933 *res = hval1;
01934 }
01935 else {
01936 if (buf) {
01937 if (res->len+hval1.len+1 > buf_len) {
01938 buf_len = res->len+hval1.len+1+_ALLOC_INC_SIZE;
01939 res->s = pkg_realloc(buf, buf_len);
01940 if (!res->s) {
01941 pkg_free(buf);
01942 LOG(L_ERR, "ERROR: textops: cannot realloc buffer\n");
01943 res->len = 0;
01944 return E_OUT_OF_MEM;
01945 }
01946 buf = res->s;
01947 }
01948 }
01949 else {
01950
01951 buf_len = res->len+hval1.len+1+_ALLOC_INC_SIZE;
01952 buf = pkg_malloc(buf_len);
01953 if (!buf) {
01954 LOG(L_ERR, "ERROR: testops: out of memory\n");
01955 res->len = 0;
01956 return E_OUT_OF_MEM;
01957 }
01958
01959 memcpy(buf, res->s, res->len);
01960 res->s = buf;
01961 }
01962 res->s[res->len] = ',';
01963 res->len++;
01964 if (hval1.len) {
01965 memcpy(res->s+res->len, hval1.s, hval1.len);
01966 res->len += hval1.len;
01967 }
01968 }
01969 } while (r);
01970 }
01971 } while (hf);
01972 if (buf) {
01973 res->s = get_static_buffer(res->len);
01974 if (!res->s) {
01975 pkg_free(buf);
01976 res->len = 0;
01977 LOG(L_ERR, "ERROR: testops: cannot allocate static buffer\n");
01978 return E_OUT_OF_MEM;
01979 }
01980 memcpy(res->s, buf, res->len);
01981 pkg_free(buf);
01982 }
01983 }
01984 else {
01985 r = find_hf_value_idx(msg, hname, &hf, &hval1, &hval2);
01986 if (r > 0) {
01987 if (hname->param.len) {
01988 str d1, d2;
01989 get_uri_and_skip_until_params(&hval1, &dummy_name, &huri);
01990 if (find_hf_value_param(hname, &hval1, &val, &d1, &d2)) {
01991 *res = val;
01992 }
01993 }
01994 else {
01995 *res = hval1;
01996 }
01997 }
01998 }
01999 break;
02000 case hnoGetValue2:
02001 r = find_hf_value_idx(msg, hname, &hf, 0, 0);
02002 if (r > 0) {
02003 if (hname->param.len) {
02004 str d1, d2;
02005 char c;
02006 if (find_hf_value2_param(hname, &hf->body, &val, &d1, &d2, &c)) {
02007 *res = val;
02008 }
02009 }
02010 else {
02011 *res = hf->body;
02012 }
02013 }
02014 break;
02015 default:
02016 break;
02017 }
02018 return 0;
02019 }
02020
02021 static int sel_hf_value_name_param_name(str* res, select_t* s, struct sip_msg* msg) {
02022 return sel_hf_value_name(res, s, msg);
02023 }
02024
02025 static int sel_hf_value_name_param_name2(str* res, select_t* s, struct sip_msg* msg) {
02026 if (!msg) {
02027 int n;
02028 n = s->param_offset[select_level+1] - s->param_offset[select_level];
02029 s->params[n-2] = s->params[n-1];
02030 }
02031 return sel_hf_value_name(res, s, msg);
02032 }
02033
02034 static int sel_hf_value_name_uri(str* res, select_t* s, struct sip_msg* msg) {
02035 int r;
02036 r = sel_hf_value_name(res, s, msg);
02037 if (!msg && r==0) {
02038 ((struct hname_data*) s->params[1].v.p)->oper = hnoGetValueUri;
02039 }
02040 return r;
02041 }
02042
02043 static int sel_hf_value_name_name(str* res, select_t* s, struct sip_msg* msg) {
02044 int r;
02045 r = sel_hf_value_name(res, s, msg);
02046 if (!msg && r==0) {
02047 ((struct hname_data*) s->params[1].v.p)->oper = hnoGetValueName;
02048 }
02049 return r;
02050 }
02051
02052 static int sel_hf_value_exists(str* res, select_t* s, struct sip_msg* msg) {
02053 return 0;
02054 }
02055
02056 static int sel_hf_value_exists_param(str* res, select_t* s, struct sip_msg* msg) {
02057 static char ret_val[] = "01";
02058 struct xlstr xlstr;
02059 int r;
02060
02061 if (!msg) {
02062 r = sel_hf_value_name(res, s, msg);
02063 if (r == 0)
02064 ((struct hname_data*) s->params[1].v.p)->oper = hnoIsIncluded;
02065 return r;
02066 }
02067 xlstr.s = s->params[2].v.s;
02068 xlstr.xlfmt = 0;
02069 r = incexc_hf_value_f(msg, s->params[1].v.p, (void*) &xlstr);
02070 res->s = &ret_val[r > 0];
02071 res->len = 1;
02072
02073 return 0;
02074 }
02075
02076 static int sel_hf_value2(str* res, select_t* s, struct sip_msg* msg) {
02077 return 0;
02078 }
02079
02080 static int sel_hf_value2_name(str* res, select_t* s, struct sip_msg* msg) {
02081 int r;
02082 r = sel_hf_value_name(res, s, msg);
02083 if (!msg && r==0) {
02084 ((struct hname_data*) s->params[1].v.p)->oper = hnoGetValue2;
02085 }
02086 return r;
02087 }
02088
02089 static int sel_hf_value2_name_param_name(str* res, select_t* s, struct sip_msg* msg) {
02090 return sel_hf_value2_name(res, s, msg);
02091 }
02092
02093 SELECT_F(select_any_nameaddr)
02094 SELECT_F(select_any_uri)
02095 SELECT_F(select_anyheader_params)
02096
02097 select_row_t sel_declaration[] = {
02098 { NULL, SEL_PARAM_STR, STR_STATIC_INIT("hf_value"), sel_hf_value, SEL_PARAM_EXPECTED},
02099
02100 { sel_hf_value, SEL_PARAM_STR, STR_NULL, sel_hf_value_name, CONSUME_NEXT_INT | OPTIONAL | FIXUP_CALL},
02101 { sel_hf_value_name, SEL_PARAM_STR, STR_STATIC_INIT("param"), sel_hf_value_name_param_name2, CONSUME_NEXT_STR | FIXUP_CALL},
02102 { sel_hf_value_name, SEL_PARAM_STR, STR_STATIC_INIT("p"), sel_hf_value_name_param_name2, CONSUME_NEXT_STR | FIXUP_CALL},
02103 { sel_hf_value_name, SEL_PARAM_STR, STR_STATIC_INIT("uri"), sel_hf_value_name_uri, FIXUP_CALL},
02104 { sel_hf_value_name, SEL_PARAM_STR, STR_STATIC_INIT("name"), sel_hf_value_name_name, FIXUP_CALL},
02105 { sel_hf_value_name, SEL_PARAM_STR, STR_STATIC_INIT("nameaddr"), select_any_nameaddr, NESTED | CONSUME_NEXT_STR},
02106 { sel_hf_value_name, SEL_PARAM_STR, STR_STATIC_INIT("params"), select_anyheader_params, NESTED},
02107
02108 { sel_hf_value_name_uri, SEL_PARAM_INT, STR_NULL, select_any_uri, NESTED},
02109 { sel_hf_value_name, SEL_PARAM_STR, STR_NULL, sel_hf_value_name_param_name, FIXUP_CALL},
02110
02111 { NULL, SEL_PARAM_STR, STR_STATIC_INIT("hf_value_exists"), sel_hf_value_exists, CONSUME_NEXT_STR | SEL_PARAM_EXPECTED},
02112 { sel_hf_value_exists, SEL_PARAM_STR, STR_NULL, sel_hf_value_exists_param, FIXUP_CALL},
02113
02114 { NULL, SEL_PARAM_STR, STR_STATIC_INIT("hf_value2"), sel_hf_value2, SEL_PARAM_EXPECTED},
02115 { sel_hf_value2, SEL_PARAM_STR, STR_NULL, sel_hf_value2_name, CONSUME_NEXT_INT | OPTIONAL | FIXUP_CALL},
02116 { sel_hf_value2_name, SEL_PARAM_STR, STR_STATIC_INIT("params"), select_anyheader_params, NESTED},
02117 { sel_hf_value2_name, SEL_PARAM_STR, STR_NULL, sel_hf_value2_name_param_name, FIXUP_CALL},
02118 { sel_hf_value2_name_param_name, SEL_PARAM_STR, STR_STATIC_INIT("nameaddr"), select_any_nameaddr, NESTED},
02119 { sel_hf_value2_name_param_name, SEL_PARAM_STR, STR_STATIC_INIT("uri"), select_any_uri, NESTED},
02120
02121 { NULL, SEL_PARAM_INT, STR_NULL, NULL, 0}
02122 };