Module: sip-router
Branch: master
Commit: 0f598b1a5798ecd403ef588f7d4c6b38177883ce
URL:    
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=0f598b1a5798ecd403ef588f7d4c6b38177883ce

Author: Daniel-Constantin Mierla <[email protected]>
Committer: Daniel-Constantin Mierla <[email protected]>
Date:   Fri Dec 16 13:10:57 2011 +0100

pv: new transformation class 'line'

- {line.count} - return number of lines in PV
- {line.at,pos} - return the line at position pos
- {line.sw,exp} - return the line starting with 'exp'

---

 modules_k/pv/pv.c       |    2 +
 modules_k/pv/pv_trans.c |  291 +++++++++++++++++++++++++++++++++++++++++++++++
 modules_k/pv/pv_trans.h |    6 +-
 3 files changed, 298 insertions(+), 1 deletions(-)

diff --git a/modules_k/pv/pv.c b/modules_k/pv/pv.c
index f5784d9..bc47e1a 100644
--- a/modules_k/pv/pv.c
+++ b/modules_k/pv/pv.c
@@ -53,6 +53,8 @@ static tr_export_t mod_trans[] = {
                tr_parse_paramlist },
        { {"tobody", sizeof("tobody")-1}, /* param class */
                tr_parse_tobody },
+       { {"line", sizeof("line")-1}, /* line class */
+               tr_parse_line },
 
        { { 0, 0 }, 0 }
 };
diff --git a/modules_k/pv/pv_trans.c b/modules_k/pv/pv_trans.c
index f1dcce3..22d3a9e 100644
--- a/modules_k/pv/pv_trans.c
+++ b/modules_k/pv/pv_trans.c
@@ -1342,6 +1342,202 @@ int tr_eval_tobody(struct sip_msg *msg, tr_param_t *tp, 
int subtype,
        return 0;
 }
 
+void *memfindrchr(const void *buf, int c, size_t n)
+{
+       int i;
+       unsigned char *p;
+
+       p = (unsigned char*)buf;
+
+       for (i=n-1; i>=0; i--) {
+               if (p[i] == (unsigned char)c) {
+                       return (void*)(p+i);
+               }
+       }
+       return NULL;
+}
+
+/*!
+ * \brief Evaluate line transformations
+ * \param msg SIP message
+ * \param tp transformation
+ * \param subtype transformation type
+ * \param val pseudo-variable
+ * \return 0 on success, -1 on error
+ */
+int tr_eval_line(struct sip_msg *msg, tr_param_t *tp, int subtype,
+               pv_value_t *val)
+{
+       pv_value_t v;
+       str sv;
+       str mv;
+       char *p;
+       int n, i;
+
+       if(val==NULL || (!(val->flags&PV_VAL_STR)) || val->rs.len<=0)
+               return -1;
+
+       switch(subtype)
+       {
+               case TR_LINE_SW:
+                       if(tp==NULL)
+                       {
+                               LM_ERR("value invalid parameters\n");
+                               return -1;
+                       }
+
+                       if(tp->type==TR_PARAM_STRING)
+                       {
+                               sv = tp->v.s;
+                       } else {
+                               if(pv_get_spec_value(msg, 
(pv_spec_p)tp->v.data, &v)!=0
+                                               || (!(v.flags&PV_VAL_STR)) || 
v.rs.len<=0)
+                               {
+                                       LM_ERR("value cannot get p1\n");
+                                       return -1;
+                               }
+                               sv = v.rs;
+                       }
+
+                       if(val->rs.len < sv.len)
+                       {
+                               val->rs = _tr_empty;
+                               goto done;
+                       }
+                       p = val->rs.s;
+                       do {
+                               if(strncmp(p, sv.s, sv.len)==0)
+                               {
+                                       /* match */
+                                       mv.s = p;
+                                       p += sv.len;
+                                       p = memchr(p, '\n', (val->rs.s + 
val->rs.len) - p);
+                                       if(p==NULL)
+                                       {
+                                               /* last line */
+                                               mv.len = (val->rs.s + 
val->rs.len) - p;
+                                       } else {
+                                               mv.len = p - mv.s;
+                                       }
+                                       val->rs = mv;
+                                       goto done;
+                               }
+                               p = memchr(p, '\n', (val->rs.s + val->rs.len) - 
p);
+                       } while(p && ((++p)<=val->rs.s+val->rs.len-sv.len));
+                       val->rs = _tr_empty;
+                       break;
+
+               case TR_LINE_AT:
+                       if(tp==NULL)
+                       {
+                               LM_ERR("name invalid parameters\n");
+                               return -1;
+                       }
+
+                       if(tp->type==TR_PARAM_NUMBER)
+                       {
+                               n = tp->v.n;
+                       } else {
+                               if(pv_get_spec_value(msg, 
(pv_spec_p)tp->v.data, &v)!=0
+                                               || (!(v.flags&PV_VAL_INT)))
+                               {
+                                       LM_ERR("name cannot get p1\n");
+                                       return -1;
+                               }
+                               n = v.ri;
+                       }
+                       if(n<0)
+                       {
+                               p = val->rs.s + val->rs.len - 1;
+                               if(*p=='\n')
+                                       p--;
+                               mv.s = p;
+                               n = -n;
+                               i=1;
+                               p = memfindrchr(val->rs.s, '\n', p - val->rs.s);
+                               if(p!=NULL)
+                                       p--;
+                               while(i<n && p)
+                               {
+                                       mv.s = p;
+                                       p = memfindrchr(val->rs.s, '\n', p - 
val->rs.s);
+                                       if(p!=NULL)
+                                               p--;
+                                       i++;
+                               }
+                               if(i==n)
+                               {
+                                       if(p==NULL)
+                                       {
+                                               /* first line */
+                                               mv.len = mv.s - val->rs.s + 1;
+                                               mv.s = val->rs.s;
+                                       } else {
+                                               mv.len = mv.s - p - 1;
+                                               mv.s = p + 2;
+                                       }
+                                       val->rs = mv;
+                                       goto done;
+                               }
+                       } else {
+                               p = val->rs.s;
+                               i = 0;
+                               while(i<n && p)
+                               {
+                                       p = memchr(p, '\n', (val->rs.s + 
val->rs.len) - p);
+                                       if(p!=NULL)
+                                               p++;
+                                       i++;
+                               }
+                               if(i==n && p!=NULL)
+                               {
+                                       /* line found */
+                                       mv.s = p;
+                                       p = memchr(p, '\n', (val->rs.s + 
val->rs.len) - p);
+                                       if(p==NULL)
+                                       {
+                                               /* last line */
+                                               mv.len = (val->rs.s + 
val->rs.len) - p;
+                                       } else {
+                                               mv.len = p - mv.s;
+                                       }
+                                       val->rs = mv;
+                                       goto done;
+                               }
+                       }
+                       val->rs = _tr_empty;
+                       break;
+
+               case TR_LINE_COUNT:
+                       n=0;
+                       for(i=0; i<val->rs.len; i++)
+                               if(val->rs.s[i]=='\n')
+                                       n++;
+                       if(n==0 && val->rs.len>0)
+                               n = 1;
+                       val->flags = PV_TYPE_INT|PV_VAL_INT|PV_VAL_STR;
+                       val->ri = n;
+                       val->rs.s = int2str(val->ri, &val->rs.len);
+                       break;
+
+                       break;
+
+               default:
+                       LM_ERR("unknown subtype %d\n",
+                                       subtype);
+                       return -1;
+       }
+done:
+       if(val->rs.len>0)
+       {
+               /* skip ending '\r' if present */
+               if(val->rs.s[val->rs.len-1]=='\r')
+                       val->rs.len--;
+       }
+       val->flags = PV_VAL_STR;
+       return 0;
+}
+
 
 #define _tr_parse_nparam(_p, _p0, _tp, _spec, _n, _sign, _in, _s) \
        while(is_in_str(_p, _in) && (*_p==' ' || *_p=='\t' || *_p=='\n')) _p++; 
\
@@ -2113,3 +2309,98 @@ done:
        t->name = name;
        return p;
 }
+
+/*!
+ * \brief Helper fuction to parse a line transformation
+ * \param in parsed string
+ * \param t transformation
+ * \return pointer to the end of the transformation in the string - '}', null 
on error
+ */
+char* tr_parse_line(str* in, trans_t *t)
+{
+       char *p;
+       char *p0;
+       char *ps;
+       str s;
+       str name;
+       int n;
+       int sign;
+       pv_spec_t *spec = NULL;
+       tr_param_t *tp = NULL;
+
+
+       if(in==NULL || t==NULL)
+               return NULL;
+
+       p = in->s;
+       name.s = in->s;
+       t->type = TR_LINE;
+       t->trf = tr_eval_line;
+
+       /* find next token */
+       while(is_in_str(p, in) && *p!=TR_PARAM_MARKER && *p!=TR_RBRACKET) p++;
+       if(*p=='\0')
+       {
+               LM_ERR("invalid transformation: %.*s\n",
+                               in->len, in->s);
+               goto error;
+       }
+       name.len = p - name.s;
+       trim(&name);
+
+       if(name.len==2 && strncasecmp(name.s, "at", 2)==0)
+       {
+               t->subtype = TR_LINE_AT;
+               if(*p!=TR_PARAM_MARKER)
+               {
+                       LM_ERR("invalid name transformation: %.*s\n",
+                                       in->len, in->s);
+                       goto error;
+               }
+               p++;
+               _tr_parse_nparam(p, p0, tp, spec, n, sign, in, s)
+               t->params = tp;
+               tp = 0;
+               while(is_in_str(p, in) && (*p==' ' || *p=='\t' || *p=='\n')) 
p++;
+               if(*p!=TR_RBRACKET)
+               {
+                       LM_ERR("invalid name transformation: %.*s!\n",
+                                       in->len, in->s);
+                       goto error;
+               }
+
+               goto done;
+       } else if(name.len==2 && strncasecmp(name.s, "sw", 2)==0) {
+               t->subtype = TR_LINE_SW;
+               if(*p!=TR_PARAM_MARKER)
+               {
+                       LM_ERR("invalid value transformation: %.*s\n",
+                                       in->len, in->s);
+                       goto error;
+               }
+               p++;
+               _tr_parse_sparam(p, p0, tp, spec, ps, in, s);
+               t->params = tp;
+               tp = 0;
+               while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
+               if(*p!=TR_RBRACKET)
+               {
+                       LM_ERR("invalid value transformation: %.*s!\n",
+                                       in->len, in->s);
+                       goto error;
+               }
+               goto done;
+       } else if(name.len==5 && strncasecmp(name.s, "count", 5)==0) {
+               t->subtype = TR_LINE_COUNT;
+               goto done;
+       }
+
+
+       LM_ERR("unknown transformation: %.*s/%.*s/%d!\n", in->len, in->s,
+                       name.len, name.s, name.len);
+error:
+       return NULL;
+done:
+       t->name = name;
+       return p;
+}
diff --git a/modules_k/pv/pv_trans.h b/modules_k/pv/pv_trans.h
index 4d77e1d..c660102 100644
--- a/modules_k/pv/pv_trans.h
+++ b/modules_k/pv/pv_trans.h
@@ -33,7 +33,7 @@
 
 
 enum _tr_type { TR_NONE=0, TR_STRING, TR_URI, TR_PARAMLIST, TR_NAMEADDR,
-                               TR_TOBODY };
+                               TR_TOBODY, TR_LINE };
 enum _tr_s_subtype { 
        TR_S_NONE=0, TR_S_LEN, TR_S_INT, TR_S_MD5, TR_S_SUBSTR,
        TR_S_SELECT, TR_S_ENCODEHEXA, TR_S_DECODEHEXA,
@@ -58,6 +58,9 @@ enum _tr_tobody_subtype {
        TR_TOBODY_NONE=0, TR_TOBODY_DISPLAY, TR_TOBODY_URI, TR_TOBODY_TAG,
        TR_TOBODY_URI_USER, TR_TOBODY_URI_HOST, TR_TOBODY_PARAMS
 };
+enum _tr_line_subtype {
+       TR_LINE_NONE=0, TR_LINE_COUNT, TR_LINE_AT, TR_LINE_SW
+};
 
 
 char* tr_parse_string(str *in, trans_t *tr);
@@ -65,6 +68,7 @@ char* tr_parse_uri(str *in, trans_t *tr);
 char* tr_parse_paramlist(str *in, trans_t *tr);
 char* tr_parse_nameaddr(str *in, trans_t *tr);
 char* tr_parse_tobody(str* in, trans_t *t);
+char* tr_parse_line(str* in, trans_t *t);
 
 int tr_init_buffers(void);
 


_______________________________________________
sr-dev mailing list
[email protected]
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev

Reply via email to