textops.c

Go to the documentation of this file.
00001 /*$Id: textops.c 5551 2009-02-02 10:40:53Z henningw $
00002  *
00003  * Copyright (C) 2001-2003 FhG Fokus
00004  *
00005  * This file is part of Kamailio, a free SIP server.
00006  *
00007  * Kamailio is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version
00011  *
00012  * Kamailio is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License 
00018  * along with this program; if not, write to the Free Software 
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  *
00021  *
00022  * History:
00023  * -------
00024  *  2003-02-28  scratchpad compatibility abandoned (jiri)
00025  *  2003-01-29: - rewriting actions (replace, search_append) now begin
00026  *                at the second line -- previously, they could affect
00027  *                first line too, which resulted in wrong calculation of
00028  *                forwarded requests and an error consequently
00029  *              - replace_all introduced
00030  *  2003-01-28  scratchpad removed (jiri)
00031  *  2003-01-18  append_urihf introduced (jiri)
00032  *  2003-03-10  module export interface updated to the new format (andrei)
00033  *  2003-03-16  flags export parameter added (janakj)
00034  *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
00035  *  2003-04-97  actions permitted to be used from failure/reply routes (jiri)
00036  *  2003-04-21  remove_hf and is_present_hf introduced (jiri)
00037  *  2003-08-19  subst added (support for sed like res:s/re/repl/flags) (andrei)
00038  *  2003-08-20  subst_uri added (like above for uris) (andrei)
00039  *  2003-09-11  updated to new build_lump_rpl() interface (bogdan)
00040  *  2003-11-11: build_lump_rpl() removed, add_lump_rpl() has flags (bogdan)
00041  *  2004-05-09: append_time introduced (jiri)
00042  *  2004-07-06  subst_user added (like subst_uri but only for user) (sobomax)
00043  *  2004-11-12  subst_user changes (old serdev mails) (andrei)
00044  *  2005-07-05  is_method("name") to check method using id (ramona)
00045  *  2006-03-17  applied patch from Marc Haisenko <haisenko@comdasys.com> 
00046  *              for adding has_body() function (bogdan)
00047  *  2008-07-14  Moved some function declarations to a separate file (Ardjan Zwartjes) 
00048  *
00049  */
00050 
00051 
00052 #include "../../action.h"
00053 #include "../../sr_module.h"
00054 #include "../../dprint.h"
00055 #include "../../data_lump.h"
00056 #include "../../data_lump_rpl.h"
00057 #include "../../error.h"
00058 #include "../../mem/mem.h"
00059 #include "../../str.h"
00060 #include "../../re.h"
00061 #include "../../mod_fix.h"
00062 #include "../../parser/parse_uri.h"
00063 #include "../../parser/parse_hname2.h"
00064 #include "../../parser/parse_methods.h"
00065 #include "../../parser/parse_content.h"
00066 #include "../../parser/parse_privacy.h"
00067 #include "../../mod_fix.h"
00068 #include "../../ut.h"
00069 #include "../../cmpapi.h"
00070 #include <stdio.h>
00071 #include <stdlib.h>
00072 #include <string.h>
00073 #include <sys/types.h> /* for regex */
00074 #include <regex.h>
00075 #include <time.h>
00076 #include <sys/time.h>
00077 
00078 #include "textops.h"
00079 #include "txt_var.h"
00080 #include "api.h"
00081 
00082 MODULE_VERSION
00083 
00084 
00085 /* RFC822-conforming dates format:
00086 
00087    %a -- abbreviated week of day name (locale), %d day of month
00088    as decimal number, %b abbreviated month name (locale), %Y
00089    year with century, %T time in 24h notation
00090 */
00091 #define TIME_FORMAT "Date: %a, %d %b %Y %H:%M:%S GMT"
00092 #define MAX_TIME 64
00093 
00094 
00095 static int search_body_f(struct sip_msg*, char*, char*);
00096 static int replace_f(struct sip_msg*, char*, char*);
00097 static int replace_body_f(struct sip_msg*, char*, char*);
00098 static int replace_all_f(struct sip_msg*, char*, char*);
00099 static int replace_body_all_f(struct sip_msg*, char*, char*);
00100 static int replace_body_atonce_f(struct sip_msg*, char*, char*);
00101 static int subst_f(struct sip_msg*, char*, char*);
00102 static int subst_uri_f(struct sip_msg*, char*, char*);
00103 static int subst_user_f(struct sip_msg*, char*, char*);
00104 static int subst_body_f(struct sip_msg*, char*, char*);
00105 static int filter_body_f(struct sip_msg*, char*, char*);
00106 static int is_present_hf_f(struct sip_msg* msg, char* str_hf, char* foo);
00107 static int search_append_body_f(struct sip_msg*, char*, char*);
00108 static int append_to_reply_f(struct sip_msg* msg, char* key, char* str);
00109 static int append_hf_1(struct sip_msg* msg, char* str1, char* str2);
00110 static int append_hf_2(struct sip_msg* msg, char* str1, char* str2);
00111 static int insert_hf_1(struct sip_msg* msg, char* str1, char* str2);
00112 static int insert_hf_2(struct sip_msg* msg, char* str1, char* str2);
00113 static int append_urihf(struct sip_msg* msg, char* str1, char* str2);
00114 static int append_time_f(struct sip_msg* msg, char* , char *);
00115 static int set_body_f(struct sip_msg* msg, char*, char *);
00116 static int set_rpl_body_f(struct sip_msg* msg, char*, char *);
00117 static int is_method_f(struct sip_msg* msg, char* , char *);
00118 static int has_body_f(struct sip_msg *msg, char *type, char *str2 );
00119 static int is_privacy_f(struct sip_msg *msg, char *privacy, char *str2 );
00120 static int cmp_str_f(struct sip_msg *msg, char *str1, char *str2 );
00121 static int cmp_istr_f(struct sip_msg *msg, char *str1, char *str2 );
00122 static int remove_hf_re_f(struct sip_msg* msg, char* key, char* foo);
00123 static int is_present_hf_re_f(struct sip_msg* msg, char* key, char* foo);
00124 
00125 static int fixup_substre(void**, int);
00126 static int hname_fixup(void** param, int param_no);
00127 static int free_hname_fixup(void** param, int param_no);
00128 static int fixup_method(void** param, int param_no);
00129 static int add_header_fixup(void** param, int param_no);
00130 static int fixup_body_type(void** param, int param_no);
00131 static int fixup_privacy(void** param, int param_no);
00132 
00133 static int mod_init(void);
00134 
00135 static tr_export_t mod_trans[] = {
00136    { {"re", sizeof("re")-1}, /* regexp class */
00137       tr_txt_parse_re },
00138 
00139    { { 0, 0 }, 0 }
00140 };
00141 
00142 static cmd_export_t cmds[]={
00143    {"search",           (cmd_function)search_f,          1,
00144       fixup_regexp_null, fixup_free_regexp_null,
00145       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00146    {"search_body",      (cmd_function)search_body_f,     1,
00147       fixup_regexp_null, fixup_free_regexp_null,
00148       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00149    {"search_append",    (cmd_function)search_append_f,   2,
00150       fixup_regexp_none,fixup_free_regexp_none,
00151       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00152    {"search_append_body", (cmd_function)search_append_body_f,   2,
00153       fixup_regexp_none, fixup_free_regexp_none, 
00154       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00155    {"replace",          (cmd_function)replace_f,         2,
00156       fixup_regexp_none, fixup_free_regexp_none,
00157       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00158    {"replace_body",     (cmd_function)replace_body_f,    2,
00159       fixup_regexp_none, fixup_free_regexp_none,
00160       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00161    {"replace_all",      (cmd_function)replace_all_f,     2,
00162       fixup_regexp_none, fixup_free_regexp_none,
00163       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00164    {"replace_body_all", (cmd_function)replace_body_all_f,2,
00165       fixup_regexp_none, fixup_free_regexp_none,
00166       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00167    {"replace_body_atonce", (cmd_function)replace_body_atonce_f,2,
00168       fixup_regexpNL_none, fixup_free_regexp_none,
00169       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00170    {"append_to_reply",  (cmd_function)append_to_reply_f, 1,
00171       fixup_spve_null, 0,
00172       REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ERROR_ROUTE},
00173    {"append_hf",        (cmd_function)append_hf_1,       1,
00174       add_header_fixup, 0,
00175       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00176    {"append_hf",        (cmd_function)append_hf_2,       2,
00177       add_header_fixup, 0,
00178       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00179    {"insert_hf",        (cmd_function)insert_hf_1,       1, 
00180       add_header_fixup, 0,
00181       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00182    {"insert_hf",        (cmd_function)insert_hf_2,       2, 
00183       add_header_fixup, 0,
00184       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00185    {"append_urihf",     (cmd_function)append_urihf,      2,
00186       fixup_str_str, fixup_free_str_str,
00187       REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
00188    {"remove_hf",        (cmd_function)remove_hf_f,       1,
00189       hname_fixup, free_hname_fixup,
00190       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00191    {"remove_hf_re",     (cmd_function)remove_hf_re_f,    1,
00192       fixup_regexp_null, fixup_free_regexp_null,
00193       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00194    {"is_present_hf",    (cmd_function)is_present_hf_f,   1,
00195       hname_fixup, free_hname_fixup,
00196       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00197    {"is_present_hf_re", (cmd_function)is_present_hf_re_f,1,
00198       fixup_regexp_null, fixup_free_regexp_null,
00199       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00200    {"subst",            (cmd_function)subst_f,           1,
00201       fixup_substre, 0,
00202       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00203    {"subst_uri",        (cmd_function)subst_uri_f,       1,
00204       fixup_substre, 0,
00205       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
00206    {"subst_user",       (cmd_function)subst_user_f,      1,
00207       fixup_substre, 0,
00208       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
00209    {"subst_body",       (cmd_function)subst_body_f,      1,
00210       fixup_substre, 0,
00211       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00212    {"filter_body",      (cmd_function)filter_body_f,     1,
00213       fixup_str_null, 0,
00214       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00215    {"append_time",      (cmd_function)append_time_f,     0,
00216       0, 0,
00217       REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
00218    {"set_body",         (cmd_function)set_body_f,        2,
00219       fixup_spve_spve, 0,
00220       REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE },
00221    {"set_reply_body",     (cmd_function)set_rpl_body_f,    2,
00222       fixup_spve_spve, 0,
00223       REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
00224    {"is_method",        (cmd_function)is_method_f,       1,
00225       fixup_method, 0,
00226       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00227    {"has_body",         (cmd_function)has_body_f,        0,
00228       0, 0,
00229       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00230    {"has_body",         (cmd_function)has_body_f,        1, 
00231       fixup_body_type, 0,
00232       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00233    {"is_privacy",       (cmd_function)is_privacy_f,      1,
00234       fixup_privacy, 0,
00235       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00236    {"cmp_str",  (cmd_function)cmp_str_f, 2,
00237       fixup_spve_spve, 0,
00238       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00239    {"cmp_istr",  (cmd_function)cmp_istr_f, 2,
00240       fixup_spve_spve, 0,
00241       REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
00242 
00243    {0,0,0,0,0,0}
00244 };
00245 
00246 
00247 struct module_exports exports= {
00248    "textops",  /* module name*/
00249    DEFAULT_DLFLAGS, /* dlopen flags */
00250    cmds,       /* exported functions */
00251    0,          /* module parameters */
00252    0,          /* exported statistics */
00253    0,          /* exported MI functions */
00254    0,          /* exported pseudo-variables */
00255    0,          /* extra processes */
00256    mod_init,   /* module initialization function */
00257    0,          /* response function */
00258    0,          /* destroy function */
00259    0,          /* per-child init function */
00260 };
00261 
00262 
00263 static int mod_init(void)
00264 {
00265    return 0;
00266 }
00267 
00268 int mod_register(char *path, int *dlflags, void *p1, void *p2)
00269 {
00270    return register_trans_mod(path, mod_trans);
00271 }
00272 
00273 static char *get_header(struct sip_msg *msg)
00274 {
00275    return msg->buf+msg->first_line.len;
00276 }
00277 
00278 
00279 
00280 int search_f(struct sip_msg* msg, char* key, char* str2)
00281 {
00282    /*we registered only 1 param, so we ignore str2*/
00283    regmatch_t pmatch;
00284 
00285    if (regexec((regex_t*) key, msg->buf, 1, &pmatch, 0)!=0) return -1;
00286    return 1;
00287 }
00288 
00289 
00290 static int search_body_f(struct sip_msg* msg, char* key, char* str2)
00291 {
00292    str body;
00293    /*we registered only 1 param, so we ignore str2*/
00294    regmatch_t pmatch;
00295 
00296    body.s = get_body(msg);
00297    if (body.s==0) {
00298       LM_ERR("failed to get the message body\n");
00299       return -1;
00300    }
00301    body.len = msg->len -(int)(body.s-msg->buf);
00302    if (body.len==0) {
00303       LM_DBG("message body has zero length\n");
00304       return -1;
00305    }
00306 
00307    if (regexec((regex_t*) key, body.s, 1, &pmatch, 0)!=0) return -1;
00308    return 1;
00309 }
00310 
00311 
00312 int search_append_f(struct sip_msg* msg, char* key, char* str2)
00313 {
00314    struct lump* l;
00315    regmatch_t pmatch;
00316    char* s;
00317    int len;
00318    char *begin;
00319    int off;
00320 
00321    begin=get_header(msg); /* msg->orig/buf previously .. uri problems */
00322    off=begin-msg->buf;
00323 
00324    if (regexec((regex_t*) key, begin, 1, &pmatch, 0)!=0) return -1;
00325    if (pmatch.rm_so!=-1){
00326       if ((l=anchor_lump(msg, off+pmatch.rm_eo, 0, 0))==0)
00327          return -1;
00328       len=strlen(str2);
00329       s=pkg_malloc(len);
00330       if (s==0){
00331          LM_ERR("memory allocation failure\n");
00332          return -1;
00333       }
00334       memcpy(s, str2, len); 
00335       if (insert_new_lump_after(l, s, len, 0)==0){
00336          LM_ERR("could not insert new lump\n");
00337          pkg_free(s);
00338          return -1;
00339       }
00340       return 1;
00341    }
00342    return -1;
00343 }
00344 
00345 static int search_append_body_f(struct sip_msg* msg, char* key, char* str2)
00346 {
00347    struct lump* l;
00348    regmatch_t pmatch;
00349    char* s;
00350    int len;
00351    int off;
00352    str body;
00353 
00354    body.s = get_body(msg);
00355    if (body.s==0) {
00356       LM_ERR("failed to get the message body\n");
00357       return -1;
00358    }
00359    body.len = msg->len -(int)(body.s-msg->buf);
00360    if (body.len==0) {
00361       LM_DBG("message body has zero length\n");
00362       return -1;
00363    }
00364 
00365    off=body.s-msg->buf;
00366 
00367    if (regexec((regex_t*) key, body.s, 1, &pmatch, 0)!=0) return -1;
00368    if (pmatch.rm_so!=-1){
00369       if ((l=anchor_lump(msg, off+pmatch.rm_eo, 0, 0))==0)
00370          return -1;
00371       len=strlen(str2);
00372       s=pkg_malloc(len);
00373       if (s==0){
00374          LM_ERR("memory allocation failure\n");
00375          return -1;
00376       }
00377       memcpy(s, str2, len); 
00378       if (insert_new_lump_after(l, s, len, 0)==0){
00379          LM_ERR("could not insert new lump\n");
00380          pkg_free(s);
00381          return -1;
00382       }
00383       return 1;
00384    }
00385    return -1;
00386 }
00387 
00388 
00389 static int replace_all_f(struct sip_msg* msg, char* key, char* str2)
00390 {
00391    struct lump* l;
00392    regmatch_t pmatch;
00393    char* s;
00394    int len;
00395    char* begin;
00396    int off;
00397    int ret;
00398    int eflags;
00399 
00400    begin = get_header(msg);
00401    ret=-1; /* pessimist: we will not find any */
00402    len=strlen(str2);
00403    eflags=0; /* match ^ at the beginning of the string*/
00404 
00405    while (begin<msg->buf+msg->len 
00406             && regexec((regex_t*) key, begin, 1, &pmatch, eflags)==0) {
00407       off=begin-msg->buf;
00408       if (pmatch.rm_so==-1){
00409          LM_ERR("offset unknown\n");
00410          return -1;
00411       }
00412       if (pmatch.rm_so==pmatch.rm_eo){
00413          LM_ERR("matched string is empty... invalid regexp?\n");
00414          return -1;
00415       }
00416       if ((l=del_lump(msg, pmatch.rm_so+off,
00417                   pmatch.rm_eo-pmatch.rm_so, 0))==0) {
00418          LM_ERR("del_lump failed\n");
00419          return -1;
00420       }
00421       s=pkg_malloc(len);
00422       if (s==0){
00423          LM_ERR("memory allocation failure\n");
00424          return -1;
00425       }
00426       memcpy(s, str2, len); 
00427       if (insert_new_lump_after(l, s, len, 0)==0){
00428          LM_ERR("could not insert new lump\n");
00429          pkg_free(s);
00430          return -1;
00431       }
00432       /* new cycle */
00433       begin=begin+pmatch.rm_eo;
00434       /* is it still a string start */
00435       if (*(begin-1)=='\n' || *(begin-1)=='\r')
00436          eflags&=~REG_NOTBOL;
00437       else
00438          eflags|=REG_NOTBOL;
00439       ret=1;
00440    } /* while found ... */
00441    return ret;
00442 }
00443 
00444 static int do_replace_body_f(struct sip_msg* msg, char* key, char* str2, int nobol)
00445 {
00446    struct lump* l;
00447    regmatch_t pmatch;
00448    char* s;
00449    int len;
00450    char* begin;
00451    int off;
00452    int ret;
00453    int eflags;
00454    str body;
00455 
00456    body.s = get_body(msg);
00457    if (body.s==0) {
00458       LM_ERR("failed to get the message body\n");
00459       return -1;
00460    }
00461    body.len = msg->len -(int)(body.s-msg->buf);
00462    if (body.len==0) {
00463       LM_DBG("message body has zero length\n");
00464       return -1;
00465    }
00466 
00467    begin=body.s;
00468    ret=-1; /* pessimist: we will not find any */
00469    len=strlen(str2);
00470    eflags=0; /* match ^ at the beginning of the string*/
00471 
00472    while (begin<msg->buf+msg->len 
00473             && regexec((regex_t*) key, begin, 1, &pmatch, eflags)==0) {
00474       off=begin-msg->buf;
00475       if (pmatch.rm_so==-1){
00476          LM_ERR("offset unknown\n");
00477          return -1;
00478       }
00479       if (pmatch.rm_so==pmatch.rm_eo){
00480          LM_ERR("matched string is empty... invalid regexp?\n");
00481          return -1;
00482       }
00483       if ((l=del_lump(msg, pmatch.rm_so+off,
00484                   pmatch.rm_eo-pmatch.rm_so, 0))==0) {
00485          LM_ERR("del_lump failed\n");
00486          return -1;
00487       }
00488       s=pkg_malloc(len);
00489       if (s==0){
00490          LM_ERR("memory allocation failure\n");
00491          return -1;
00492       }
00493       memcpy(s, str2, len); 
00494       if (insert_new_lump_after(l, s, len, 0)==0){
00495          LM_ERR("could not insert new lump\n");
00496          pkg_free(s);
00497          return -1;
00498       }
00499       /* new cycle */
00500       begin=begin+pmatch.rm_eo;
00501       /* is it still a string start */
00502       if (nobol && (*(begin-1)=='\n' || *(begin-1)=='\r'))
00503          eflags&=~REG_NOTBOL;
00504       else
00505          eflags|=REG_NOTBOL;
00506       ret=1;
00507    } /* while found ... */
00508    return ret;
00509 }
00510 
00511 static int replace_body_all_f(struct sip_msg* msg, char* key, char* str2)
00512 {
00513    return do_replace_body_f(msg, key, str2, 1);
00514 }
00515 
00516 static int replace_body_atonce_f(struct sip_msg* msg, char* key, char* str2)
00517 {
00518    return do_replace_body_f(msg, key, str2, 0);
00519 }
00520 
00521 static int replace_f(struct sip_msg* msg, char* key, char* str2)
00522 {
00523    struct lump* l;
00524    regmatch_t pmatch;
00525    char* s;
00526    int len;
00527    char* begin;
00528    int off;
00529 
00530    begin=get_header(msg); /* msg->orig previously .. uri problems */
00531 
00532    if (regexec((regex_t*) key, begin, 1, &pmatch, 0)!=0) return -1;
00533    off=begin-msg->buf;
00534 
00535    if (pmatch.rm_so!=-1){
00536       if ((l=del_lump(msg, pmatch.rm_so+off,
00537                   pmatch.rm_eo-pmatch.rm_so, 0))==0)
00538          return -1;
00539       len=strlen(str2);
00540       s=pkg_malloc(len);
00541       if (s==0){
00542          LM_ERR("memory allocation failure\n");
00543          return -1;
00544       }
00545       memcpy(s, str2, len); 
00546       if (insert_new_lump_after(l, s, len, 0)==0){
00547          LM_ERR("could not insert new lump\n");
00548          pkg_free(s);
00549          return -1;
00550       }
00551       
00552       return 1;
00553    }
00554    return -1;
00555 }
00556 
00557 static int replace_body_f(struct sip_msg* msg, char* key, char* str2)
00558 {
00559    struct lump* l;
00560    regmatch_t pmatch;
00561    char* s;
00562    int len;
00563    char* begin;
00564    int off;
00565    str body;
00566 
00567    body.s = get_body(msg);
00568    if (body.s==0) {
00569       LM_ERR("failed to get the message body\n");
00570       return -1;
00571    }
00572    body.len = msg->len -(int)(body.s-msg->buf);
00573    if (body.len==0) {
00574       LM_DBG("message body has zero length\n");
00575       return -1;
00576    }
00577 
00578    begin=body.s; /* msg->orig previously .. uri problems */
00579 
00580    if (regexec((regex_t*) key, begin, 1, &pmatch, 0)!=0) return -1;
00581    off=begin-msg->buf;
00582 
00583    if (pmatch.rm_so!=-1){
00584       if ((l=del_lump(msg, pmatch.rm_so+off,
00585                   pmatch.rm_eo-pmatch.rm_so, 0))==0)
00586          return -1;
00587       len=strlen(str2);
00588       s=pkg_malloc(len);
00589       if (s==0){
00590          LM_ERR("memory allocation failure\n");
00591          return -1;
00592       }
00593       memcpy(s, str2, len); 
00594       if (insert_new_lump_after(l, s, len, 0)==0){
00595          LM_ERR("could not insert new lump\n");
00596          pkg_free(s);
00597          return -1;
00598       }
00599       
00600       return 1;
00601    }
00602    return -1;
00603 }
00604 
00605 
00606 /* sed-perl style re: s/regular expression/replacement/flags */
00607 static int subst_f(struct sip_msg* msg, char*  subst, char* ignored)
00608 {
00609    struct lump* l;
00610    struct replace_lst* lst;
00611    struct replace_lst* rpl;
00612    char* begin;
00613    struct subst_expr* se;
00614    int off;
00615    int ret;
00616    int nmatches;
00617    
00618    se=(struct subst_expr*)subst;
00619    begin=get_header(msg);  /* start after first line to avoid replacing
00620                         the uri */
00621    off=begin-msg->buf;
00622    ret=-1;
00623    if ((lst=subst_run(se, begin, msg, &nmatches))==0)
00624       goto error; /* not found */
00625    for (rpl=lst; rpl; rpl=rpl->next){
00626       LM_DBG("%s: replacing at offset %d [%.*s] with [%.*s]\n",
00627             exports.name, rpl->offset+off,
00628             rpl->size, rpl->offset+off+msg->buf,
00629             rpl->rpl.len, rpl->rpl.s);
00630       if ((l=del_lump(msg, rpl->offset+off, rpl->size, 0))==0)
00631          goto error;
00632       /* hack to avoid re-copying rpl, possible because both 
00633        * replace_lst & lumps use pkg_malloc */
00634       if (insert_new_lump_after(l, rpl->rpl.s, rpl->rpl.len, 0)==0){
00635          LM_ERR("%s: could not insert new lump\n", exports.name);
00636          goto error;
00637       }
00638       /* hack continued: set rpl.s to 0 so that replace_lst_free will
00639        * not free it */
00640       rpl->rpl.s=0;
00641       rpl->rpl.len=0;
00642    }
00643    ret=1;
00644 error:
00645    LM_DBG("lst was %p\n", lst);
00646    if (lst) replace_lst_free(lst);
00647    if (nmatches<0)
00648       LM_ERR("%s: subst_run failed\n", exports.name);
00649    return ret;
00650 }
00651 
00652 
00653 
00654 /* sed-perl style re: s/regular expression/replacement/flags, like
00655  *  subst but works on the message uri */
00656 static int subst_uri_f(struct sip_msg* msg, char*  subst, char* ignored)
00657 {
00658    char* tmp;
00659    int len;
00660    char c;
00661    struct subst_expr* se;
00662    str* result;
00663    
00664    se=(struct subst_expr*)subst;
00665    if (msg->new_uri.s){
00666       len=msg->new_uri.len;
00667       tmp=msg->new_uri.s;
00668    }else{
00669       tmp=msg->first_line.u.request.uri.s;
00670       len   =msg->first_line.u.request.uri.len;
00671    };
00672    /* ugly hack: 0 s[len], and restore it afterward
00673     * (our re functions require 0 term strings), we can do this
00674     * because we always alloc len+1 (new_uri) and for first_line, the
00675     * message will always be > uri.len */
00676    c=tmp[len];
00677    tmp[len]=0;
00678    result=subst_str(tmp, msg, se, 0); /* pkg malloc'ed result */
00679    tmp[len]=c;
00680    if (result){
00681       LM_DBG("%s match - old uri= [%.*s], new uri= [%.*s]\n",
00682             exports.name, len, tmp,
00683             (result->len)?result->len:0,(result->s)?result->s:"");
00684       if (msg->new_uri.s) pkg_free(msg->new_uri.s);
00685       msg->new_uri=*result;
00686       msg->parsed_uri_ok=0; /* reset "use cached parsed uri" flag */
00687       pkg_free(result); /* free str* pointer */
00688       return 1; /* success */
00689    }
00690    return -1; /* false, no subst. made */
00691 }
00692    
00693 
00694 
00695 /* sed-perl style re: s/regular expression/replacement/flags, like
00696  *  subst but works on the user part of the uri */
00697 static int subst_user_f(struct sip_msg* msg, char*  subst, char* ignored)
00698 {
00699    int rval;
00700    str* result;
00701    struct subst_expr* se;
00702    struct action act;
00703    str user;
00704    char c;
00705    int nmatches;
00706 
00707    c=0;
00708    if (parse_sip_msg_uri(msg)<0){
00709       return -1; /* error, bad uri */
00710    }
00711    if (msg->parsed_uri.user.s==0){
00712       /* no user in uri */
00713       user.s="";
00714       user.len=0;
00715    }else{
00716       user=msg->parsed_uri.user;
00717       c=user.s[user.len];
00718       user.s[user.len]=0;
00719    }
00720    se=(struct subst_expr*)subst;
00721    result=subst_str(user.s, msg, se, &nmatches);/* pkg malloc'ed result */
00722    if (c)   user.s[user.len]=c;
00723    if (result == NULL) {
00724       if (nmatches<0)
00725          LM_ERR("subst_user(): subst_str() failed\n");
00726       return -1;
00727    }
00728    /* result->s[result->len] = '\0';  --subst_str returns 0-term strings */
00729    memset(&act, 0, sizeof(act)); /* be on the safe side */
00730    act.type = SET_USER_T;
00731    act.elem[0].type = STRING_ST;
00732    act.elem[0].u.string = result->s;
00733    rval = do_action(&act, msg);
00734    pkg_free(result->s);
00735    pkg_free(result);
00736    return rval;
00737 }
00738 
00739 
00740 /* sed-perl style re: s/regular expression/replacement/flags */
00741 static int subst_body_f(struct sip_msg* msg, char*  subst, char* ignored)
00742 {
00743    struct lump* l;
00744    struct replace_lst* lst;
00745    struct replace_lst* rpl;
00746    char* begin;
00747    struct subst_expr* se;
00748    int off;
00749    int ret;
00750    int nmatches;
00751    str body;
00752 
00753    body.s = get_body(msg);
00754    if (body.s==0) {
00755       LM_ERR("failed to get the message body\n");
00756       return -1;
00757    }
00758    body.len = msg->len -(int)(body.s-msg->buf);
00759    if (body.len==0) {
00760       LM_DBG("message body has zero length\n");
00761       return -1;
00762    }
00763    
00764    se=(struct subst_expr*)subst;
00765    begin=body.s;
00766    
00767    off=begin-msg->buf;
00768    ret=-1;
00769    if ((lst=subst_run(se, begin, msg, &nmatches))==0)
00770       goto error; /* not found */
00771    for (rpl=lst; rpl; rpl=rpl->next){
00772       LM_DBG("%s replacing at offset %d [%.*s] with [%.*s]\n",
00773             exports.name, rpl->offset+off,
00774             rpl->size, rpl->offset+off+msg->buf,
00775             rpl->rpl.len, rpl->rpl.s);
00776       if ((l=del_lump(msg, rpl->offset+off, rpl->size, 0))==0)
00777          goto error;
00778       /* hack to avoid re-copying rpl, possible because both 
00779        * replace_lst & lumps use pkg_malloc */
00780       if (insert_new_lump_after(l, rpl->rpl.s, rpl->rpl.len, 0)==0){
00781          LM_ERR("%s could not insert new lump\n",
00782                exports.name);
00783          goto error;
00784       }
00785       /* hack continued: set rpl.s to 0 so that replace_lst_free will
00786        * not free it */
00787       rpl->rpl.s=0;
00788       rpl->rpl.len=0;
00789    }
00790    ret=1;
00791 error:
00792    LM_DBG("lst was %p\n", lst);
00793    if (lst) replace_lst_free(lst);
00794    if (nmatches<0)
00795       LM_ERR("%s subst_run failed\n", exports.name);
00796    return ret;
00797 }
00798 
00799 
00800 static inline int find_line_start(char *text, unsigned int text_len,
00801               char **buf, unsigned int *buf_len)
00802 {
00803     char *ch, *start;
00804     unsigned int len;
00805 
00806     start = *buf;
00807     len = *buf_len;
00808 
00809     while (text_len <= len) {
00810    if (strncmp(text, start, text_len) == 0) {
00811        *buf = start;
00812        *buf_len = len;
00813        return 1;
00814    }
00815    if ((ch = memchr(start, 13, len - 1))) {
00816        if (*(ch + 1) != 10) {
00817       LM_ERR("No LF after CR\n");
00818       return 0;
00819        }
00820        len = len - (ch - start + 2);
00821        start = ch + 2;
00822    } else {
00823        LM_ERR("No CRLF found\n");
00824        return 0;
00825    }
00826     }
00827     return 0;
00828 }
00829 
00830 
00831 /* Filters multipart body by leaving out everything else except
00832  * first body part of given content type. */
00833 static int filter_body_f(struct sip_msg* msg, char* _content_type,
00834           char* ignored)
00835 {
00836    char *start;
00837    unsigned int len;
00838    str *content_type, body;
00839 
00840    body.s = get_body(msg);
00841    if (body.s == 0) {
00842       LM_ERR("Failed to get the message body\n");
00843       return -1;
00844    }
00845    body.len = msg->len - (int)(body.s - msg->buf);
00846    if (body.len == 0) {
00847       LM_DBG("Message body has zero length\n");
00848       return -1;
00849    }
00850    
00851    content_type = (str *)_content_type;
00852    start = body.s;
00853    len = body.len;
00854    
00855    while (find_line_start("Content-Type: ", 14, &start, &len)) {
00856        start = start + 14;
00857        len = len - 14;
00858        if (len > content_type->len + 2) {
00859       if (strncasecmp(start, content_type->s, content_type->len)
00860           == 0) {
00861           start = start + content_type->len;
00862           if ((*start != 13) || (*(start + 1) != 10)) {
00863          LM_ERR("No CRLF found after content type\n");
00864          return -1;
00865           }
00866           start = start + 2;
00867           len = len - content_type->len - 2;
00868           while ((len > 0) && ((*start == 13) || (*start == 10))) {
00869          len = len - 1;
00870          start = start + 1;
00871           }
00872           if (del_lump(msg, body.s - msg->buf, start - body.s, 0)
00873          == 0) {
00874          LM_ERR("Deleting lump <%.*s> failed\n",
00875                 (int)(start - body.s), body.s);
00876          return -1;
00877           }
00878           if (find_line_start("--Boundary", 10, &start, &len)) {
00879          if (del_lump(msg, start - msg->buf, len, 0) == 0) {
00880              LM_ERR("Deleting lump <%.*s> failed\n",
00881                len, start);
00882              return -1;
00883          } else {
00884              return 1;
00885          }
00886           } else {
00887          LM_ERR("Boundary not found after content\n");
00888          return -1;
00889           }
00890       }
00891        } else {
00892       return -1;
00893        }
00894    }
00895    return -1;
00896 }
00897 
00898 
00899 int remove_hf_f(struct sip_msg* msg, char* str_hf, char* foo)
00900 {
00901    struct hdr_field *hf;
00902    struct lump* l;
00903    int cnt;
00904    gparam_p gp;
00905 
00906    gp = (gparam_p)str_hf;
00907    cnt=0;
00908 
00909    /* we need to be sure we have seen all HFs */
00910    parse_headers(msg, HDR_EOH_F, 0);
00911    for (hf=msg->headers; hf; hf=hf->next) {
00912       /* for well known header names str_hf->s will be set to NULL 
00913          during parsing of kamailio.cfg and str_hf->len contains 
00914          the header type */
00915       if(gp->type==GPARAM_TYPE_INT)
00916       {
00917          if (gp->v.ival!=hf->type)
00918             continue;
00919       } else {
00920          if (hf->name.len!=gp->v.sval.len)
00921             continue;
00922          if (cmp_hdrname_str(&hf->name, &gp->v.sval)!=0)
00923             continue;
00924       }
00925       l=del_lump(msg, hf->name.s-msg->buf, hf->len, 0);
00926       if (l==0) {
00927          LM_ERR("no memory\n");
00928          return -1;
00929       }
00930       cnt++;
00931    }
00932    return cnt==0 ? -1 : 1;
00933 }
00934 
00935 static int remove_hf_re_f(struct sip_msg* msg, char* key, char* foo)
00936 {
00937    struct hdr_field *hf;
00938    struct lump* l;
00939    int cnt;
00940    regex_t *re;
00941    char c;
00942    regmatch_t pmatch;
00943 
00944    re = (regex_t*)key;
00945    cnt=0;
00946 
00947    /* we need to be sure we have seen all HFs */
00948    parse_headers(msg, HDR_EOH_F, 0);
00949    for (hf=msg->headers; hf; hf=hf->next)
00950    {
00951       c = hf->name.s[hf->name.len];
00952       hf->name.s[hf->name.len] = '\0';
00953       if (regexec(re, hf->name.s, 1, &pmatch, 0)!=0)
00954       {
00955          hf->name.s[hf->name.len] = c;
00956          continue;
00957       }
00958       hf->name.s[hf->name.len] = c;
00959       l=del_lump(msg, hf->name.s-msg->buf, hf->len, 0);
00960       if (l==0)
00961       {
00962          LM_ERR("cannot remove header\n");
00963          return -1;
00964       }
00965       cnt++;
00966    }
00967 
00968    return cnt==0 ? -1 : 1;
00969 }
00970 
00971 static int is_present_hf_f(struct sip_msg* msg, char* str_hf, char* foo)
00972 {
00973    struct hdr_field *hf;
00974    gparam_p gp;
00975 
00976    gp = (gparam_p)str_hf;
00977 
00978    /* we need to be sure we have seen all HFs */
00979    parse_headers(msg, HDR_EOH_F, 0);
00980    for (hf=msg->headers; hf; hf=hf->next) {
00981       if(gp->type==GPARAM_TYPE_INT)
00982       {
00983          if (gp->v.ival!=hf->type)
00984             continue;
00985       } else {
00986          if (hf->name.len!=gp->v.sval.len)
00987             continue;
00988          if (cmp_hdrname_str(&hf->name,&gp->v.sval)!=0)
00989             continue;
00990       }
00991       return 1;
00992    }
00993    return -1;
00994 }
00995 
00996 static int is_present_hf_re_f(struct sip_msg* msg, char* key, char* foo)
00997 {
00998    struct hdr_field *hf;
00999    regex_t *re;
01000    regmatch_t pmatch;
01001    char c;
01002 
01003    re = (regex_t*)key;
01004 
01005    /* we need to be sure we have seen all HFs */
01006    parse_headers(msg, HDR_EOH_F, 0);
01007    for (hf=msg->headers; hf; hf=hf->next)
01008    {
01009       c = hf->name.s[hf->name.len];
01010       hf->name.s[hf->name.len] = '\0';
01011       if (regexec(re, hf->name.s, 1, &pmatch, 0)!=0)
01012       {
01013          hf->name.s[hf->name.len] = c;
01014          continue;
01015       }
01016       hf->name.s[hf->name.len] = c;
01017       return 1;
01018    }
01019 
01020    return -1;
01021 }
01022 
01023 
01024 static int fixup_substre(void** param, int param_no)
01025 {
01026    struct subst_expr* se;
01027    str subst;
01028 
01029    LM_DBG("%s module -- fixing %s\n", exports.name, (char*)(*param));
01030    if (param_no!=1) return 0;
01031    subst.s=*param;
01032    subst.len=strlen(*param);
01033    se=subst_parser(&subst);
01034    if (se==0){
01035       LM_ERR("%s: bad subst. re %s\n", exports.name, 
01036             (char*)*param);
01037       return E_BAD_RE;
01038    }
01039    /* don't free string -- needed for specifiers */
01040    /* pkg_free(*param); */
01041    /* replace it with the compiled subst. re */
01042    *param=se;
01043    return 0;
01044 }
01045 
01046 
01047 static int append_time_f(struct sip_msg* msg, char* p1, char *p2)
01048 {
01049 
01050 
01051    size_t len;
01052    char time_str[MAX_TIME];
01053    time_t now;
01054    struct tm *bd_time;
01055 
01056    now=time(0);
01057 
01058    bd_time=gmtime(&now);
01059    if (bd_time==NULL) {
01060       LM_ERR("gmtime failed\n");
01061       return -1;
01062    }
01063 
01064    len=strftime(time_str, MAX_TIME, TIME_FORMAT, bd_time);
01065    if (len>MAX_TIME-2 || len==0) {
01066       LM_ERR("unexpected time length\n");
01067       return -1;
01068    }
01069 
01070    time_str[len]='\r';
01071    time_str[len+1]='\n';
01072 
01073 
01074    if (add_lump_rpl(msg, time_str, len+2, LUMP_RPL_HDR)==0)
01075    {
01076       LM_ERR("unable to add lump\n");
01077       return -1;
01078    }
01079 
01080    return 1;
01081 }
01082 
01083 
01084 static int set_body_f(struct sip_msg* msg, char* p1, char* p2)
01085 {
01086    struct lump *anchor;
01087    char* buf;
01088    int len;
01089    char* value_s;
01090    int value_len;
01091    str body = {0,0};
01092    str nb = {0,0};
01093    str nc = {0,0};
01094 
01095    if(p1==0 || p2==0)
01096    {
01097       LM_ERR("invalid parameters\n");
01098       return -1;
01099    }
01100 
01101    if(fixup_get_svalue(msg, (gparam_p)p1, &nb)!=0)
01102    {
01103       LM_ERR("unable to get p1\n");
01104       return -1;
01105    }
01106    if(nb.s==NULL || nb.len == 0)
01107    {
01108       LM_ERR("invalid body parameter\n");
01109       return -1;
01110    }
01111    if(fixup_get_svalue(msg, (gparam_p)p2, &nc)!=0)
01112    {
01113       LM_ERR("unable to get p2\n");
01114       return -1;
01115    }
01116    if(nc.s==NULL || nc.len == 0)
01117    {
01118       LM_ERR("invalid content-type parameter\n");
01119       return -1;
01120    }
01121 
01122    body.len = 0;
01123    body.s = get_body(msg);
01124    if (body.s==0)
01125    {
01126       LM_ERR("malformed sip message\n");
01127       return -1;
01128    }
01129 
01130    free_lump_list(msg->body_lumps);
01131    msg->body_lumps = NULL;
01132 
01133    if (msg->content_length) 
01134    {
01135       body.len = get_content_length( msg );
01136       if(body.len > 0)
01137       {
01138          if(body.s+body.len>msg->buf+msg->len)
01139          {
01140             LM_ERR("invalid content length: %d\n", body.len);
01141             return -1;
01142          }
01143          if(del_lump(msg, body.s - msg->buf, body.len, 0) == 0)
01144          {
01145             LM_ERR("cannot delete existing body");
01146             return -1;
01147          }
01148       }
01149    }
01150 
01151    anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0, 0);
01152 
01153    if (anchor == 0)
01154    {
01155       LM_ERR("failed to get anchor\n");
01156       return -1;
01157    } 
01158 
01159    if (msg->content_length==0)
01160    {
01161       /* need to add Content-Length */
01162       len = nb.len;
01163       value_s=int2str(len, &value_len);
01164       LM_DBG("content-length: %d (%s)\n", value_len, value_s);
01165 
01166       len=CONTENT_LENGTH_LEN+value_len+CRLF_LEN;
01167       buf=pkg_malloc(sizeof(char)*(len));
01168 
01169       if (buf==0)
01170       {
01171          LM_ERR("out of pkg memory\n");
01172          return -1;
01173       }
01174 
01175       memcpy(buf, CONTENT_LENGTH, CONTENT_LENGTH_LEN);
01176       memcpy(buf+CONTENT_LENGTH_LEN, value_s, value_len);
01177       memcpy(buf+CONTENT_LENGTH_LEN+value_len, CRLF, CRLF_LEN);
01178       if (insert_new_lump_after(anchor, buf, len, 0) == 0)
01179       {
01180          LM_ERR("failed to insert content-length lump\n");
01181          pkg_free(buf);
01182          return -1;
01183       }
01184    }
01185 
01186    /* add content-type */
01187    if(msg->content_type==NULL || msg->content_type->body.len!=nc.len
01188          || strncmp(msg->content_type->body.s, nc.s, nc.len)!=0)
01189    {
01190       if(msg->content_type!=NULL)
01191          if(del_lump(msg, msg->content_type->name.s-msg->buf,
01192                   msg->content_type->len, 0) == 0)
01193          {
01194             LM_ERR("failed to delete content type\n");
01195             return -1;
01196          }
01197       value_len = nc.len;
01198       len=sizeof("Content-Type: ") - 1 + value_len + CRLF_LEN;
01199       buf=pkg_malloc(sizeof(char)*(len));
01200 
01201       if (buf==0)
01202       {
01203          LM_ERR("out of pkg memory\n");
01204          return -1;
01205       }
01206       memcpy(buf, "Content-Type: ", sizeof("Content-Type: ") - 1);
01207       memcpy(buf+sizeof("Content-Type: ") - 1, nc.s, value_len);
01208       memcpy(buf+sizeof("Content-Type: ") - 1 + value_len, CRLF, CRLF_LEN);
01209       if (insert_new_lump_after(anchor, buf, len, 0) == 0)
01210       {
01211          LM_ERR("failed to insert content-type lump\n");
01212          pkg_free(buf);
01213          return -1;
01214       }
01215    }  
01216    anchor = anchor_lump(msg, body.s - msg->buf, 0, 0);
01217 
01218    if (anchor == 0)
01219    {
01220       LM_ERR("failed to get body anchor\n");
01221       return -1;
01222    } 
01223 
01224    buf=pkg_malloc(sizeof(char)*(nb.len));
01225    if (buf==0)
01226    {
01227       LM_ERR("out of pkg memory\n");
01228       return -1;
01229    }
01230    memcpy(buf, nb.s, nb.len);
01231    if (insert_new_lump_after(anchor, buf, nb.len, 0) == 0)
01232    {
01233       LM_ERR("failed to insert body lump\n");
01234       pkg_free(buf);
01235       return -1;
01236    }
01237    LM_DBG("new body: [%.*s]", nb.len, nb.s);
01238    return 1;
01239 }
01240 
01241 static int set_rpl_body_f(struct sip_msg* msg, char* p1, char* p2)
01242 {
01243    char* buf;
01244    int len;
01245    int value_len;
01246    str nb = {0,0};
01247    str nc = {0,0};
01248 
01249    if(p1==0 || p2==0)
01250    {
01251       LM_ERR("invalid parameters\n");
01252       return -1;
01253    }
01254 
01255    if(fixup_get_svalue(msg, (gparam_p)p1, &nb)!=0)
01256    {
01257       LM_ERR("unable to get p1\n");
01258       return -1;
01259    }
01260    if(nb.s==NULL || nb.len == 0)
01261    {
01262       LM_ERR("invalid body parameter\n");
01263       return -1;
01264    }
01265    if(fixup_get_svalue(msg, (gparam_p)p2, &nc)!=0)
01266    {
01267       LM_ERR("unable to get p2\n");
01268       return -1;
01269    }
01270    if(nc.s==NULL || nc.len == 0)
01271    {
01272       LM_ERR("invalid content-type parameter\n");
01273       return -1;
01274    }
01275 
01276    /* add content-type */
01277    value_len = nc.len;
01278    len=sizeof("Content-Type: ") - 1 + value_len + CRLF_LEN;
01279    buf=pkg_malloc(sizeof(char)*(len));
01280 
01281    if (buf==0)
01282    {
01283       LM_ERR("out of pkg memory\n");
01284       return -1;
01285    }
01286    memcpy(buf, "Content-Type: ", sizeof("Content-Type: ") - 1);
01287    memcpy(buf+sizeof("Content-Type: ") - 1, nc.s, value_len);
01288    memcpy(buf+sizeof("Content-Type: ") - 1 + value_len, CRLF, CRLF_LEN);
01289    if (add_lump_rpl(msg, buf, len, LUMP_RPL_HDR) == 0)
01290    {
01291       LM_ERR("failed to insert content-type lump\n");
01292       pkg_free(buf);
01293       return -1;
01294    }
01295    pkg_free(buf);
01296 
01297    if (add_lump_rpl( msg, nb.s, nb.len, LUMP_RPL_BODY)==0) {
01298       LM_ERR("cannot add body lump\n");
01299       return -1;
01300    }
01301       
01302    return 1;
01303 }
01304 
01305 
01306 
01307 static int append_to_reply_f(struct sip_msg* msg, char* key, char* str0)
01308 {
01309    str s0;
01310 
01311    if(key==NULL)
01312    {
01313       LM_ERR("bad parameters\n");
01314       return -1;
01315    }
01316 
01317    if(fixup_get_svalue(msg, (gparam_p)key, &s0)!=0)
01318    {
01319       LM_ERR("cannot print the format\n");
01320       return -1;
01321    }
01322  
01323    if ( add_lump_rpl( msg, s0.s, s0.len, LUMP_RPL_HDR)==0 )
01324    {
01325       LM_ERR("unable to add lump_rl\n");
01326       return -1;
01327    }
01328 
01329    return 1;
01330 }
01331 
01332 
01333 /* add str1 to end of header or str1.r-uri.str2 */
01334 
01335 int add_hf_helper(struct sip_msg* msg, str *str1, str *str2,
01336       gparam_p hfval, int mode, gparam_p hfanc)
01337 {
01338    struct lump* anchor;
01339    struct hdr_field *hf;
01340    char *s;
01341    int len;
01342    str s0;
01343 
01344    if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
01345       LM_ERR("error while parsing message\n");
01346       return -1;
01347    }
01348    
01349    hf = 0;
01350    if(hfanc!=NULL) {
01351       for (hf=msg->headers; hf; hf=hf->next) {
01352          if(hfanc->type==GPARAM_TYPE_INT)
01353          {
01354             if (hfanc->v.ival!=hf->type)
01355                continue;
01356          } else {
01357             if (hf->name.len!=hfanc->v.sval.len)
01358                continue;
01359             if (cmp_hdrname_str(&hf->name,&hfanc->v.sval)!=0)
01360                continue;
01361          }
01362          break;
01363       }
01364    }
01365 
01366    if(mode == 0) { /* append */
01367       if(hf==0) { /* after last header */
01368          anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0, 0);
01369       } else { /* after hf */
01370          anchor = anchor_lump(msg, hf->name.s + hf->len - msg->buf, 0, 0);
01371       }
01372    } else { /* insert */
01373       if(hf==0) { /* before first header */
01374          anchor = anchor_lump(msg, msg->headers->name.s - msg->buf, 0, 0);
01375       } else { /* before hf */
01376          anchor = anchor_lump(msg, hf->name.s - msg->buf, 0, 0);
01377       }
01378    }
01379 
01380    if(anchor == 0) {
01381       LM_ERR("can't get anchor\n");
01382       return -1;
01383    }
01384 
01385    if(str1) {
01386       s0 = *str1;
01387    } else {
01388       if(hfval) {
01389          if(fixup_get_svalue(msg, hfval, &s0)!=0)
01390          {
01391             LM_ERR("cannot print the format\n");
01392             return -1;
01393          }
01394       } else {
01395          s0.len = 0;
01396          s0.s   = 0;
01397       }
01398    }
01399       
01400    len=s0.len;
01401    if (str2) len+= str2->len + REQ_LINE(msg).uri.len;
01402 
01403    s = (char*)pkg_malloc(len);
01404    if (!s) {
01405       LM_ERR("no pkg memory left\n");
01406       return -1;
01407    }
01408 
01409    memcpy(s, s0.s, s0.len);
01410    if (str2) {
01411       memcpy(s+str1->len, REQ_LINE(msg).uri.s, REQ_LINE(msg).uri.len);
01412       memcpy(s+str1->len+REQ_LINE(msg).uri.len, str2->s, str2->len );
01413    }
01414 
01415    if (insert_new_lump_before(anchor, s, len, 0) == 0) {
01416       LM_ERR("can't insert lump\n");
01417       pkg_free(s);
01418       return -1;
01419    }
01420    return 1;
01421 }
01422 
01423 static int append_hf_1(struct sip_msg *msg, char *str1, char *str2 )
01424 {
01425    return add_hf_helper(msg, 0, 0, (gparam_p)str1, 0, 0);
01426 }
01427 
01428 static int append_hf_2(struct sip_msg *msg, char *str1, char *str2 )
01429 {
01430    return add_hf_helper(msg, 0, 0, (gparam_p)str1, 0,
01431          (gparam_p)str2);
01432 }
01433 
01434 static int insert_hf_1(struct sip_msg *msg, char *str1, char *str2 )
01435 {
01436    return add_hf_helper(msg, 0, 0, (gparam_p)str1, 1, 0);
01437 }
01438 
01439 static int insert_hf_2(struct sip_msg *msg, char *str1, char *str2 )
01440 {
01441    return add_hf_helper(msg, 0, 0, (gparam_p)str1, 1, 
01442          (gparam_p)str2);
01443 }
01444 
01445 static int append_urihf(struct sip_msg *msg, char *str1, char *str2)
01446 {
01447    return add_hf_helper(msg, (str*)str1, (str*)str2, 0, 0, 0);
01448 }
01449 
01450 static int is_method_f(struct sip_msg *msg, char *meth, char *str2 )
01451 {
01452    str *m;
01453 
01454    m = (str*)meth;
01455    if(msg->first_line.type==SIP_REQUEST)
01456    {
01457       if(m->s==0)
01458          return (msg->first_line.u.request.method_value&m->len)?1:-1;
01459       else
01460          return (msg->first_line.u.request.method_value==METHOD_OTHER
01461                && msg->first_line.u.request.method.len==m->len
01462                && (strncasecmp(msg->first_line.u.request.method.s, m->s,
01463                m->len)==0))?1:-1;
01464    }
01465    if(parse_headers(msg, HDR_CSEQ_F, 0)!=0 || msg->cseq==NULL)
01466    {
01467       LM_ERR("cannot parse cseq header\n");
01468       return -1; /* should it be 0 ?!?! */
01469    }
01470    if(m->s==0)
01471       return (get_cseq(msg)->method_id&m->len)?1:-1;
01472    else
01473       return (get_cseq(msg)->method_id==METHOD_OTHER
01474             && get_cseq(msg)->method.len==m->len
01475             && (strncasecmp(get_cseq(msg)->method.s, m->s,
01476             m->len)==0))?1:-1;
01477 }
01478 
01479 
01480 /*
01481  * Convert char* header_name to str* parameter
01482  */
01483 static int hname_fixup(void** param, int param_no)
01484 {
01485    char c;
01486    struct hdr_field hdr;
01487    gparam_p gp = NULL;
01488    
01489    gp = (gparam_p)pkg_malloc(sizeof(gparam_t));
01490    if(gp == NULL)
01491    {
01492       LM_ERR("no more memory\n");
01493       return E_UNSPEC;
01494    }
01495    memset(gp, 0, sizeof(gparam_t));
01496 
01497    gp->v.sval.s = (char*)*param;
01498    gp->v.sval.len = strlen(gp->v.sval.s);
01499    if(gp->v.sval.len==0)
01500    {
01501       LM_ERR("empty header name parameter\n");
01502       pkg_free(gp);
01503       return E_UNSPEC;
01504    }
01505    
01506    c = gp->v.sval.s[gp->v.sval.len];
01507    gp->v.sval.s[gp->v.sval.len] = ':';
01508    gp->v.sval.len++;
01509    
01510    if (parse_hname2(gp->v.sval.s, gp->v.sval.s
01511             + ((gp->v.sval.len<4)?4:gp->v.sval.len), &hdr)==0)
01512    {
01513       LM_ERR("error parsing header name\n");
01514       pkg_free(gp);
01515       return E_UNSPEC;
01516    }
01517    
01518    gp->v.sval.len--;
01519    gp->v.sval.s[gp->v.sval.len] = c;
01520 
01521    if (hdr.type!=HDR_OTHER_T && hdr.type!=HDR_ERROR_T)
01522    {
01523       LM_INFO("using hdr type (%d) instead of <%.*s>\n",
01524             hdr.type, gp->v.sval.len, gp->v.sval.s);
01525       pkg_free(gp->v.sval.s);
01526       gp->v.sval.s = NULL;
01527       gp->v.ival = hdr.type;
01528       gp->type = GPARAM_TYPE_INT;
01529    } else {
01530       gp->type = GPARAM_TYPE_STR;
01531       LM_INFO("using hdr type name <%.*s>\n", gp->v.sval.len, gp->v.sval.s);
01532    }
01533    
01534    *param = (void*)gp;
01535    return 0;
01536 }
01537 
01538 static int free_hname_fixup(void** param, int param_no)
01539 {
01540    if(*param)
01541    {
01542       if(((gparam_p)(*param))->type==GPARAM_TYPE_STR)
01543          pkg_free(((gparam_p)(*param))->v.sval.s);
01544       pkg_free(*param);
01545       *param = 0;
01546    }
01547    return 0;
01548 }
01549 
01550 /*
01551  * Convert char* method to str* parameter
01552  */
01553 static int fixup_method(void** param, int param_no)
01554 {
01555    str* s;
01556    char *p;
01557    int m;
01558    unsigned int method;
01559    
01560    s = (str*)pkg_malloc(sizeof(str));
01561    if (!s) {
01562       LM_ERR("no pkg memory left\n");
01563       return E_UNSPEC;
01564    }
01565 
01566    s->s = (char*)*param;
01567    s->len = strlen(s->s);
01568    if(s->len==0)
01569    {
01570       LM_ERR("empty method name\n");
01571       pkg_free(s);
01572       return E_UNSPEC;
01573    }
01574    m=0;
01575    p=s->s;
01576    while(*p)
01577    {
01578       if(*p=='|')
01579       {
01580          *p = ',';
01581          m=1;
01582       }
01583       p++;
01584    }
01585    if(parse_methods(s, &method)!=0)
01586    {
01587       LM_ERR("bad method names\n");
01588       pkg_free(s);
01589       return E_UNSPEC;
01590    }
01591 
01592    if(m==1)
01593    {
01594       if(method==METHOD_UNDEF || method&METHOD_OTHER)
01595       {
01596          LM_ERR("unknown method in list [%.*s/%d] - must be only defined methods\n",
01597             s->len, s->s, method);
01598          return E_UNSPEC;
01599       }
01600       LM_DBG("using id for methods [%.*s/%d]\n",
01601             s->len, s->s, method);
01602       s->s = 0;
01603       s->len = method;
01604    } else {
01605       if(method!=METHOD_UNDEF && method!=METHOD_OTHER)
01606       {
01607          LM_DBG("using id for method [%.*s/%d]\n",
01608             s->len, s->s, method);
01609          s->s = 0;
01610          s->len = method;
01611       } else
01612          LM_DBG("name for method [%.*s/%d]\n",
01613             s->len, s->s, method);
01614    }
01615 
01616    *param = (void*)s;
01617    return 0;
01618 }
01619 
01620 /*
01621  * Convert char* privacy value to corresponding bit value
01622  */
01623 static int fixup_privacy(void** param, int param_no)
01624 {
01625     str p;
01626     unsigned int val;
01627 
01628     p.s = (char*)*param;
01629     p.len = strlen(p.s);
01630 
01631     if (p.len == 0) {
01632    LM_ERR("empty privacy value\n");
01633    return E_UNSPEC;
01634     }
01635 
01636     if (parse_priv_value(p.s, p.len, &val) != p.len) {
01637    LM_ERR("invalid privacy value\n");
01638    return E_UNSPEC;
01639     }
01640     
01641     *param = (void *)(long)val;
01642     return 0;
01643 }
01644 
01645 static int add_header_fixup(void** param, int param_no)
01646 {
01647    if(param_no==1)
01648    {
01649       return fixup_spve_null(param, param_no);
01650    } else if(param_no==2) {
01651       return hname_fixup(param, param_no);
01652    } else {
01653       LM_ERR("wrong number of parameters\n");
01654       return E_UNSPEC;
01655    }
01656 }
01657 
01658 
01659 static int fixup_body_type(void** param, int param_no)
01660 {
01661    char *p;
01662    char *r;
01663    unsigned int type;
01664 
01665    if(param_no==1) {
01666       p = (char*)*param;
01667       if (p==0 || p[0]==0) {
01668          type = 0;
01669       } else {
01670          r = decode_mime_type( p, p+strlen(p) , &type);
01671          if (r==0) {
01672             LM_ERR("unsupported mime <%s>\n",p);
01673             return E_CFG;
01674          }
01675          if ( r!=p+strlen(p) ) {
01676             LM_ERR("multiple mimes not supported!\n");
01677             return E_CFG;
01678          }
01679       }
01680       pkg_free(*param);
01681       *param = (void*)(long)type;
01682    }
01683    return 0;
01684 
01685 }
01686 
01687 
01688 static int has_body_f(struct sip_msg *msg, char *type, char *str2 )
01689 {
01690    int mime;
01691 
01692    /* parse content len hdr */
01693    if ( msg->content_length==NULL &&
01694    (parse_headers(msg,HDR_CONTENTLENGTH_F, 0)==-1||msg->content_length==NULL))
01695       return -1;
01696 
01697    if (get_content_length (msg)==0) {
01698       LM_DBG("content length is zero\n");
01699       /* Nothing to see here, please move on. */
01700       return -1;
01701    }
01702 
01703    /* check type also? */
01704    if (type==0)
01705       return 1;
01706 
01707    /* the function search for and parses the Content-Type hdr */
01708    mime = parse_content_type_hdr (msg);
01709    if (mime<0) {
01710       LM_ERR("failed to extract content type hdr\n");
01711       return -1;
01712    }
01713    if (mime==0) {
01714       /* content type hdr not found -> according the RFC3261 we
01715        * assume APPLICATION/SDP  --bogdan */
01716       mime = ((TYPE_APPLICATION << 16) + SUBTYPE_SDP);
01717    }
01718    LM_DBG("content type is %d\n",mime);
01719 
01720    if ( (unsigned int)mime!=(unsigned int)(unsigned long)type )
01721       return -1;
01722 
01723    return 1;
01724 }
01725 
01726 
01727 static int is_privacy_f(struct sip_msg *msg, char *_privacy, char *str2 )
01728 {
01729     if (parse_privacy(msg) == -1)
01730    return -1;
01731 
01732     return get_privacy_values(msg) & ((unsigned int)(long)_privacy) ? 1 : -1;
01733 
01734 }
01735 
01736 static int cmp_str_f(struct sip_msg *msg, char *str1, char *str2 )
01737 {
01738    str s1;
01739    str s2;
01740    int ret;
01741 
01742    if(fixup_get_svalue(msg, (gparam_p)str1, &s1)!=0)
01743    {
01744       LM_ERR("cannot get first parameter\n");
01745       return -8;
01746    }
01747    if(fixup_get_svalue(msg, (gparam_p)str2, &s2)!=0)
01748    {
01749       LM_ERR("cannot get second parameter\n");
01750       return -8;
01751    }
01752    ret = cmp_str(&s1, &s2);
01753    if(ret==0)
01754       return 1;
01755    if(ret>0)
01756       return -1;
01757    return -2;
01758 }
01759 
01760 static int cmp_istr_f(struct sip_msg *msg, char *str1, char *str2)
01761 {
01762    str s1;
01763    str s2;
01764    int ret;
01765 
01766    if(fixup_get_svalue(msg, (gparam_p)str1, &s1)!=0)
01767    {
01768       LM_ERR("cannot get first parameter\n");
01769       return -8;
01770    }
01771    if(fixup_get_svalue(msg, (gparam_p)str2, &s2)!=0)
01772    {
01773       LM_ERR("cannot get second parameter\n");
01774       return -8;
01775    }
01776    ret = cmpi_str(&s1, &s2);
01777    if(ret==0)
01778       return 1;
01779    if(ret>0)
01780       return -1;
01781    return -2;
01782 }
01783 

Generated on Thu May 24 20:00:33 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6