strcommon.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2007 voice-system.ro
  5. *
  6. * This file is part of Kamailio, a free SIP server.
  7. *
  8. * Kamailio is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version
  12. *
  13. * Kamailio is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. *
  22. */
  23. /*!
  24. * \file
  25. * \brief Generic string handling functions
  26. */
  27. #include "../../ut.h"
  28. #include "strcommon.h"
  29. /*! \brief
  30. * add backslashes to special characters
  31. */
  32. int escape_common(char *dst, char *src, int src_len)
  33. {
  34. int i, j;
  35. if(dst==0 || src==0 || src_len<=0)
  36. return 0;
  37. j = 0;
  38. for(i=0; i<src_len; i++)
  39. {
  40. switch(src[i])
  41. {
  42. case '\'':
  43. dst[j++] = '\\';
  44. dst[j++] = src[i];
  45. break;
  46. case '"':
  47. dst[j++] = '\\';
  48. dst[j++] = src[i];
  49. break;
  50. case '\\':
  51. dst[j++] = '\\';
  52. dst[j++] = src[i];
  53. break;
  54. case '\0':
  55. dst[j++] = '\\';
  56. dst[j++] = '0';
  57. break;
  58. default:
  59. dst[j++] = src[i];
  60. }
  61. }
  62. return j;
  63. }
  64. /*! \brief
  65. * remove backslashes to special characters
  66. */
  67. int unescape_common(char *dst, char *src, int src_len)
  68. {
  69. int i, j;
  70. if(dst==0 || src==0 || src_len<=0)
  71. return 0;
  72. j = 0;
  73. i = 0;
  74. while(i<src_len)
  75. {
  76. if(src[i]=='\\' && i+1<src_len)
  77. {
  78. switch(src[i+1])
  79. {
  80. case '\'':
  81. dst[j++] = '\'';
  82. i++;
  83. break;
  84. case '"':
  85. dst[j++] = '"';
  86. i++;
  87. break;
  88. case '\\':
  89. dst[j++] = '\\';
  90. i++;
  91. break;
  92. case '0':
  93. dst[j++] = '\0';
  94. i++;
  95. break;
  96. default:
  97. dst[j++] = src[i];
  98. }
  99. } else {
  100. dst[j++] = src[i];
  101. }
  102. i++;
  103. }
  104. return j;
  105. }
  106. /*! \brief Unscape all printable ASCII characters */
  107. int unescape_user(str *sin, str *sout)
  108. {
  109. char *at, *p, c;
  110. if(sin==NULL || sout==NULL || sin->s==NULL || sout->s==NULL
  111. || sin->len<0 || sout->len < sin->len+1)
  112. return -1;
  113. at = sout->s;
  114. p = sin->s;
  115. while(p < sin->s+sin->len)
  116. {
  117. if (*p == '%')
  118. {
  119. p++;
  120. switch (*p)
  121. {
  122. case '0':
  123. case '1':
  124. case '2':
  125. case '3':
  126. case '4':
  127. case '5':
  128. case '6':
  129. case '7':
  130. case '8':
  131. case '9':
  132. c = (*p - '0') << 4;
  133. break;
  134. case 'a':
  135. case 'b':
  136. case 'c':
  137. case 'd':
  138. case 'e':
  139. case 'f':
  140. c = (*p - 'a' + 10) << 4;
  141. break;
  142. case 'A':
  143. case 'B':
  144. case 'C':
  145. case 'D':
  146. case 'E':
  147. case 'F':
  148. c = (*p - 'A' + 10) << 4;
  149. break;
  150. default:
  151. LM_ERR("invalid hex digit <%u>\n", (unsigned int)*p);
  152. return -1;
  153. }
  154. p++;
  155. switch (*p)
  156. {
  157. case '0':
  158. case '1':
  159. case '2':
  160. case '3':
  161. case '4':
  162. case '5':
  163. case '6':
  164. case '7':
  165. case '8':
  166. case '9':
  167. c = c + (*p - '0');
  168. break;
  169. case 'a':
  170. case 'b':
  171. case 'c':
  172. case 'd':
  173. case 'e':
  174. case 'f':
  175. c = c + (*p - 'a' + 10);
  176. break;
  177. case 'A':
  178. case 'B':
  179. case 'C':
  180. case 'D':
  181. case 'E':
  182. case 'F':
  183. c = c + (*p - 'A' + 10);
  184. break;
  185. default:
  186. LM_ERR("invalid hex digit <%u>\n", (unsigned int)*p);
  187. return -1;
  188. }
  189. if ((c < 32) || (c > 126))
  190. {
  191. LM_ERR("invalid escaped character <%u>\n", (unsigned int)c);
  192. return -1;
  193. }
  194. *at++ = c;
  195. } else {
  196. *at++ = *p;
  197. }
  198. p++;
  199. }
  200. *at = 0;
  201. sout->len = at - sout->s;
  202. LM_DBG("unescaped string is <%s>\n", sout->s);
  203. return 0;
  204. }
  205. /*! \brief
  206. * Escape all printable characters that are not valid in user
  207. * part of request uri
  208. * no_need_to_escape = unreserved | user-unreserved
  209. * unreserved = aplhanum | mark
  210. * mark = - | _ | . | ! | ~ | * | ' | ( | )
  211. * user-unreserved = & | = | + | $ | , | ; | ? | /
  212. */
  213. int escape_user(str *sin, str *sout)
  214. {
  215. char *at, *p;
  216. unsigned char x;
  217. if(sin==NULL || sout==NULL || sin->s==NULL || sout->s==NULL
  218. || sin->len<0 || sout->len < 3*sin->len+1)
  219. return -1;
  220. at = sout->s;
  221. p = sin->s;
  222. while (p < sin->s+sin->len)
  223. {
  224. if (*p < 32 || *p > 126)
  225. {
  226. LM_ERR("invalid escaped character <%u>\n", (unsigned int)*p);
  227. return -1;
  228. }
  229. if (isdigit((int)*p) || ((*p >= 'A') && (*p <= 'Z')) ||
  230. ((*p >= 'a') && (*p <= 'z')))
  231. {
  232. *at = *p;
  233. } else {
  234. switch (*p) {
  235. case '-':
  236. case '_':
  237. case '.':
  238. case '!':
  239. case '~':
  240. case '*':
  241. case '\'':
  242. case '(':
  243. case ')':
  244. case '&':
  245. case '=':
  246. case '+':
  247. case '$':
  248. case ',':
  249. case ';':
  250. case '?':
  251. *at = *p;
  252. break;
  253. default:
  254. *at++ = '%';
  255. x = (*p) >> 4;
  256. if (x < 10)
  257. {
  258. *at++ = x + '0';
  259. } else {
  260. *at++ = x - 10 + 'a';
  261. }
  262. x = (*p) & 0x0f;
  263. if (x < 10) {
  264. *at = x + '0';
  265. } else {
  266. *at = x - 10 + 'a';
  267. }
  268. }
  269. }
  270. at++;
  271. p++;
  272. }
  273. *at = 0;
  274. sout->len = at - sout->s;
  275. LM_DBG("escaped string is <%s>\n", sout->s);
  276. return 0;
  277. }
  278. int unescape_param(str *sin, str *sout)
  279. {
  280. return unescape_user(sin, sout);
  281. }
  282. /*! \brief
  283. * Escape all printable characters that are not valid in
  284. * a param part of request uri
  285. * no_need_to_escape = unreserved | param-unreserved
  286. * unreserved = alphanum | mark
  287. * mark = - | _ | . | ! | ~ | * | ' | ( | )
  288. * param-unreserved = [ | ] | / | : | & | + | $
  289. */
  290. int escape_param(str *sin, str *sout)
  291. {
  292. char *at, *p;
  293. unsigned char x;
  294. if (sin==NULL || sout==NULL || sin->s==NULL || sout->s==NULL ||
  295. sin->len<0 || sout->len < 3*sin->len+1)
  296. return -1;
  297. at = sout->s;
  298. p = sin->s;
  299. while (p < sin->s+sin->len) {
  300. if (*p < 32 || *p > 126) {
  301. LM_ERR("invalid escaped character <%u>\n", (unsigned int)*p);
  302. return -1;
  303. } else if (isdigit((int)*p) || ((*p >= 'A') && (*p <= 'Z')) ||
  304. ((*p >= 'a') && (*p <= 'z'))) {
  305. *at = *p;
  306. } else {
  307. switch (*p) {
  308. case '-':
  309. case '_':
  310. case '.':
  311. case '!':
  312. case '~':
  313. case '*':
  314. case '\'':
  315. case '(':
  316. case ')':
  317. case '[':
  318. case ']':
  319. case '/':
  320. case ':':
  321. case '&':
  322. case '+':
  323. case '$':
  324. *at = *p;
  325. break;
  326. default:
  327. *at++ = '%';
  328. x = (*p) >> 4;
  329. if (x < 10)
  330. {
  331. *at++ = x + '0';
  332. } else {
  333. *at++ = x - 10 + 'a';
  334. }
  335. x = (*p) & 0x0f;
  336. if (x < 10) {
  337. *at = x + '0';
  338. } else {
  339. *at = x - 10 + 'a';
  340. }
  341. break;
  342. }
  343. }
  344. at++;
  345. p++;
  346. }
  347. *at = 0;
  348. sout->len = at - sout->s;
  349. LM_DBG("escaped string is <%s>\n", sout->s);
  350. return 0;
  351. }