Module: sip-router
Branch: master
Commit: 617a444fcbe84290a701228bd78e279bbde4818e
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=617a444…
Author: Daniel-Constantin Mierla <miconda(a)gmail.com>
Committer: Daniel-Constantin Mierla <miconda(a)gmail.com>
Date: Thu Jul 11 15:27:16 2013 +0200
pv: added transformations for url encode/decode
- patch by JoshE, FS#311
---
modules/pv/pv_trans.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++
modules/pv/pv_trans.h | 3 +-
2 files changed, 112 insertions(+), 1 deletions(-)
diff --git a/modules/pv/pv_trans.c b/modules/pv/pv_trans.c
index e4e5455..abfff74 100644
--- a/modules/pv/pv_trans.c
+++ b/modules/pv/pv_trans.c
@@ -104,6 +104,82 @@ char *tr_set_crt_buffer(void)
val->rs.s = _tr_buffer; \
} while(0);
+/* -- helper functions */
+
+/* Converts a hex character to its integer value */
+static char pv_from_hex(char ch)
+{
+ return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
+}
+
+/* Converts an integer value to its hex character */
+static char pv_to_hex(char code)
+{
+ static char hex[] = "0123456789abcdef";
+ return hex[code & 15];
+}
+
+/*! \brief
+ * URL Encodes a string for use in a HTTP query
+ */
+static int urlencode_param(str *sin, str *sout)
+{
+ char *at, *p;
+
+ at = sout->s;
+ p = sin->s;
+
+ if (sin==NULL || sout==NULL || sin->s==NULL || sout->s==NULL ||
+ sin->len<0 || sout->len < 3*sin->len+1)
+ return -1;
+
+ while (p < sin->s+sin->len) {
+ if (isalnum(*p) || *p == '-' || *p == '_' || *p == '.' || *p ==
'~')
+ *at++ = *p;
+ else if (*p == ' ')
+ *at++ = '+';
+ else
+ *at++ = '%', *at++ = pv_to_hex(*p >> 4), *at++ = pv_to_hex(*p &
15);
+ p++;
+ }
+
+ *at = 0;
+ sout->len = at - sout->s;
+ LM_DBG("urlencoded string is <%s>\n", sout->s);
+
+ return 0;
+}
+
+/* URL Decode a string */
+static int urldecode_param(str *sin, str *sout) {
+ char *at, *p;
+
+ at = sout->s;
+ p = sin->s;
+
+ while (p < sin->s+sin->len) {
+ if (*p == '%') {
+ if (p[1] && p[2]) {
+ *at++ = pv_from_hex(p[1]) << 4 | pv_from_hex(p[2]);
+ p += 2;
+ }
+ } else if (*p == '+') {
+ *at++ = ' ';
+ } else {
+ *at++ = *p;
+ }
+ p++;
+ }
+
+ *at = 0;
+ sout->len = at - sout->s;
+
+ LM_DBG("urldecoded string is <%s>\n", sout->s);
+ return 0;
+}
+
+/* -- transformations functions */
+
/*!
* \brief Evaluate string transformations
* \param msg SIP message
@@ -827,6 +903,34 @@ int tr_eval_string(struct sip_msg *msg, tr_param_t *tp, int subtype,
val->rs.len = j;
break;
+ case TR_S_URLENCODEPARAM:
+ if(!(val->flags&PV_VAL_STR))
+ val->rs.s = int2str(val->ri, &val->rs.len);
+ if(val->rs.len>TR_BUFFER_SIZE-1)
+ return -1;
+ st.s = _tr_buffer;
+ st.len = TR_BUFFER_SIZE;
+ if (urlencode_param(&val->rs, &st) < 0)
+ return -1;
+ memset(val, 0, sizeof(pv_value_t));
+ val->flags = PV_VAL_STR;
+ val->rs = st;
+ break;
+
+ case TR_S_URLDECODEPARAM:
+ if(!(val->flags&PV_VAL_STR))
+ val->rs.s = int2str(val->ri, &val->rs.len);
+ if(val->rs.len>TR_BUFFER_SIZE-1)
+ return -1;
+ st.s = _tr_buffer;
+ st.len = TR_BUFFER_SIZE;
+ if (urldecode_param(&val->rs, &st) < 0)
+ return -1;
+ memset(val, 0, sizeof(pv_value_t));
+ val->flags = PV_VAL_STR;
+ val->rs = st;
+ break;
+
default:
LM_ERR("unknown subtype %d\n",
subtype);
@@ -2061,6 +2165,12 @@ char* tr_parse_string(str* in, trans_t *t)
goto error;
}
goto done;
+ } else if(name.len==15 && strncasecmp(name.s, "urlencode.param",
15)==0) {
+ t->subtype = TR_S_URLENCODEPARAM;
+ goto done;
+ } else if(name.len==15 && strncasecmp(name.s, "urldecode.param",
15)==0) {
+ t->subtype = TR_S_URLDECODEPARAM;
+ goto done;
}
LM_ERR("unknown transformation: %.*s/%.*s/%d!\n", in->len, in->s,
diff --git a/modules/pv/pv_trans.h b/modules/pv/pv_trans.h
index e2aa494..8544d8c 100644
--- a/modules/pv/pv_trans.h
+++ b/modules/pv/pv_trans.h
@@ -41,7 +41,8 @@ enum _tr_s_subtype {
TR_S_ESCAPECOMMON, TR_S_UNESCAPECOMMON, TR_S_ESCAPEUSER, TR_S_UNESCAPEUSER,
TR_S_ESCAPEPARAM, TR_S_UNESCAPEPARAM, TR_S_TOLOWER, TR_S_TOUPPER,
TR_S_STRIP, TR_S_STRIPTAIL, TR_S_PREFIXES, TR_S_PREFIXES_QUOT, TR_S_REPLACE,
- TR_S_TIMEFORMAT, TR_S_TRIM, TR_S_RTRIM, TR_S_LTRIM, TR_S_RM, TR_S_STRIPTO
+ TR_S_TIMEFORMAT, TR_S_TRIM, TR_S_RTRIM, TR_S_LTRIM, TR_S_RM, TR_S_STRIPTO,
+ TR_S_URLENCODEPARAM, TR_S_URLDECODEPARAM
};
enum _tr_uri_subtype {
TR_URI_NONE=0, TR_URI_USER, TR_URI_HOST, TR_URI_PASSWD, TR_URI_PORT,