modules_k/textops/textops.c

00001 /*$Id$
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_param.h"
00067 #include "../../parser/sdp/sdp.h"
00068 #include "../../lib/kcore/parse_privacy.h"
00069 #include "../../msg_translator.h"
00070 #include "../../ut.h"
00071 #include "../../dset.h"
00072 #include "../../lib/kcore/cmpapi.h"
00073 #include <stdio.h>
00074 #include <stdlib.h>
00075 #include <string.h>
00076 #include <sys/types.h> /* for regex */
00077 #include <regex.h>
00078 #include <time.h>
00079 #include <sys/time.h>
00080 
00081 #include "textops.h"
00082 #include "txt_var.h"
00083 #include "api.h"
00084 
00085 MODULE_VERSION
00086 
00087 
00088 /* RFC822-conforming dates format:
00089 
00090    %a -- abbreviated week of day name (locale), %d day of month
00091    as decimal number, %b abbreviated month name (locale), %Y
00092    year with century, %T time in 24h notation
00093 */
00094 #define TIME_FORMAT "Date: %a, %d %b %Y %H:%M:%S GMT"
00095 #define MAX_TIME 64
00096 
00097 #define AUDIO_STR "audio"
00098 #define AUDIO_STR_LEN 5
00099 
00100 
00101 static int search_body_f(struct sip_msg*, char*, char*);
00102 static int search_hf_f(struct sip_msg*, char*, char*, char*);
00103 static int replace_f(struct sip_msg*, char*, char*);
00104 static int replace_body_f(struct sip_msg*, char*, char*);
00105 static int replace_all_f(struct sip_msg*, char*, char*);
00106 static int replace_body_all_f(struct sip_msg*, char*, char*);
00107 static int replace_body_atonce_f(struct sip_msg*, char*, char*);
00108 static int subst_f(struct sip_msg*, char*, char*);
00109 static int subst_uri_f(struct sip_msg*, char*, char*);
00110 static int subst_user_f(struct sip_msg*, char*, char*);
00111 static int subst_body_f(struct sip_msg*, char*, char*);
00112 static int subst_hf_f(struct sip_msg*, char*, char*, char*);
00113 static int filter_body_f(struct sip_msg*, char*, char*);
00114 static int is_present_hf_f(struct sip_msg* msg, char* str_hf, char* foo);
00115 static int search_append_body_f(struct sip_msg*, char*, char*);
00116 static int append_to_reply_f(struct sip_msg* msg, char* key, char* str);
00117 static int append_hf_1(struct sip_msg* msg, char* str1, char* str2);
00118 static int append_hf_2(struct sip_msg* msg, char* str1, char* str2);
00119 static int insert_hf_1(struct sip_msg* msg, char* str1, char* str2);
00120 static int insert_hf_2(struct sip_msg* msg, char* str1, char* str2);
00121 static int append_urihf(struct sip_msg* msg, char* str1, char* str2);
00122 static int append_time_f(struct sip_msg* msg, char* , char *);
00123 static int append_time_request_f(struct sip_msg* msg, char* , char *);
00124 static int set_body_f(struct sip_msg* msg, char*, char *);
00125 static int set_rpl_body_f(struct sip_msg* msg, char*, char *);
00126 static int is_method_f(struct sip_msg* msg, char* , char *);
00127 static int has_body_f(struct sip_msg *msg, char *type, char *str2 );
00128 static int in_list_f(struct sip_msg* _msg, char* _subject, char* _list,
00129                      char* _sep);
00130 static int cmp_str_f(struct sip_msg *msg, char *str1, char *str2 );
00131 static int cmp_istr_f(struct sip_msg *msg, char *str1, char *str2 );
00132 static int starts_with_f(struct sip_msg *msg, char *str1, char *str2 );
00133 static int remove_hf_re_f(struct sip_msg* msg, char* key, char* foo);
00134 static int is_present_hf_re_f(struct sip_msg* msg, char* key, char* foo);
00135 static int is_audio_on_hold_f(struct sip_msg *msg, char *str1, char *str2 );
00136 static int fixup_substre(void**, int);
00137 static int hname_fixup(void** param, int param_no);
00138 static int free_hname_fixup(void** param, int param_no);
00139 static int fixup_method(void** param, int param_no);
00140 static int add_header_fixup(void** param, int param_no);
00141 static int fixup_body_type(void** param, int param_no);
00142 static int fixup_in_list(void** param, int param_no);
00143 static int fixup_free_in_list(void** param, int param_no);
00144 int fixup_regexpNL_none(void** param, int param_no);
00145 static int fixup_search_hf(void** param, int param_no);
00146 static int fixup_subst_hf(void** param, int param_no);
00147 
00148 static int mod_init(void);
00149 
00150 static tr_export_t mod_trans[] = {
00151         { {"re", sizeof("re")-1}, /* regexp class */
00152                 tr_txt_parse_re },
00153 
00154         { { 0, 0 }, 0 }
00155 };
00156 
00157 static cmd_export_t cmds[]={
00158         {"search",           (cmd_function)search_f,          1,
00159                 fixup_regexp_null, fixup_free_regexp_null,
00160                 ANY_ROUTE},
00161         {"search_body",      (cmd_function)search_body_f,     1,
00162                 fixup_regexp_null, fixup_free_regexp_null,
00163                 ANY_ROUTE},
00164         {"search_hf",      (cmd_function)search_hf_f,         3,
00165                 fixup_search_hf, 0,
00166                 ANY_ROUTE},
00167         {"search_append",    (cmd_function)search_append_f,   2,
00168                 fixup_regexp_none,fixup_free_regexp_none,
00169                 ANY_ROUTE},
00170         {"search_append_body", (cmd_function)search_append_body_f,   2,
00171                 fixup_regexp_none, fixup_free_regexp_none, 
00172                 ANY_ROUTE},
00173         {"replace",          (cmd_function)replace_f,         2,
00174                 fixup_regexp_none, fixup_free_regexp_none,
00175                 ANY_ROUTE},
00176         {"replace_body",     (cmd_function)replace_body_f,    2,
00177                 fixup_regexp_none, fixup_free_regexp_none,
00178                 ANY_ROUTE},
00179         {"replace_all",      (cmd_function)replace_all_f,     2,
00180                 fixup_regexp_none, fixup_free_regexp_none,
00181                 ANY_ROUTE},
00182         {"replace_body_all", (cmd_function)replace_body_all_f,2,
00183                 fixup_regexp_none, fixup_free_regexp_none,
00184                 ANY_ROUTE},
00185         {"replace_body_atonce", (cmd_function)replace_body_atonce_f,2,
00186                 fixup_regexpNL_none, fixup_free_regexp_none,
00187                 ANY_ROUTE},
00188         {"append_to_reply",  (cmd_function)append_to_reply_f, 1,
00189                 fixup_spve_null, 0,
00190                 REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
00191         {"append_hf",        (cmd_function)append_hf_1,       1,
00192                 add_header_fixup, 0,
00193                 ANY_ROUTE},
00194         {"append_hf",        (cmd_function)append_hf_2,       2,
00195                 add_header_fixup, 0,
00196                 ANY_ROUTE},
00197         {"insert_hf",        (cmd_function)insert_hf_1,       1, 
00198                 add_header_fixup, 0,
00199                 ANY_ROUTE},
00200         {"insert_hf",        (cmd_function)insert_hf_2,       2, 
00201                 add_header_fixup, 0,
00202                 ANY_ROUTE},
00203         {"append_urihf",     (cmd_function)append_urihf,      2,
00204                 fixup_str_str, fixup_free_str_str,
00205                 REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
00206         {"remove_hf",        (cmd_function)remove_hf_f,       1,
00207                 hname_fixup, free_hname_fixup,
00208                 ANY_ROUTE},
00209         {"remove_hf_re",     (cmd_function)remove_hf_re_f,    1,
00210                 fixup_regexp_null, fixup_free_regexp_null,
00211                 ANY_ROUTE},
00212         {"is_present_hf",    (cmd_function)is_present_hf_f,   1,
00213                 hname_fixup, free_hname_fixup,
00214                 ANY_ROUTE},
00215         {"is_present_hf_re", (cmd_function)is_present_hf_re_f,1,
00216                 fixup_regexp_null, fixup_free_regexp_null,
00217                 ANY_ROUTE},
00218         {"subst",            (cmd_function)subst_f,           1,
00219                 fixup_substre, 0,
00220                 ANY_ROUTE},
00221         {"subst_uri",        (cmd_function)subst_uri_f,       1,
00222                 fixup_substre, 0,
00223                 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
00224         {"subst_user",       (cmd_function)subst_user_f,      1,
00225                 fixup_substre, 0,
00226                 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
00227         {"subst_body",       (cmd_function)subst_body_f,      1,
00228                 fixup_substre, 0,
00229                 ANY_ROUTE},
00230         {"subst_hf",         (cmd_function)subst_hf_f,        3,
00231                 fixup_subst_hf, 0,
00232                 ANY_ROUTE},
00233         {"filter_body",      (cmd_function)filter_body_f,     1,
00234                 fixup_str_null, 0,
00235                 ANY_ROUTE},
00236         {"append_time",      (cmd_function)append_time_f,     0,
00237                 0, 0,
00238                 REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
00239         {"set_body",         (cmd_function)set_body_f,        2,
00240                 fixup_spve_spve, 0,
00241                 REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE },
00242         {"set_reply_body",     (cmd_function)set_rpl_body_f,    2,
00243                 fixup_spve_spve, 0,
00244                 REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
00245         {"is_method",        (cmd_function)is_method_f,       1,
00246                 fixup_method, 0,
00247                 ANY_ROUTE},
00248         {"has_body",         (cmd_function)has_body_f,        0,
00249                 0, 0,
00250                 ANY_ROUTE},
00251         {"has_body",         (cmd_function)has_body_f,        1, 
00252                 fixup_body_type, 0,
00253                 ANY_ROUTE},
00254         {"is_privacy",       (cmd_function)is_privacy_f,      1,
00255                 fixup_privacy, 0,
00256                 ANY_ROUTE},
00257         {"in_list", (cmd_function)in_list_f, 3, fixup_in_list,
00258                 fixup_free_in_list,
00259                 ANY_ROUTE},
00260         {"cmp_str",  (cmd_function)cmp_str_f, 2,
00261                 fixup_spve_spve, 0,
00262                 ANY_ROUTE},
00263         {"cmp_istr",  (cmd_function)cmp_istr_f, 2,
00264                 fixup_spve_spve, 0,
00265                 ANY_ROUTE},
00266         {"starts_with",  (cmd_function)starts_with_f, 2,
00267                 fixup_spve_spve, 0,
00268                 ANY_ROUTE},
00269         {"is_audio_on_hold",  (cmd_function)is_audio_on_hold_f, 0,
00270                 0, 0,
00271                 ANY_ROUTE},
00272         {"append_time_to_request", (cmd_function)append_time_request_f, 0,
00273                 0, 0,
00274                 ANY_ROUTE},
00275 
00276         {"bind_textops",      (cmd_function)bind_textops,       0, 0, 0,
00277                 0},
00278 
00279         {0,0,0,0,0,0}
00280 };
00281 
00282 
00283 struct module_exports exports= {
00284         "textops",  /* module name*/
00285         DEFAULT_DLFLAGS, /* dlopen flags */
00286         cmds,       /* exported functions */
00287         0,          /* module parameters */
00288         0,          /* exported statistics */
00289         0,          /* exported MI functions */
00290         0,          /* exported pseudo-variables */
00291         0,          /* extra processes */
00292         mod_init,   /* module initialization function */
00293         0,          /* response function */
00294         0,          /* destroy function */
00295         0,          /* per-child init function */
00296 };
00297 
00298 
00299 static int mod_init(void)
00300 {
00301         return 0;
00302 }
00303 
00304 int mod_register(char *path, int *dlflags, void *p1, void *p2)
00305 {
00306         return register_trans_mod(path, mod_trans);
00307 }
00308 
00309 static char *get_header(struct sip_msg *msg)
00310 {
00311         return msg->buf+msg->first_line.len;
00312 }
00313 
00314 
00315 
00316 int search_f(struct sip_msg* msg, char* key, char* str2)
00317 {
00318         /*we registered only 1 param, so we ignore str2*/
00319         regmatch_t pmatch;
00320 
00321         if (regexec((regex_t*) key, msg->buf, 1, &pmatch, 0)!=0) return -1;
00322         return 1;
00323 }
00324 
00325 
00326 static int search_body_f(struct sip_msg* msg, char* key, char* str2)
00327 {
00328         str body;
00329         /*we registered only 1 param, so we ignore str2*/
00330         regmatch_t pmatch;
00331 
00332         body.s = get_body(msg);
00333         if (body.s==0) {
00334                 LM_ERR("failed to get the message body\n");
00335                 return -1;
00336         }
00337         body.len = msg->len -(int)(body.s-msg->buf);
00338         if (body.len==0) {
00339                 LM_DBG("message body has zero length\n");
00340                 return -1;
00341         }
00342 
00343         if (regexec((regex_t*) key, body.s, 1, &pmatch, 0)!=0) return -1;
00344         return 1;
00345 }
00346 
00347 
00348 int search_append_f(struct sip_msg* msg, char* key, char* str2)
00349 {
00350         struct lump* l;
00351         regmatch_t pmatch;
00352         char* s;
00353         int len;
00354         char *begin;
00355         int off;
00356 
00357         begin=get_header(msg); /* msg->orig/buf previously .. uri problems */
00358         off=begin-msg->buf;
00359 
00360         if (regexec((regex_t*) key, begin, 1, &pmatch, 0)!=0) return -1;
00361         if (pmatch.rm_so!=-1){
00362                 if ((l=anchor_lump(msg, off+pmatch.rm_eo, 0, 0))==0)
00363                         return -1;
00364                 len=strlen(str2);
00365                 s=pkg_malloc(len);
00366                 if (s==0){
00367                         LM_ERR("memory allocation failure\n");
00368                         return -1;
00369                 }
00370                 memcpy(s, str2, len); 
00371                 if (insert_new_lump_after(l, s, len, 0)==0){
00372                         LM_ERR("could not insert new lump\n");
00373                         pkg_free(s);
00374                         return -1;
00375                 }
00376                 return 1;
00377         }
00378         return -1;
00379 }
00380 
00381 static int search_append_body_f(struct sip_msg* msg, char* key, char* str2)
00382 {
00383         struct lump* l;
00384         regmatch_t pmatch;
00385         char* s;
00386         int len;
00387         int off;
00388         str body;
00389 
00390         body.s = get_body(msg);
00391         if (body.s==0) {
00392                 LM_ERR("failed to get the message body\n");
00393                 return -1;
00394         }
00395         body.len = msg->len -(int)(body.s-msg->buf);
00396         if (body.len==0) {
00397                 LM_DBG("message body has zero length\n");
00398                 return -1;
00399         }
00400 
00401         off=body.s-msg->buf;
00402 
00403         if (regexec((regex_t*) key, body.s, 1, &pmatch, 0)!=0) return -1;
00404         if (pmatch.rm_so!=-1){
00405                 if ((l=anchor_lump(msg, off+pmatch.rm_eo, 0, 0))==0)
00406                         return -1;
00407                 len=strlen(str2);
00408                 s=pkg_malloc(len);
00409                 if (s==0){
00410                         LM_ERR("memory allocation failure\n");
00411                         return -1;
00412                 }
00413                 memcpy(s, str2, len); 
00414                 if (insert_new_lump_after(l, s, len, 0)==0){
00415                         LM_ERR("could not insert new lump\n");
00416                         pkg_free(s);
00417                         return -1;
00418                 }
00419                 return 1;
00420         }
00421         return -1;
00422 }
00423 
00424 
00425 static int replace_all_f(struct sip_msg* msg, char* key, char* str2)
00426 {
00427         struct lump* l;
00428         regmatch_t pmatch;
00429         char* s;
00430         int len;
00431         char* begin;
00432         int off;
00433         int ret;
00434         int eflags;
00435 
00436         begin = get_header(msg);
00437         ret=-1; /* pessimist: we will not find any */
00438         len=strlen(str2);
00439         eflags=0; /* match ^ at the beginning of the string*/
00440 
00441         while (begin<msg->buf+msg->len 
00442                                 && regexec((regex_t*) key, begin, 1, &pmatch, eflags)==0) {
00443                 off=begin-msg->buf;
00444                 if (pmatch.rm_so==-1){
00445                         LM_ERR("offset unknown\n");
00446                         return -1;
00447                 }
00448                 if (pmatch.rm_so==pmatch.rm_eo){
00449                         LM_ERR("matched string is empty... invalid regexp?\n");
00450                         return -1;
00451                 }
00452                 if ((l=del_lump(msg, pmatch.rm_so+off,
00453                                                 pmatch.rm_eo-pmatch.rm_so, 0))==0) {
00454                         LM_ERR("del_lump failed\n");
00455                         return -1;
00456                 }
00457                 s=pkg_malloc(len);
00458                 if (s==0){
00459                         LM_ERR("memory allocation failure\n");
00460                         return -1;
00461                 }
00462                 memcpy(s, str2, len); 
00463                 if (insert_new_lump_after(l, s, len, 0)==0){
00464                         LM_ERR("could not insert new lump\n");
00465                         pkg_free(s);
00466                         return -1;
00467                 }
00468                 /* new cycle */
00469                 begin=begin+pmatch.rm_eo;
00470                 /* is it still a string start */
00471                 if (*(begin-1)=='\n' || *(begin-1)=='\r')
00472                         eflags&=~REG_NOTBOL;
00473                 else
00474                         eflags|=REG_NOTBOL;
00475                 ret=1;
00476         } /* while found ... */
00477         return ret;
00478 }
00479 
00480 static int do_replace_body_f(struct sip_msg* msg, char* key, char* str2, int nobol)
00481 {
00482         struct lump* l;
00483         regmatch_t pmatch;
00484         char* s;
00485         int len;
00486         char* begin;
00487         int off;
00488         int ret;
00489         int eflags;
00490         str body;
00491 
00492         body.s = get_body(msg);
00493         if (body.s==0) {
00494                 LM_ERR("failed to get the message body\n");
00495                 return -1;
00496         }
00497         body.len = msg->len -(int)(body.s-msg->buf);
00498         if (body.len==0) {
00499                 LM_DBG("message body has zero length\n");
00500                 return -1;
00501         }
00502 
00503         begin=body.s;
00504         ret=-1; /* pessimist: we will not find any */
00505         len=strlen(str2);
00506         eflags=0; /* match ^ at the beginning of the string*/
00507 
00508         while (begin<msg->buf+msg->len 
00509                                 && regexec((regex_t*) key, begin, 1, &pmatch, eflags)==0) {
00510                 off=begin-msg->buf;
00511                 if (pmatch.rm_so==-1){
00512                         LM_ERR("offset unknown\n");
00513                         return -1;
00514                 }
00515                 if (pmatch.rm_so==pmatch.rm_eo){
00516                         LM_ERR("matched string is empty... invalid regexp?\n");
00517                         return -1;
00518                 }
00519                 if ((l=del_lump(msg, pmatch.rm_so+off,
00520                                                 pmatch.rm_eo-pmatch.rm_so, 0))==0) {
00521                         LM_ERR("del_lump failed\n");
00522                         return -1;
00523                 }
00524                 s=pkg_malloc(len);
00525                 if (s==0){
00526                         LM_ERR("memory allocation failure\n");
00527                         return -1;
00528                 }
00529                 memcpy(s, str2, len); 
00530                 if (insert_new_lump_after(l, s, len, 0)==0){
00531                         LM_ERR("could not insert new lump\n");
00532                         pkg_free(s);
00533                         return -1;
00534                 }
00535                 /* new cycle */
00536                 begin=begin+pmatch.rm_eo;
00537                 /* is it still a string start */
00538                 if (nobol && (*(begin-1)=='\n' || *(begin-1)=='\r'))
00539                         eflags&=~REG_NOTBOL;
00540                 else
00541                         eflags|=REG_NOTBOL;
00542                 ret=1;
00543         } /* while found ... */
00544         return ret;
00545 }
00546 
00547 static int replace_body_all_f(struct sip_msg* msg, char* key, char* str2)
00548 {
00549         return do_replace_body_f(msg, key, str2, 1);
00550 }
00551 
00552 static int replace_body_atonce_f(struct sip_msg* msg, char* key, char* str2)
00553 {
00554         return do_replace_body_f(msg, key, str2, 0);
00555 }
00556 
00557 static int replace_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 
00566         begin=get_header(msg); /* msg->orig previously .. uri problems */
00567 
00568         if (regexec((regex_t*) key, begin, 1, &pmatch, 0)!=0) return -1;
00569         off=begin-msg->buf;
00570 
00571         if (pmatch.rm_so!=-1){
00572                 if ((l=del_lump(msg, pmatch.rm_so+off,
00573                                                 pmatch.rm_eo-pmatch.rm_so, 0))==0)
00574                         return -1;
00575                 len=strlen(str2);
00576                 s=pkg_malloc(len);
00577                 if (s==0){
00578                         LM_ERR("memory allocation failure\n");
00579                         return -1;
00580                 }
00581                 memcpy(s, str2, len); 
00582                 if (insert_new_lump_after(l, s, len, 0)==0){
00583                         LM_ERR("could not insert new lump\n");
00584                         pkg_free(s);
00585                         return -1;
00586                 }
00587                 
00588                 return 1;
00589         }
00590         return -1;
00591 }
00592 
00593 static int replace_body_f(struct sip_msg* msg, char* key, char* str2)
00594 {
00595         struct lump* l;
00596         regmatch_t pmatch;
00597         char* s;
00598         int len;
00599         char* begin;
00600         int off;
00601         str body;
00602 
00603         body.s = get_body(msg);
00604         if (body.s==0) {
00605                 LM_ERR("failed to get the message body\n");
00606                 return -1;
00607         }
00608         body.len = msg->len -(int)(body.s-msg->buf);
00609         if (body.len==0) {
00610                 LM_DBG("message body has zero length\n");
00611                 return -1;
00612         }
00613 
00614         begin=body.s; /* msg->orig previously .. uri problems */
00615 
00616         if (regexec((regex_t*) key, begin, 1, &pmatch, 0)!=0) return -1;
00617         off=begin-msg->buf;
00618 
00619         if (pmatch.rm_so!=-1){
00620                 if ((l=del_lump(msg, pmatch.rm_so+off,
00621                                                 pmatch.rm_eo-pmatch.rm_so, 0))==0)
00622                         return -1;
00623                 len=strlen(str2);
00624                 s=pkg_malloc(len);
00625                 if (s==0){
00626                         LM_ERR("memory allocation failure\n");
00627                         return -1;
00628                 }
00629                 memcpy(s, str2, len); 
00630                 if (insert_new_lump_after(l, s, len, 0)==0){
00631                         LM_ERR("could not insert new lump\n");
00632                         pkg_free(s);
00633                         return -1;
00634                 }
00635                 
00636                 return 1;
00637         }
00638         return -1;
00639 }
00640 
00641 
00642 /* sed-perl style re: s/regular expression/replacement/flags */
00643 static int subst_f(struct sip_msg* msg, char*  subst, char* ignored)
00644 {
00645         struct lump* l;
00646         struct replace_lst* lst;
00647         struct replace_lst* rpl;
00648         char* begin;
00649         struct subst_expr* se;
00650         int off;
00651         int ret;
00652         int nmatches;
00653         
00654         se=(struct subst_expr*)subst;
00655         begin=get_header(msg);  /* start after first line to avoid replacing
00656                                                            the uri */
00657         off=begin-msg->buf;
00658         ret=-1;
00659         if ((lst=subst_run(se, begin, msg, &nmatches))==0)
00660                 goto error; /* not found */
00661         for (rpl=lst; rpl; rpl=rpl->next){
00662                 LM_DBG("%s: replacing at offset %d [%.*s] with [%.*s]\n",
00663                                 exports.name, rpl->offset+off,
00664                                 rpl->size, rpl->offset+off+msg->buf,
00665                                 rpl->rpl.len, rpl->rpl.s);
00666                 if ((l=del_lump(msg, rpl->offset+off, rpl->size, 0))==0)
00667                         goto error;
00668                 /* hack to avoid re-copying rpl, possible because both 
00669                  * replace_lst & lumps use pkg_malloc */
00670                 if (insert_new_lump_after(l, rpl->rpl.s, rpl->rpl.len, 0)==0){
00671                         LM_ERR("%s: could not insert new lump\n", exports.name);
00672                         goto error;
00673                 }
00674                 /* hack continued: set rpl.s to 0 so that replace_lst_free will
00675                  * not free it */
00676                 rpl->rpl.s=0;
00677                 rpl->rpl.len=0;
00678         }
00679         ret=1;
00680 error:
00681         LM_DBG("lst was %p\n", lst);
00682         if (lst) replace_lst_free(lst);
00683         if (nmatches<0)
00684                 LM_ERR("%s: subst_run failed\n", exports.name);
00685         return ret;
00686 }
00687 
00688 
00689 
00690 /* sed-perl style re: s/regular expression/replacement/flags, like
00691  *  subst but works on the message uri */
00692 static int subst_uri_f(struct sip_msg* msg, char*  subst, char* ignored)
00693 {
00694         char* tmp;
00695         int len;
00696         char c;
00697         struct subst_expr* se;
00698         str* result;
00699         
00700         se=(struct subst_expr*)subst;
00701         if (msg->new_uri.s){
00702                 len=msg->new_uri.len;
00703                 tmp=msg->new_uri.s;
00704         }else{
00705                 tmp=msg->first_line.u.request.uri.s;
00706                 len     =msg->first_line.u.request.uri.len;
00707         };
00708         /* ugly hack: 0 s[len], and restore it afterward
00709          * (our re functions require 0 term strings), we can do this
00710          * because we always alloc len+1 (new_uri) and for first_line, the
00711          * message will always be > uri.len */
00712         c=tmp[len];
00713         tmp[len]=0;
00714         result=subst_str(tmp, msg, se, 0); /* pkg malloc'ed result */
00715         tmp[len]=c;
00716         if (result){
00717                 LM_DBG("%s match - old uri= [%.*s], new uri= [%.*s]\n",
00718                                 exports.name, len, tmp,
00719                                 (result->len)?result->len:0,(result->s)?result->s:"");
00720                 if (msg->new_uri.s) pkg_free(msg->new_uri.s);
00721                 msg->new_uri=*result;
00722                 msg->parsed_uri_ok=0; /* reset "use cached parsed uri" flag */
00723                 ruri_mark_new();
00724                 pkg_free(result); /* free str* pointer */
00725                 return 1; /* success */
00726         }
00727         return -1; /* false, no subst. made */
00728 }
00729         
00730 
00731 
00732 /* sed-perl style re: s/regular expression/replacement/flags, like
00733  *  subst but works on the user part of the uri */
00734 static int subst_user_f(struct sip_msg* msg, char*  subst, char* ignored)
00735 {
00736         int rval;
00737         str* result;
00738         struct subst_expr* se;
00739         struct action act;
00740         struct run_act_ctx h;
00741         str user;
00742         char c;
00743         int nmatches;
00744 
00745         c=0;
00746         if (parse_sip_msg_uri(msg)<0){
00747                 return -1; /* error, bad uri */
00748         }
00749         if (msg->parsed_uri.user.s==0){
00750                 /* no user in uri */
00751                 user.s="";
00752                 user.len=0;
00753         }else{
00754                 user=msg->parsed_uri.user;
00755                 c=user.s[user.len];
00756                 user.s[user.len]=0;
00757         }
00758         se=(struct subst_expr*)subst;
00759         result=subst_str(user.s, msg, se, &nmatches);/* pkg malloc'ed result */
00760         if (c)  user.s[user.len]=c;
00761         if (result == NULL) {
00762                 if (nmatches<0)
00763                         LM_ERR("subst_user(): subst_str() failed\n");
00764                 return -1;
00765         }
00766         /* result->s[result->len] = '\0';  --subst_str returns 0-term strings */
00767         memset(&act, 0, sizeof(act)); /* be on the safe side */
00768         act.type = SET_USER_T;
00769         act.val[0].type = STRING_ST;
00770         act.val[0].u.string = result->s;
00771         init_run_actions_ctx(&h);
00772         rval = do_action(&h, &act, msg);
00773         pkg_free(result->s);
00774         pkg_free(result);
00775         return rval;
00776 }
00777 
00778 
00779 /* sed-perl style re: s/regular expression/replacement/flags */
00780 static int subst_body_f(struct sip_msg* msg, char*  subst, char* ignored)
00781 {
00782         struct lump* l;
00783         struct replace_lst* lst;
00784         struct replace_lst* rpl;
00785         char* begin;
00786         struct subst_expr* se;
00787         int off;
00788         int ret;
00789         int nmatches;
00790         str body;
00791 
00792         body.s = get_body(msg);
00793         if (body.s==0) {
00794                 LM_ERR("failed to get the message body\n");
00795                 return -1;
00796         }
00797         body.len = msg->len -(int)(body.s-msg->buf);
00798         if (body.len==0) {
00799                 LM_DBG("message body has zero length\n");
00800                 return -1;
00801         }
00802         
00803         se=(struct subst_expr*)subst;
00804         begin=body.s;
00805         
00806         off=begin-msg->buf;
00807         ret=-1;
00808         if ((lst=subst_run(se, begin, msg, &nmatches))==0)
00809                 goto error; /* not found */
00810         for (rpl=lst; rpl; rpl=rpl->next){
00811                 LM_DBG("%s replacing at offset %d [%.*s] with [%.*s]\n",
00812                                 exports.name, rpl->offset+off,
00813                                 rpl->size, rpl->offset+off+msg->buf,
00814                                 rpl->rpl.len, rpl->rpl.s);
00815                 if ((l=del_lump(msg, rpl->offset+off, rpl->size, 0))==0)
00816                         goto error;
00817                 /* hack to avoid re-copying rpl, possible because both 
00818                  * replace_lst & lumps use pkg_malloc */
00819                 if (insert_new_lump_after(l, rpl->rpl.s, rpl->rpl.len, 0)==0){
00820                         LM_ERR("%s could not insert new lump\n",
00821                                         exports.name);
00822                         goto error;
00823                 }
00824                 /* hack continued: set rpl.s to 0 so that replace_lst_free will
00825                  * not free it */
00826                 rpl->rpl.s=0;
00827                 rpl->rpl.len=0;
00828         }
00829         ret=1;
00830 error:
00831         LM_DBG("lst was %p\n", lst);
00832         if (lst) replace_lst_free(lst);
00833         if (nmatches<0)
00834                 LM_ERR("%s subst_run failed\n", exports.name);
00835         return ret;
00836 }
00837 
00838 
00839 static inline int find_line_start(char *text, unsigned int text_len,
00840                                   char **buf, unsigned int *buf_len)
00841 {
00842     char *ch, *start;
00843     unsigned int len;
00844 
00845     start = *buf;
00846     len = *buf_len;
00847 
00848     while (text_len <= len) {
00849         if (strncmp(text, start, text_len) == 0) {
00850             *buf = start;
00851             *buf_len = len;
00852             return 1;
00853         }
00854         if ((ch = memchr(start, 13, len - 1))) {
00855             if (*(ch + 1) != 10) {
00856                 LM_ERR("No LF after CR\n");
00857                 return 0;
00858             }
00859             len = len - (ch - start + 2);
00860             start = ch + 2;
00861         } else {
00862             LM_ERR("No CRLF found\n");
00863             return 0;
00864         }
00865     }
00866     return 0;
00867 }
00868 
00869 
00870 /* Filters multipart/mixed body by leaving out everything else except
00871  * first body part of given content type. */
00872 static int filter_body_f(struct sip_msg* msg, char* _content_type,
00873                          char* ignored)
00874 {
00875         char *start;
00876         unsigned int len;
00877         str *content_type, body, params, boundary;
00878         param_hooks_t hooks;
00879         param_t *p, *list;
00880         unsigned int mime;
00881 
00882         body.s = get_body(msg);
00883         if (body.s == 0) {
00884                 LM_ERR("failed to get the message body\n");
00885                 return -1;
00886         }
00887         body.len = msg->len - (int)(body.s - msg->buf);
00888         if (body.len == 0) {
00889                 LM_DBG("message body has zero length\n");
00890                 return -1;
00891         }
00892         
00893         content_type = (str *)_content_type;
00894 
00895         mime = parse_content_type_hdr(msg);
00896         if (mime <= 0) {
00897             LM_ERR("failed to parse Content-Type hdr\n");
00898             return -1;
00899         }
00900         if (mime != ((TYPE_MULTIPART << 16) + SUBTYPE_MIXED)) {
00901             LM_ERR("content type is not multipart/mixed\n");
00902             return -1;
00903         }
00904 
00905         params.s = memchr(msg->content_type->body.s, ';', 
00906                           msg->content_type->body.len);
00907         if (params.s == NULL) {
00908             LM_ERR("Content-Type hdr has no params\n");
00909             return -1;
00910         }
00911         params.len = msg->content_type->body.len - 
00912             (params.s - msg->content_type->body.s);
00913         if (parse_params(&params, CLASS_ANY, &hooks, &list) < 0) {
00914             LM_ERR("while parsing Content-Type params\n");
00915             return -1;
00916         }
00917         boundary.s = NULL;
00918         boundary.len = 0;
00919         for (p = list; p; p = p->next) {
00920             if ((p->name.len == 8)
00921                 && (strncasecmp(p->name.s, "boundary", 8) == 0)) {
00922                 boundary.s = pkg_malloc(p->body.len + 2);
00923                 if (boundary.s == NULL) {
00924                     free_params(list);
00925                     LM_ERR("no memory for boundary string\n");
00926                     return -1;
00927                 }
00928                 *(boundary.s) = '-';
00929                 *(boundary.s + 1) = '-';
00930                 memcpy(boundary.s + 2, p->body.s, p->body.len);
00931                 boundary.len = 2 + p->body.len;
00932                 LM_DBG("boundary is <%.*s>\n", boundary.len, boundary.s);
00933                 break;
00934             }
00935         }
00936         free_params(list);
00937         if (boundary.s == NULL) {
00938             LM_ERR("no mandatory param \";boundary\"\n");
00939             return -1;
00940         }
00941         
00942         start = body.s;
00943         len = body.len;
00944         
00945         while (find_line_start("Content-Type: ", 14, &start, &len)) {
00946             start = start + 14;
00947             len = len - 14;
00948             if (len > content_type->len + 2) {
00949                 if (strncasecmp(start, content_type->s, content_type->len)
00950                     == 0) {
00951                     LM_DBG("found content type %.*s\n",
00952                             content_type->len, content_type->s);
00953                     start = start + content_type->len;
00954                     if ((*start != 13) || (*(start + 1) != 10)) {
00955                         LM_ERR("no CRLF found after content type\n");
00956                         goto err;
00957                     }
00958                     start = start + 2;
00959                     len = len - content_type->len - 2;
00960                     while ((len > 0) && ((*start == 13) || (*start == 10))) {
00961                         len = len - 1;
00962                         start = start + 1;
00963                     }
00964                     if (del_lump(msg, body.s - msg->buf, start - body.s, 0)
00965                         == 0) {
00966                         LM_ERR("deleting lump <%.*s> failed\n",
00967                                (int)(start - body.s), body.s);
00968                         goto err;
00969                     }
00970                     if (find_line_start(boundary.s, boundary.len, &start,
00971                                         &len)) { 
00972                         if (del_lump(msg, start - msg->buf, len, 0) == 0) {
00973                             LM_ERR("deleting lump <%.*s> failed\n",
00974                                    len, start);
00975                             goto err;
00976                         } else {
00977                             pkg_free(boundary.s);
00978                             return 1;
00979                         }
00980                     } else {
00981                         LM_ERR("boundary not found after content\n");
00982                         goto err;
00983                     }
00984                 }
00985             } else {
00986                 pkg_free(boundary.s);
00987                 return -1;
00988             }
00989         }
00990  err:
00991         pkg_free(boundary.s);
00992         return -1;
00993 }
00994 
00995 
00996 int remove_hf_f(struct sip_msg* msg, char* str_hf, char* foo)
00997 {
00998         struct hdr_field *hf;
00999         struct lump* l;
01000         int cnt;
01001         gparam_p gp;
01002 
01003         gp = (gparam_p)str_hf;
01004         cnt=0;
01005 
01006         /* we need to be sure we have seen all HFs */
01007         parse_headers(msg, HDR_EOH_F, 0);
01008         for (hf=msg->headers; hf; hf=hf->next) {
01009                 /* for well known header names str_hf->s will be set to NULL 
01010                    during parsing of kamailio.cfg and str_hf->len contains 
01011                    the header type */
01012                 if(gp->type==GPARAM_TYPE_INT)
01013                 {
01014                         if (gp->v.i!=hf->type)
01015                                 continue;
01016                 } else {
01017                         if (hf->name.len!=gp->v.str.len)
01018                                 continue;
01019                         if (cmp_hdrname_str(&hf->name, &gp->v.str)!=0)
01020                                 continue;
01021                 }
01022                 l=del_lump(msg, hf->name.s-msg->buf, hf->len, 0);
01023                 if (l==0) {
01024                         LM_ERR("no memory\n");
01025                         return -1;
01026                 }
01027                 cnt++;
01028         }
01029         return cnt==0 ? -1 : 1;
01030 }
01031 
01032 static int remove_hf_re_f(struct sip_msg* msg, char* key, char* foo)
01033 {
01034         struct hdr_field *hf;
01035         struct lump* l;
01036         int cnt;
01037         regex_t *re;
01038         char c;
01039         regmatch_t pmatch;
01040 
01041         re = (regex_t*)key;
01042         cnt=0;
01043 
01044         /* we need to be sure we have seen all HFs */
01045         parse_headers(msg, HDR_EOH_F, 0);
01046         for (hf=msg->headers; hf; hf=hf->next)
01047         {
01048                 c = hf->name.s[hf->name.len];
01049                 hf->name.s[hf->name.len] = '\0';
01050                 if (regexec(re, hf->name.s, 1, &pmatch, 0)!=0)
01051                 {
01052                         hf->name.s[hf->name.len] = c;
01053                         continue;
01054                 }
01055                 hf->name.s[hf->name.len] = c;
01056                 l=del_lump(msg, hf->name.s-msg->buf, hf->len, 0);
01057                 if (l==0)
01058                 {
01059                         LM_ERR("cannot remove header\n");
01060                         return -1;
01061                 }
01062                 cnt++;
01063         }
01064 
01065         return cnt==0 ? -1 : 1;
01066 }
01067 
01068 static int is_present_hf_f(struct sip_msg* msg, char* str_hf, char* foo)
01069 {
01070         struct hdr_field *hf;
01071         gparam_p gp;
01072 
01073         gp = (gparam_p)str_hf;
01074 
01075         /* we need to be sure we have seen all HFs */
01076         parse_headers(msg, HDR_EOH_F, 0);
01077         for (hf=msg->headers; hf; hf=hf->next) {
01078                 if(gp->type==GPARAM_TYPE_INT)
01079                 {
01080                         if (gp->v.i!=hf->type)
01081                                 continue;
01082                 } else {
01083                         if (hf->name.len!=gp->v.str.len)
01084                                 continue;
01085                         if (cmp_hdrname_str(&hf->name,&gp->v.str)!=0)
01086                                 continue;
01087                 }
01088                 return 1;
01089         }
01090         return -1;
01091 }
01092 
01093 static int is_present_hf_re_f(struct sip_msg* msg, char* key, char* foo)
01094 {
01095         struct hdr_field *hf;
01096         regex_t *re;
01097         regmatch_t pmatch;
01098         char c;
01099 
01100         re = (regex_t*)key;
01101 
01102         /* we need to be sure we have seen all HFs */
01103         parse_headers(msg, HDR_EOH_F, 0);
01104         for (hf=msg->headers; hf; hf=hf->next)
01105         {
01106                 c = hf->name.s[hf->name.len];
01107                 hf->name.s[hf->name.len] = '\0';
01108                 if (regexec(re, hf->name.s, 1, &pmatch, 0)!=0)
01109                 {
01110                         hf->name.s[hf->name.len] = c;
01111                         continue;
01112                 }
01113                 hf->name.s[hf->name.len] = c;
01114                 return 1;
01115         }
01116 
01117         return -1;
01118 }
01119 
01120 
01121 static int fixup_substre(void** param, int param_no)
01122 {
01123         struct subst_expr* se;
01124         str subst;
01125 
01126         LM_DBG("%s module -- fixing %s\n", exports.name, (char*)(*param));
01127         if (param_no!=1) return 0;
01128         subst.s=*param;
01129         subst.len=strlen(*param);
01130         se=subst_parser(&subst);
01131         if (se==0){
01132                 LM_ERR("%s: bad subst. re %s\n", exports.name, 
01133                                 (char*)*param);
01134                 return E_BAD_RE;
01135         }
01136         /* don't free string -- needed for specifiers */
01137         /* pkg_free(*param); */
01138         /* replace it with the compiled subst. re */
01139         *param=se;
01140         return 0;
01141 }
01142 
01143 
01144 static int append_time_f(struct sip_msg* msg, char* p1, char *p2)
01145 {
01146 
01147 
01148         size_t len;
01149         char time_str[MAX_TIME];
01150         time_t now;
01151         struct tm *bd_time;
01152 
01153         now=time(0);
01154 
01155         bd_time=gmtime(&now);
01156         if (bd_time==NULL) {
01157                 LM_ERR("gmtime failed\n");
01158                 return -1;
01159         }
01160 
01161         len=strftime(time_str, MAX_TIME, TIME_FORMAT, bd_time);
01162         if (len>MAX_TIME-2 || len==0) {
01163                 LM_ERR("unexpected time length\n");
01164                 return -1;
01165         }
01166 
01167         time_str[len]='\r';
01168         time_str[len+1]='\n';
01169 
01170 
01171         if (add_lump_rpl(msg, time_str, len+2, LUMP_RPL_HDR)==0)
01172         {
01173                 LM_ERR("unable to add lump\n");
01174                 return -1;
01175         }
01176 
01177         return 1;
01178 }
01179 
01180 static int append_time_request_f(struct sip_msg* msg, char* p1, char *p2)
01181 {
01182         str time_str = {0, 0};
01183         time_t now;
01184         struct tm *bd_time;
01185         struct hdr_field *hf = msg->headers;
01186         struct lump *anchor = anchor_lump(msg, hf->name.s + hf->len - msg->buf, 0, 0);
01187 
01188         now=time(0);
01189 
01190         bd_time=gmtime(&now);
01191         if (bd_time==NULL) {
01192                 LM_ERR("gmtime failed\n");
01193                 goto error;
01194         }
01195 
01196         time_str.s = pkg_malloc(MAX_TIME);
01197         time_str.len=strftime(time_str.s, MAX_TIME, TIME_FORMAT, bd_time);
01198         if (time_str.len>MAX_TIME-2 || time_str.len==0) {
01199                 LM_ERR("unexpected time length\n");
01200                 goto error;
01201         }
01202 
01203         time_str.s[time_str.len++]='\r';
01204         time_str.s[time_str.len++]='\n';
01205 
01206         if (anchor == NULL)
01207         {
01208                 LM_ERR("Problem with getting anchor");
01209                 goto error;
01210         }
01211 
01212         if (insert_new_lump_after(anchor, time_str.s, time_str.len, 0) == 0)
01213         {
01214                 LM_ERR("unable to add lump\n");
01215                 goto error;
01216         }
01217 
01218         return 1;
01219 error:
01220         if (time_str.s != NULL)
01221                 pkg_free(time_str.s);
01222 
01223         return -1;
01224 }
01225 
01226 static int set_body_f(struct sip_msg* msg, char* p1, char* p2)
01227 {
01228         struct lump *anchor;
01229         char* buf;
01230         int len;
01231         char* value_s;
01232         int value_len;
01233         str body = {0,0};
01234         str nb = {0,0};
01235         str nc = {0,0};
01236 
01237         if(p1==0 || p2==0)
01238         {
01239                 LM_ERR("invalid parameters\n");
01240                 return -1;
01241         }
01242 
01243         if(fixup_get_svalue(msg, (gparam_p)p1, &nb)!=0)
01244         {
01245                 LM_ERR("unable to get p1\n");
01246                 return -1;
01247         }
01248         if(nb.s==NULL || nb.len == 0)
01249         {
01250                 LM_ERR("invalid body parameter\n");
01251                 return -1;
01252         }
01253         if(fixup_get_svalue(msg, (gparam_p)p2, &nc)!=0)
01254         {
01255                 LM_ERR("unable to get p2\n");
01256                 return -1;
01257         }
01258         if(nc.s==NULL || nc.len == 0)
01259         {
01260                 LM_ERR("invalid content-type parameter\n");
01261                 return -1;
01262         }
01263 
01264         body.len = 0;
01265         body.s = get_body(msg);
01266         if (body.s==0)
01267         {
01268                 LM_ERR("malformed sip message\n");
01269                 return -1;
01270         }
01271 
01272         del_nonshm_lump( &(msg->body_lumps) );
01273         msg->body_lumps = NULL;
01274 
01275         if (msg->content_length) 
01276         {
01277                 body.len = get_content_length( msg );
01278                 if(body.len > 0)
01279                 {
01280                         if(body.s+body.len>msg->buf+msg->len)
01281                         {
01282                                 LM_ERR("invalid content length: %d\n", body.len);
01283                                 return -1;
01284                         }
01285                         if(del_lump(msg, body.s - msg->buf, body.len, 0) == 0)
01286                         {
01287                                 LM_ERR("cannot delete existing body");
01288                                 return -1;
01289                         }
01290                 }
01291         }
01292 
01293         anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0, 0);
01294 
01295         if (anchor == 0)
01296         {
01297                 LM_ERR("failed to get anchor\n");
01298                 return -1;
01299         } 
01300 
01301         if (msg->content_length==0)
01302         {
01303                 /* need to add Content-Length */
01304                 len = nb.len;
01305                 value_s=int2str(len, &value_len);
01306                 LM_DBG("content-length: %d (%s)\n", value_len, value_s);
01307 
01308                 len=CONTENT_LENGTH_LEN+value_len+CRLF_LEN;
01309                 buf=pkg_malloc(sizeof(char)*(len));
01310 
01311                 if (buf==0)
01312                 {
01313                         LM_ERR("out of pkg memory\n");
01314                         return -1;
01315                 }
01316 
01317                 memcpy(buf, CONTENT_LENGTH, CONTENT_LENGTH_LEN);
01318                 memcpy(buf+CONTENT_LENGTH_LEN, value_s, value_len);
01319                 memcpy(buf+CONTENT_LENGTH_LEN+value_len, CRLF, CRLF_LEN);
01320                 if (insert_new_lump_after(anchor, buf, len, 0) == 0)
01321                 {
01322                         LM_ERR("failed to insert content-length lump\n");
01323                         pkg_free(buf);
01324                         return -1;
01325                 }
01326         }
01327 
01328         /* add content-type */
01329         if(msg->content_type==NULL || msg->content_type->body.len!=nc.len
01330                         || strncmp(msg->content_type->body.s, nc.s, nc.len)!=0)
01331         {
01332                 if(msg->content_type!=NULL)
01333                         if(del_lump(msg, msg->content_type->name.s-msg->buf,
01334                                                 msg->content_type->len, 0) == 0)
01335                         {
01336                                 LM_ERR("failed to delete content type\n");
01337                                 return -1;
01338                         }
01339                 value_len = nc.len;
01340                 len=sizeof("Content-Type: ") - 1 + value_len + CRLF_LEN;
01341                 buf=pkg_malloc(sizeof(char)*(len));
01342 
01343                 if (buf==0)
01344                 {
01345                         LM_ERR("out of pkg memory\n");
01346                         return -1;
01347                 }
01348                 memcpy(buf, "Content-Type: ", sizeof("Content-Type: ") - 1);
01349                 memcpy(buf+sizeof("Content-Type: ") - 1, nc.s, value_len);
01350                 memcpy(buf+sizeof("Content-Type: ") - 1 + value_len, CRLF, CRLF_LEN);
01351                 if (insert_new_lump_after(anchor, buf, len, 0) == 0)
01352                 {
01353                         LM_ERR("failed to insert content-type lump\n");
01354                         pkg_free(buf);
01355                         return -1;
01356                 }
01357         }       
01358         anchor = anchor_lump(msg, body.s - msg->buf, 0, 0);
01359 
01360         if (anchor == 0)
01361         {
01362                 LM_ERR("failed to get body anchor\n");
01363                 return -1;
01364         } 
01365 
01366         buf=pkg_malloc(sizeof(char)*(nb.len));
01367         if (buf==0)
01368         {
01369                 LM_ERR("out of pkg memory\n");
01370                 return -1;
01371         }
01372         memcpy(buf, nb.s, nb.len);
01373         if (insert_new_lump_after(anchor, buf, nb.len, 0) == 0)
01374         {
01375                 LM_ERR("failed to insert body lump\n");
01376                 pkg_free(buf);
01377                 return -1;
01378         }
01379         LM_DBG("new body: [%.*s]", nb.len, nb.s);
01380         return 1;
01381 }
01382 
01383 static int set_rpl_body_f(struct sip_msg* msg, char* p1, char* p2)
01384 {
01385         char* buf;
01386         int len;
01387         int value_len;
01388         str nb = {0,0};
01389         str nc = {0,0};
01390 
01391         if(p1==0 || p2==0)
01392         {
01393                 LM_ERR("invalid parameters\n");
01394                 return -1;
01395         }
01396 
01397         if(fixup_get_svalue(msg, (gparam_p)p1, &nb)!=0)
01398         {
01399                 LM_ERR("unable to get p1\n");
01400                 return -1;
01401         }
01402         if(nb.s==NULL || nb.len == 0)
01403         {
01404                 LM_ERR("invalid body parameter\n");
01405                 return -1;
01406         }
01407         if(fixup_get_svalue(msg, (gparam_p)p2, &nc)!=0)
01408         {
01409                 LM_ERR("unable to get p2\n");
01410                 return -1;
01411         }
01412         if(nc.s==NULL || nc.len == 0)
01413         {
01414                 LM_ERR("invalid content-type parameter\n");
01415                 return -1;
01416         }
01417 
01418         /* add content-type */
01419         value_len = nc.len;
01420         len=sizeof("Content-Type: ") - 1 + value_len + CRLF_LEN;
01421         buf=pkg_malloc(sizeof(char)*(len));
01422 
01423         if (buf==0)
01424         {
01425                 LM_ERR("out of pkg memory\n");
01426                 return -1;
01427         }
01428         memcpy(buf, "Content-Type: ", sizeof("Content-Type: ") - 1);
01429         memcpy(buf+sizeof("Content-Type: ") - 1, nc.s, value_len);
01430         memcpy(buf+sizeof("Content-Type: ") - 1 + value_len, CRLF, CRLF_LEN);
01431         if (add_lump_rpl(msg, buf, len, LUMP_RPL_HDR) == 0)
01432         {
01433                 LM_ERR("failed to insert content-type lump\n");
01434                 pkg_free(buf);
01435                 return -1;
01436         }
01437         pkg_free(buf);
01438 
01439         if (add_lump_rpl( msg, nb.s, nb.len, LUMP_RPL_BODY)==0) {
01440                 LM_ERR("cannot add body lump\n");
01441                 return -1;
01442         }
01443                 
01444         return 1;
01445 }
01446 
01447 
01448 
01449 static int append_to_reply_f(struct sip_msg* msg, char* key, char* str0)
01450 {
01451         str s0;
01452 
01453         if(key==NULL)
01454         {
01455                 LM_ERR("bad parameters\n");
01456                 return -1;
01457         }
01458 
01459         if(fixup_get_svalue(msg, (gparam_p)key, &s0)!=0)
01460         {
01461                 LM_ERR("cannot print the format\n");
01462                 return -1;
01463         }
01464  
01465         if ( add_lump_rpl( msg, s0.s, s0.len, LUMP_RPL_HDR)==0 )
01466         {
01467                 LM_ERR("unable to add lump_rl\n");
01468                 return -1;
01469         }
01470 
01471         return 1;
01472 }
01473 
01474 
01475 /* add str1 to end of header or str1.r-uri.str2 */
01476 
01477 int add_hf_helper(struct sip_msg* msg, str *str1, str *str2,
01478                 gparam_p hfval, int mode, gparam_p hfanc)
01479 {
01480         struct lump* anchor;
01481         struct hdr_field *hf;
01482         char *s;
01483         int len;
01484         str s0;
01485 
01486         if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
01487                 LM_ERR("error while parsing message\n");
01488                 return -1;
01489         }
01490         
01491         hf = 0;
01492         if(hfanc!=NULL) {
01493                 for (hf=msg->headers; hf; hf=hf->next) {
01494                         if(hfanc->type==GPARAM_TYPE_INT)
01495                         {
01496                                 if (hfanc->v.i!=hf->type)
01497                                         continue;
01498                         } else {
01499                                 if (hf->name.len!=hfanc->v.str.len)
01500                                         continue;
01501                                 if (cmp_hdrname_str(&hf->name,&hfanc->v.str)!=0)
01502                                         continue;
01503                         }
01504                         break;
01505                 }
01506         }
01507 
01508         if(mode == 0) { /* append */
01509                 if(hf==0) { /* after last header */
01510                         anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0, 0);
01511                 } else { /* after hf */
01512                         anchor = anchor_lump(msg, hf->name.s + hf->len - msg->buf, 0, 0);
01513                 }
01514         } else { /* insert */
01515                 if(hf==0) { /* before first header */
01516                         anchor = anchor_lump(msg, msg->headers->name.s - msg->buf, 0, 0);
01517                 } else { /* before hf */
01518                         anchor = anchor_lump(msg, hf->name.s - msg->buf, 0, 0);
01519                 }
01520         }
01521 
01522         if(anchor == 0) {
01523                 LM_ERR("can't get anchor\n");
01524                 return -1;
01525         }
01526 
01527         if(str1) {
01528                 s0 = *str1;
01529         } else {
01530                 if(hfval) {
01531                         if(fixup_get_svalue(msg, hfval, &s0)!=0)
01532                         {
01533                                 LM_ERR("cannot print the format\n");
01534                                 return -1;
01535                         }
01536                 } else {
01537                         s0.len = 0;
01538                         s0.s   = 0;
01539                 }
01540         }
01541                 
01542         len=s0.len;
01543         if (str2) len+= str2->len + REQ_LINE(msg).uri.len;
01544 
01545         s  = (char*)pkg_malloc(len);
01546         if (!s) {
01547                 LM_ERR("no pkg memory left\n");
01548                 return -1;
01549         }
01550 
01551         if (likely(s0.len>0)){
01552                 memcpy(s, s0.s, s0.len);
01553         }
01554 
01555         if (str2) {
01556                 memcpy(s+str1->len, REQ_LINE(msg).uri.s, REQ_LINE(msg).uri.len);
01557                 memcpy(s+str1->len+REQ_LINE(msg).uri.len, str2->s, str2->len );
01558         }
01559 
01560         if (insert_new_lump_before(anchor, s, len, 0) == 0) {
01561                 LM_ERR("can't insert lump\n");
01562                 pkg_free(s);
01563                 return -1;
01564         }
01565         return 1;
01566 }
01567 
01568 static int append_hf_1(struct sip_msg *msg, char *str1, char *str2 )
01569 {
01570         return add_hf_helper(msg, 0, 0, (gparam_p)str1, 0, 0);
01571 }
01572 
01573 static int append_hf_2(struct sip_msg *msg, char *str1, char *str2 )
01574 {
01575         return add_hf_helper(msg, 0, 0, (gparam_p)str1, 0,
01576                         (gparam_p)str2);
01577 }
01578 
01579 static int insert_hf_1(struct sip_msg *msg, char *str1, char *str2 )
01580 {
01581         return add_hf_helper(msg, 0, 0, (gparam_p)str1, 1, 0);
01582 }
01583 
01584 static int insert_hf_2(struct sip_msg *msg, char *str1, char *str2 )
01585 {
01586         return add_hf_helper(msg, 0, 0, (gparam_p)str1, 1, 
01587                         (gparam_p)str2);
01588 }
01589 
01590 static int append_urihf(struct sip_msg *msg, char *str1, char *str2)
01591 {
01592         return add_hf_helper(msg, (str*)str1, (str*)str2, 0, 0, 0);
01593 }
01594 
01595 static int is_method_f(struct sip_msg *msg, char *meth, char *str2 )
01596 {
01597         str *m;
01598 
01599         m = (str*)meth;
01600         if(msg->first_line.type==SIP_REQUEST)
01601         {
01602                 if(m->s==0)
01603                         return (msg->first_line.u.request.method_value&m->len)?1:-1;
01604                 else
01605                         return (msg->first_line.u.request.method_value==METHOD_OTHER
01606                                         && msg->first_line.u.request.method.len==m->len
01607                                         && (strncasecmp(msg->first_line.u.request.method.s, m->s,
01608                                         m->len)==0))?1:-1;
01609         }
01610         if(parse_headers(msg, HDR_CSEQ_F, 0)!=0 || msg->cseq==NULL)
01611         {
01612                 LM_ERR("cannot parse cseq header\n");
01613                 return -1; /* should it be 0 ?!?! */
01614         }
01615         if(m->s==0)
01616                 return (get_cseq(msg)->method_id&m->len)?1:-1;
01617         else
01618                 return (get_cseq(msg)->method_id==METHOD_OTHER
01619                                 && get_cseq(msg)->method.len==m->len
01620                                 && (strncasecmp(get_cseq(msg)->method.s, m->s,
01621                                 m->len)==0))?1:-1;
01622 }
01623 
01624 
01625 /*
01626  * Convert char* header_name to str* parameter
01627  */
01628 static int hname_fixup(void** param, int param_no)
01629 {
01630         char c;
01631         struct hdr_field hdr;
01632         gparam_p gp = NULL;
01633         
01634         gp = (gparam_p)pkg_malloc(sizeof(gparam_t));
01635         if(gp == NULL)
01636         {
01637                 LM_ERR("no more memory\n");
01638                 return E_UNSPEC;
01639         }
01640         memset(gp, 0, sizeof(gparam_t));
01641 
01642         gp->v.str.s = (char*)*param;
01643         gp->v.str.len = strlen(gp->v.str.s);
01644         if(gp->v.str.len==0)
01645         {
01646                 LM_ERR("empty header name parameter\n");
01647                 pkg_free(gp);
01648                 return E_UNSPEC;
01649         }
01650         
01651         c = gp->v.str.s[gp->v.str.len];
01652         gp->v.str.s[gp->v.str.len] = ':';
01653         gp->v.str.len++;
01654         
01655         if (parse_hname2(gp->v.str.s, gp->v.str.s
01656                                 + ((gp->v.str.len<4)?4:gp->v.str.len), &hdr)==0)
01657         {
01658                 LM_ERR("error parsing header name\n");
01659                 pkg_free(gp);
01660                 return E_UNSPEC;
01661         }
01662         
01663         gp->v.str.len--;
01664         gp->v.str.s[gp->v.str.len] = c;
01665 
01666         if (hdr.type!=HDR_OTHER_T && hdr.type!=HDR_ERROR_T)
01667         {
01668                 LM_DBG("using hdr type (%d) instead of <%.*s>\n",
01669                                 hdr.type, gp->v.str.len, gp->v.str.s);
01670                 pkg_free(gp->v.str.s);
01671                 gp->v.str.s = NULL;
01672                 gp->v.i = hdr.type;
01673                 gp->type = GPARAM_TYPE_INT;
01674         } else {
01675                 gp->type = GPARAM_TYPE_STR;
01676                 LM_DBG("using hdr type name <%.*s>\n", gp->v.str.len, gp->v.str.s);
01677         }
01678         
01679         *param = (void*)gp;
01680         return 0;
01681 }
01682 
01683 static int free_hname_fixup(void** param, int param_no)
01684 {
01685         if(*param)
01686         {
01687                 if(((gparam_p)(*param))->type==GPARAM_TYPE_STR)
01688                         pkg_free(((gparam_p)(*param))->v.str.s);
01689                 pkg_free(*param);
01690                 *param = 0;
01691         }
01692         return 0;
01693 }
01694 
01695 /*
01696  * Convert char* method to str* parameter
01697  */
01698 static int fixup_method(void** param, int param_no)
01699 {
01700         str* s;
01701         char *p;
01702         int m;
01703         unsigned int method;
01704         
01705         s = (str*)pkg_malloc(sizeof(str));
01706         if (!s) {
01707                 LM_ERR("no pkg memory left\n");
01708                 return E_UNSPEC;
01709         }
01710 
01711         s->s = (char*)*param;
01712         s->len = strlen(s->s);
01713         if(s->len==0)
01714         {
01715                 LM_ERR("empty method name\n");
01716                 pkg_free(s);
01717                 return E_UNSPEC;
01718         }
01719         m=0;
01720         p=s->s;
01721         while(*p)
01722         {
01723                 if(*p=='|')
01724                 {
01725                         *p = ',';
01726                         m=1;
01727                 }
01728                 p++;
01729         }
01730         if(parse_methods(s, &method)!=0)
01731         {
01732                 LM_ERR("bad method names\n");
01733                 pkg_free(s);
01734                 return E_UNSPEC;
01735         }
01736 
01737         if(m==1)
01738         {
01739                 if(method==METHOD_UNDEF || method&METHOD_OTHER)
01740                 {
01741                         LM_ERR("unknown method in list [%.*s/%d] - must be only defined methods\n",
01742                                 s->len, s->s, method);
01743                         return E_UNSPEC;
01744                 }
01745                 LM_DBG("using id for methods [%.*s/%d]\n",
01746                                 s->len, s->s, method);
01747                 s->s = 0;
01748                 s->len = method;
01749         } else {
01750                 if(method!=METHOD_UNDEF && method!=METHOD_OTHER)
01751                 {
01752                         LM_DBG("using id for method [%.*s/%d]\n",
01753                                 s->len, s->s, method);
01754                         s->s = 0;
01755                         s->len = method;
01756                 } else
01757                         LM_DBG("name for method [%.*s/%d]\n",
01758                                 s->len, s->s, method);
01759         }
01760 
01761         *param = (void*)s;
01762         return 0;
01763 }
01764 
01765 /*
01766  * Convert char* privacy value to corresponding bit value
01767  */
01768 int fixup_privacy(void** param, int param_no)
01769 {
01770     str p;
01771     unsigned int val;
01772 
01773     p.s = (char*)*param;
01774     p.len = strlen(p.s);
01775 
01776     if (p.len == 0) {
01777         LM_ERR("empty privacy value\n");
01778         return E_UNSPEC;
01779     }
01780 
01781     if (parse_priv_value(p.s, p.len, &val) != p.len) {
01782         LM_ERR("invalid privacy value\n");
01783         return E_UNSPEC;
01784     }
01785     
01786     *param = (void *)(long)val;
01787     return 0;
01788 }
01789 
01790 /*
01791  * Fix in_list params: subject and list (strings that may contain pvars),
01792  * separator (string)
01793  */
01794 static int fixup_in_list(void** param, int param_no)
01795 {
01796     if ((param_no == 1) || (param_no == 2)) return fixup_spve_null(param, 1);
01797     
01798     if (param_no == 3) {
01799         if ((strlen((char *)*param) != 1) || (*((char *)(*param)) == 0)) {
01800             LM_ERR("invalid separator parameter\n");
01801             return -1;
01802         }
01803         return 0;
01804     }
01805  
01806     LM_ERR("invalid parameter number <%d>\n", param_no);
01807     return -1;
01808 }
01809  
01810 /*
01811  * Free in_list params
01812  */
01813 static int fixup_free_in_list(void** param, int param_no)
01814 {
01815     if ((param_no == 1) || (param_no == 2)) {
01816         LM_WARN("free function has not been defined for spve\n");
01817         return 0;
01818     }
01819  
01820     if (param_no == 3) return 0;
01821      
01822     LM_ERR("invalid parameter number <%d>\n", param_no);
01823     return -1;
01824 }
01825 
01826 static int add_header_fixup(void** param, int param_no)
01827 {
01828         if(param_no==1)
01829         {
01830                 return fixup_spve_null(param, param_no);
01831         } else if(param_no==2) {
01832                 return hname_fixup(param, param_no);
01833         } else {
01834                 LM_ERR("wrong number of parameters\n");
01835                 return E_UNSPEC;
01836         }
01837 }
01838 
01839 
01840 static int fixup_body_type(void** param, int param_no)
01841 {
01842         char *p;
01843         char *r;
01844         unsigned int type;
01845 
01846         if(param_no==1) {
01847                 p = (char*)*param;
01848                 if (p==0 || p[0]==0) {
01849                         type = 0;
01850                 } else {
01851                         r = decode_mime_type( p, p+strlen(p) , &type);
01852                         if (r==0) {
01853                                 LM_ERR("unsupported mime <%s>\n",p);
01854                                 return E_CFG;
01855                         }
01856                         if ( r!=p+strlen(p) ) {
01857                                 LM_ERR("multiple mimes not supported!\n");
01858                                 return E_CFG;
01859                         }
01860                 }
01861                 pkg_free(*param);
01862                 *param = (void*)(long)type;
01863         }
01864         return 0;
01865 
01866 }
01867 
01868 
01869 static int has_body_f(struct sip_msg *msg, char *type, char *str2 )
01870 {
01871         int mime;
01872 
01873         /* parse content len hdr */
01874         if ( msg->content_length==NULL &&
01875         (parse_headers(msg,HDR_CONTENTLENGTH_F, 0)==-1||msg->content_length==NULL))
01876                 return -1;
01877 
01878         if (get_content_length (msg)==0) {
01879                 LM_DBG("content length is zero\n");
01880                 /* Nothing to see here, please move on. */
01881                 return -1;
01882         }
01883 
01884         /* check type also? */
01885         if (type==0)
01886                 return 1;
01887 
01888         /* the function search for and parses the Content-Type hdr */
01889         mime = parse_content_type_hdr (msg);
01890         if (mime<0) {
01891                 LM_ERR("failed to extract content type hdr\n");
01892                 return -1;
01893         }
01894         if (mime==0) {
01895                 /* content type hdr not found -> according the RFC3261 we
01896                  * assume APPLICATION/SDP  --bogdan */
01897                 mime = ((TYPE_APPLICATION << 16) + SUBTYPE_SDP);
01898         }
01899         LM_DBG("content type is %d\n",mime);
01900 
01901         if ( (unsigned int)mime!=(unsigned int)(unsigned long)type )
01902                 return -1;
01903 
01904         return 1;
01905 }
01906 
01907 
01908 int is_privacy_f(struct sip_msg *msg, char *_privacy, char *str2 )
01909 {
01910     if (parse_privacy(msg) == -1)
01911         return -1;
01912 
01913     return get_privacy_values(msg) & ((unsigned int)(long)_privacy) ? 1 : -1;
01914 
01915 }
01916 
01917 /* 
01918  * Checks if subject is found in list
01919  */
01920 int in_list_f(struct sip_msg* _m, char* _subject, char* _list, char* _sep)
01921 {
01922     str subject, list;
01923     int sep;
01924     char *at, *past, *next_sep, *s;
01925 
01926     if (fixup_get_svalue(_m, (gparam_p)_subject, &subject) != 0) {
01927                 LM_ERR("cannot get subject value\n");
01928                 return -1;
01929     } else {
01930                 if (subject.len == 0) {
01931                         LM_ERR("subject cannot be empty string\n");
01932                         return -1;
01933                 }
01934     }
01935 
01936     if (fixup_get_svalue(_m, (gparam_p)_list, &list) != 0) {
01937                 LM_ERR("cannot get list value\n");
01938                 return -1;
01939     } else {
01940                 if (list.len == 0) return -1;
01941     }
01942 
01943     sep = _sep[0];
01944 
01945     at = list.s;
01946     past = list.s + list.len;
01947 
01948         /* Eat leading white space */
01949         while ((at < past) && 
01950                   ((*at == ' ') || (*at == '\t') || (*at == '\r') || (*at == '\n') )) {
01951                         at++;
01952         }
01953 
01954     while (at < past) {
01955                 next_sep = index(at, sep);
01956                 s = next_sep;
01957                 
01958                 if (s == NULL) {
01959                         /* Eat trailing white space */
01960                         while ((at < past) && 
01961                                   ((*(past-1) == ' ') || (*(past-1) == '\t') || (*(past-1) == '\r') || (*(past-1) == '\n') )) {
01962                                         past--;
01963                         }
01964                         if ((subject.len == (past - at)) &&
01965                                 strncmp(at, subject.s, subject.len) == 0) {
01966                                 return 1;
01967                         } else {
01968                                 return -1;
01969                         }
01970                 } else {
01971                         /* Eat trailing white space */
01972                         while ((at < s) && 
01973                                   ((*(s-1) == ' ') || (*(s-1) == '\t') || (*(s-1) == '\r') || (*(s-1) == '\n') )) {
01974                                         s--;
01975                         }
01976                         if ((subject.len == (s - at)) &&
01977                                 strncmp(at, subject.s, subject.len) == 0) {
01978                                 return 1;
01979                         } else {
01980                                 at = next_sep + 1;
01981                                 /* Eat leading white space */
01982                                 while ((at < past) && 
01983                                           ((*at == ' ') || (*at == '\t') || (*at == '\r') || (*at == '\n') )) {
01984                                                 at++;
01985                                 }
01986                         }
01987                 }
01988     }
01989 
01990     return -1;
01991 }
01992 
01993 static int cmp_str_f(struct sip_msg *msg, char *str1, char *str2 )
01994 {
01995         str s1;
01996         str s2;
01997         int ret;
01998 
01999         if(fixup_get_svalue(msg, (gparam_p)str1, &s1)!=0)
02000         {
02001                 LM_ERR("cannot get first parameter\n");
02002                 return -8;
02003         }
02004         if(fixup_get_svalue(msg, (gparam_p)str2, &s2)!=0)
02005         {
02006                 LM_ERR("cannot get second parameter\n");
02007                 return -8;
02008         }
02009         ret = cmp_str(&s1, &s2);
02010         if(ret==0)
02011                 return 1;
02012         if(ret>0)
02013                 return -1;
02014         return -2;
02015 }
02016 
02017 static int cmp_istr_f(struct sip_msg *msg, char *str1, char *str2)
02018 {
02019         str s1;
02020         str s2;
02021         int ret;
02022 
02023         if(fixup_get_svalue(msg, (gparam_p)str1, &s1)!=0)
02024         {
02025                 LM_ERR("cannot get first parameter\n");
02026                 return -8;
02027         }
02028         if(fixup_get_svalue(msg, (gparam_p)str2, &s2)!=0)
02029         {
02030                 LM_ERR("cannot get second parameter\n");
02031                 return -8;
02032         }
02033         ret = cmpi_str(&s1, &s2);
02034         if(ret==0)
02035                 return 1;
02036         if(ret>0)
02037                 return -1;
02038         return -2;
02039 }
02040 
02041 static int starts_with_f(struct sip_msg *msg, char *str1, char *str2 )
02042 {
02043         str s1;
02044         str s2;
02045         int ret;
02046 
02047         if(fixup_get_svalue(msg, (gparam_p)str1, &s1)!=0)
02048         {
02049                 LM_ERR("cannot get first parameter\n");
02050                 return -8;
02051         }
02052         if(fixup_get_svalue(msg, (gparam_p)str2, &s2)!=0)
02053         {
02054                 LM_ERR("cannot get second parameter\n");
02055                 return -8;
02056         }
02057         if (s1.len < s2.len) return -1;
02058         ret = strncmp(s1.s, s2.s, s2.len);
02059         if(ret==0)
02060                 return 1;
02061         if(ret>0)
02062                 return -1;
02063         return -2;
02064 }
02065 
02066 static int is_audio_on_hold_f(struct sip_msg *msg, char *str1, char *str2 )
02067 {
02068         int sdp_session_num = 0, sdp_stream_num;
02069         sdp_session_cell_t* sdp_session;
02070         sdp_stream_cell_t* sdp_stream;
02071 
02072         if (0 == parse_sdp(msg)) {
02073                 for(;;) {
02074                         sdp_session = get_sdp_session(msg, sdp_session_num);
02075                         if(!sdp_session) break;
02076                         sdp_stream_num = 0;
02077                         for(;;) {
02078                                 sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num);
02079                                 if(!sdp_stream) break;
02080                                 if(sdp_stream->media.len==AUDIO_STR_LEN &&
02081                                         strncmp(sdp_stream->media.s,AUDIO_STR,AUDIO_STR_LEN)==0 &&
02082                                         sdp_stream->is_on_hold)
02083                                         return 1;
02084                                 sdp_stream_num++;
02085                         }
02086                         sdp_session_num++;
02087                 }
02088         }
02089         return -1;
02090 }
02091 
02092 int fixup_regexpNL_none(void** param, int param_no)
02093 {
02094         regex_t* re;
02095 
02096         if (param_no != 1 && param_no != 2 )
02097         {
02098                 LM_ERR("invalid parameter number %d\n", param_no);
02099                 return E_UNSPEC;
02100         }
02101         if (param_no == 2)
02102                 return 0;
02103         /* param 1 */
02104         if ((re=pkg_malloc(sizeof(regex_t)))==0) {
02105                 LM_ERR("no more pkg memory\n");
02106                 return E_OUT_OF_MEM;
02107         }
02108         if (regcomp(re, *param, REG_EXTENDED|REG_ICASE)) {
02109                 pkg_free(re);
02110                 LM_ERR("bad re %s\n", (char*)*param);
02111                 return E_BAD_RE;
02112         }
02113         /* free string */
02114         pkg_free(*param);
02115         /* replace it with the compiled re */
02116         *param=re;
02117         return 0;
02118 }
02119 
02125 int fixup_regexp_none(void** param, int param_no)
02126 {
02127         if (param_no != 1 && param_no != 2 )
02128         {
02129                 LM_ERR("invalid parameter number %d\n", param_no);
02130                 return E_UNSPEC;
02131         }
02132         if (param_no == 1)
02133                 return fixup_regexp_null(param, 1);
02134         return 0;
02135 }
02136 
02142 int fixup_free_regexp_none(void** param, int param_no)
02143 {
02144         if (param_no != 1 && param_no != 2 )
02145         {
02146                 LM_ERR("invalid parameter number %d\n", param_no);
02147                 return E_UNSPEC;
02148         }
02149         if (param_no == 1)
02150                 return fixup_free_regexp_null(param, 1);
02151         return 0;
02152 }
02153 
02154 
02158 static int search_hf_f(struct sip_msg* msg, char* str_hf, char* re, char *flags)
02159 {
02160         hdr_field_t *hf;
02161         hdr_field_t *hfl = NULL;
02162         str body;
02163         gparam_t *gp;
02164         regmatch_t pmatch;
02165         char c;
02166         int ret;
02167 
02168         gp = (gparam_t*)str_hf;
02169 
02170         /* we need to be sure we have seen all HFs */
02171         parse_headers(msg, HDR_EOH_F, 0);
02172         for (hf=msg->headers; hf; hf=hf->next) {
02173                 if(gp->type==GPARAM_TYPE_INT)
02174                 {
02175                         if (gp->v.i!=hf->type)
02176                                 continue;
02177                 } else {
02178                         if (hf->name.len!=gp->v.str.len)
02179                                 continue;
02180                         if (cmp_hdrname_str(&hf->name,&gp->v.str)!=0)
02181                                 continue;
02182                 }
02183 
02184                 if(flags==NULL || *flags!='l')
02185                 {
02186                         body = hf->body;
02187                         c = body.s[body.len];
02188                         body.s[body.len] = '\0';
02189                         ret = regexec((regex_t*) re, body.s, 1, &pmatch, 0);
02190                         body.s[body.len] = c;
02191                         if(ret==0)
02192                         {
02193                                 /* match */
02194                                 if(flags==NULL || *flags!='l')
02195                                         return 1;
02196                         } else {
02197                                 if(flags!=NULL && *flags=='f')
02198                                         return 1;
02199                         }
02200                 } else {
02201                         hfl = hf;
02202                 }
02203         }
02204         if(hfl!=NULL)
02205         {
02206                 hf = hfl;
02207                 body = hf->body;
02208                 c = body.s[body.len];
02209                 body.s[body.len] = '\0';
02210                 ret = regexec((regex_t*) re, body.s, 1, &pmatch, 0);
02211                 body.s[body.len] = c;
02212                 if(ret==0)
02213                         return 1;
02214         }
02215         return -1;
02216 }
02217 
02218 /*
02219  * Convert header name, regexp and flags
02220  */
02221 static int fixup_search_hf(void** param, int param_no)
02222 {
02223         if(param_no==1)
02224                 return hname_fixup(param, param_no);
02225         if(param_no==2)
02226                 return fixup_regexp_null(param, 1);
02227         return 0;
02228 }
02229 
02230 /* sed-perl style re: s/regular expression/replacement/flags */
02231 static int subst_hf_f(struct sip_msg *msg, char *str_hf, char *subst, char *flags)
02232 {
02233         struct lump* l;
02234         struct replace_lst* lst = NULL;
02235         struct replace_lst* rpl = NULL;
02236         char* begin;
02237         struct subst_expr* se;
02238         int off;
02239         int nmatches;
02240         str body;
02241         hdr_field_t *hf;
02242         hdr_field_t *hfl = NULL;
02243         gparam_t *gp;
02244         char c;
02245         int ret;
02246 
02247         ret = -1;
02248         gp = (gparam_t*)str_hf;
02249         se=(struct subst_expr*)subst;
02250 
02251         /* we need to be sure we have seen all HFs */
02252         parse_headers(msg, HDR_EOH_F, 0);
02253         for (hf=msg->headers; hf; hf=hf->next) {
02254                 if(gp->type==GPARAM_TYPE_INT)
02255                 {
02256                         if (gp->v.i!=hf->type)
02257                                 continue;
02258                 } else {
02259                         if (hf->name.len!=gp->v.str.len)
02260                                 continue;
02261                         if (cmp_hdrname_str(&hf->name,&gp->v.str)!=0)
02262                                 continue;
02263                 }
02264 
02265                 if(flags==NULL || *flags!='l')
02266                 {
02267                         body = hf->body;
02268                         c = body.s[body.len];
02269                         body.s[body.len] = '\0';
02270 
02271                         begin=body.s;
02272 
02273                         off=begin-msg->buf;
02274                         lst=subst_run(se, begin, msg, &nmatches);
02275                         body.s[body.len] = c;
02276                         if(lst==0 && flags!=NULL && *flags=='f')
02277                                 goto error; /* not found */
02278                         if(lst!=0)
02279                                 ret=1;
02280                         for (rpl=lst; rpl; rpl=rpl->next)
02281                         {
02282                                 LM_DBG("%s replacing at offset %d [%.*s] with [%.*s]\n",
02283                                                 exports.name, rpl->offset+off,
02284                                                 rpl->size, rpl->offset+off+msg->buf,
02285                                                 rpl->rpl.len, rpl->rpl.s);
02286                                 if ((l=del_lump(msg, rpl->offset+off, rpl->size, 0))==0)
02287                                 {
02288                                         ret=-1;
02289                                         goto error;
02290                                 }
02291                                 /* hack to avoid re-copying rpl, possible because both 
02292                                  * replace_lst & lumps use pkg_malloc */
02293                                 if (insert_new_lump_after(l, rpl->rpl.s, rpl->rpl.len, 0)==0)
02294                                 {
02295                                         LM_ERR("%s could not insert new lump\n",
02296                                                 exports.name);
02297                                         ret=-1;
02298                                         goto error;
02299                                 }
02300                                 /* hack continued: set rpl.s to 0 so that replace_lst_free will
02301                                  * not free it */
02302                                 rpl->rpl.s=0;
02303                                 rpl->rpl.len=0;
02304                         }
02305                 } else {
02306                         hfl = hf;
02307                 }
02308         }
02309         if(hfl!=NULL)
02310         {
02311                 hf= hfl;
02312                 body = hf->body;
02313                 c = body.s[body.len];
02314                 body.s[body.len] = '\0';
02315 
02316                 begin=body.s;
02317 
02318                 off=begin-msg->buf;
02319                 lst=subst_run(se, begin, msg, &nmatches);
02320                 body.s[body.len] = c;
02321                 if(lst==0)
02322                         goto error; /* not found */
02323                 ret=1;
02324                 for (rpl=lst; rpl; rpl=rpl->next)
02325                 {
02326                         LM_DBG("%s replacing at offset %d [%.*s] with [%.*s]\n",
02327                                         exports.name, rpl->offset+off,
02328                                         rpl->size, rpl->offset+off+msg->buf,
02329                                         rpl->rpl.len, rpl->rpl.s);
02330                         if ((l=del_lump(msg, rpl->offset+off, rpl->size, 0))==0)
02331                         {
02332                                 ret=-1;
02333                                 goto error;
02334                         }
02335                         /* hack to avoid re-copying rpl, possible because both 
02336                          * replace_lst & lumps use pkg_malloc */
02337                         if (insert_new_lump_after(l, rpl->rpl.s, rpl->rpl.len, 0)==0)
02338                         {
02339                                 LM_ERR("%s could not insert new lump\n",
02340                                         exports.name);
02341                                 ret=-1;
02342                                 goto error;
02343                         }
02344                         /* hack continued: set rpl.s to 0 so that replace_lst_free will
02345                          * not free it */
02346                         rpl->rpl.s=0;
02347                         rpl->rpl.len=0;
02348                 }
02349         }
02350 error:
02351         LM_DBG("lst was %p\n", lst);
02352         if (lst) replace_lst_free(lst);
02353         if (nmatches<0)
02354                 LM_ERR("%s subst_run failed\n", exports.name);
02355         return ret;
02356 }
02357 
02358 /*
02359  * Convert header name, substexp and flags
02360  */
02361 static int fixup_subst_hf(void** param, int param_no)
02362 {
02363         if(param_no==1)
02364                 return hname_fixup(param, param_no);
02365         if(param_no==2)
02366                 return fixup_substre(param, 1);
02367         return 0;
02368 }
02369