Browse code

pv: added transformations for url encode/decode

- patch by JoshE, FS#311

Daniel-Constantin Mierla authored on 11/07/2013 13:27:16
Showing 2 changed files
... ...
@@ -104,6 +104,82 @@ char *tr_set_crt_buffer(void)
104 104
 		val->rs.s = _tr_buffer; \
105 105
 	} while(0);
106 106
 
107
+/* -- helper functions */
108
+
109
+/* Converts a hex character to its integer value */
110
+static char pv_from_hex(char ch)
111
+{
112
+	return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
113
+}
114
+
115
+/* Converts an integer value to its hex character */
116
+static char pv_to_hex(char code)
117
+{
118
+	static char hex[] = "0123456789abcdef";
119
+	return hex[code & 15];
120
+}
121
+
122
+/*! \brief
123
+ *  URL Encodes a string for use in a HTTP query
124
+ */
125
+static int urlencode_param(str *sin, str *sout)
126
+{
127
+	char *at, *p;
128
+
129
+	at = sout->s;
130
+	p  = sin->s;
131
+
132
+	if (sin==NULL || sout==NULL || sin->s==NULL || sout->s==NULL ||
133
+			sin->len<0 || sout->len < 3*sin->len+1)
134
+		return -1;
135
+
136
+	while (p < sin->s+sin->len) {
137
+		if (isalnum(*p) || *p == '-' || *p == '_' || *p == '.' || *p == '~')
138
+			*at++ = *p;
139
+		else if (*p == ' ')
140
+			*at++ = '+';
141
+		else
142
+			*at++ = '%', *at++ = pv_to_hex(*p >> 4), *at++ = pv_to_hex(*p & 15);
143
+		p++;
144
+	}
145
+
146
+	*at = 0;
147
+	sout->len = at - sout->s;
148
+	LM_DBG("urlencoded string is <%s>\n", sout->s);
149
+
150
+	return 0;
151
+}
152
+
153
+/* URL Decode a string */
154
+static int urldecode_param(str *sin, str *sout) {
155
+	char *at, *p;
156
+
157
+	at = sout->s;
158
+	p  = sin->s;
159
+
160
+	while (p < sin->s+sin->len) {
161
+		if (*p == '%') {
162
+			if (p[1] && p[2]) {
163
+				*at++ = pv_from_hex(p[1]) << 4 | pv_from_hex(p[2]);
164
+				p += 2;
165
+			}
166
+		} else if (*p == '+') {
167
+			*at++ = ' ';
168
+		} else {
169
+			*at++ = *p;
170
+		}
171
+		p++;
172
+	}
173
+
174
+	*at = 0;
175
+	sout->len = at - sout->s;
176
+
177
+	LM_DBG("urldecoded string is <%s>\n", sout->s);
178
+	return 0;
179
+}
180
+
181
+/* -- transformations functions */
182
+
107 183
 /*!
108 184
  * \brief Evaluate string transformations
109 185
  * \param msg SIP message
... ...
@@ -827,6 +903,34 @@ int tr_eval_string(struct sip_msg *msg, tr_param_t *tp, int subtype,
827 827
 			val->rs.len = j;
828 828
 			break;
829 829
 
830
+		case TR_S_URLENCODEPARAM:
831
+			if(!(val->flags&PV_VAL_STR))
832
+				val->rs.s = int2str(val->ri, &val->rs.len);
833
+			if(val->rs.len>TR_BUFFER_SIZE-1)
834
+				return -1;
835
+			st.s = _tr_buffer;
836
+			st.len = TR_BUFFER_SIZE;
837
+			if (urlencode_param(&val->rs, &st) < 0)
838
+				return -1;
839
+			memset(val, 0, sizeof(pv_value_t));
840
+			val->flags = PV_VAL_STR;
841
+			val->rs = st;
842
+			break;
843
+
844
+		case TR_S_URLDECODEPARAM:
845
+			if(!(val->flags&PV_VAL_STR))
846
+				val->rs.s = int2str(val->ri, &val->rs.len);
847
+			if(val->rs.len>TR_BUFFER_SIZE-1)
848
+				return -1;
849
+			st.s = _tr_buffer;
850
+			st.len = TR_BUFFER_SIZE;
851
+			if (urldecode_param(&val->rs, &st) < 0)
852
+				return -1;
853
+			memset(val, 0, sizeof(pv_value_t));
854
+			val->flags = PV_VAL_STR;
855
+			val->rs = st;
856
+			break;
857
+
830 858
 		default:
831 859
 			LM_ERR("unknown subtype %d\n",
832 860
 					subtype);
... ...
@@ -2061,6 +2165,12 @@ char* tr_parse_string(str* in, trans_t *t)
2061 2061
 			goto error;
2062 2062
 		}
2063 2063
 		goto done;
2064
+	} else if(name.len==15 && strncasecmp(name.s, "urlencode.param", 15)==0) {
2065
+		t->subtype = TR_S_URLENCODEPARAM;
2066
+		goto done;
2067
+	} else if(name.len==15 && strncasecmp(name.s, "urldecode.param", 15)==0) {
2068
+		t->subtype = TR_S_URLDECODEPARAM;
2069
+		goto done;
2064 2070
 	}
2065 2071
 
2066 2072
 	LM_ERR("unknown transformation: %.*s/%.*s/%d!\n", in->len, in->s,
... ...
@@ -41,7 +41,8 @@ enum _tr_s_subtype {
41 41
 	TR_S_ESCAPECOMMON, TR_S_UNESCAPECOMMON, TR_S_ESCAPEUSER, TR_S_UNESCAPEUSER,
42 42
 	TR_S_ESCAPEPARAM, TR_S_UNESCAPEPARAM, TR_S_TOLOWER, TR_S_TOUPPER,
43 43
 	TR_S_STRIP, TR_S_STRIPTAIL, TR_S_PREFIXES, TR_S_PREFIXES_QUOT, TR_S_REPLACE,
44
-	TR_S_TIMEFORMAT, TR_S_TRIM, TR_S_RTRIM, TR_S_LTRIM, TR_S_RM, TR_S_STRIPTO
44
+	TR_S_TIMEFORMAT, TR_S_TRIM, TR_S_RTRIM, TR_S_LTRIM, TR_S_RM, TR_S_STRIPTO,
45
+	TR_S_URLENCODEPARAM, TR_S_URLDECODEPARAM
45 46
 };
46 47
 enum _tr_uri_subtype {
47 48
 	TR_URI_NONE=0, TR_URI_USER, TR_URI_HOST, TR_URI_PASSWD, TR_URI_PORT,