[sr-dev] git:master: pv: added transformations for url encode/decode

Daniel-Constantin Mierla miconda at gmail.com
Thu Jul 11 16:01:39 CEST 2013


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

Author: Daniel-Constantin Mierla <miconda at gmail.com>
Committer: Daniel-Constantin Mierla <miconda at 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,




More information about the sr-dev mailing list