url.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 7 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2018 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Author: Jim Winstead <jimw@php.net> |
  16. +----------------------------------------------------------------------+
  17. */
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <ctype.h>
  21. #include <sys/types.h>
  22. char *replace_controlchars_ex(char *str, size_t len)
  23. {
  24. unsigned char *s = (unsigned char *)str;
  25. unsigned char *e = (unsigned char *)str + len;
  26. if (!str) {
  27. return (NULL);
  28. }
  29. while (s < e) {
  30. if (iscntrl(*s)) {
  31. *s='_';
  32. }
  33. s++;
  34. }
  35. return (str);
  36. }
  37. char *replace_controlchars(char *str)
  38. {
  39. return replace_controlchars_ex(str, strlen(str));
  40. }
  41. static int htoi(char *s)
  42. {
  43. int value;
  44. int c;
  45. c = ((unsigned char *)s)[0];
  46. if (isupper(c))
  47. c = tolower(c);
  48. value = (c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10) * 16;
  49. c = ((unsigned char *)s)[1];
  50. if (isupper(c))
  51. c = tolower(c);
  52. value += c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10;
  53. return (value);
  54. }
  55. /* rfc1738:
  56. ...The characters ";",
  57. "/", "?", ":", "@", "=" and "&" are the characters which may be
  58. reserved for special meaning within a scheme...
  59. ...Thus, only alphanumerics, the special characters "$-_.+!*'(),", and
  60. reserved characters used for their reserved purposes may be used
  61. unencoded within a URL...
  62. For added safety, we only leave -_. unencoded.
  63. */
  64. static unsigned char hexchars[] = "0123456789ABCDEF";
  65. void url_encode(char const *s, size_t len, char *out, size_t *out_len)
  66. {
  67. register unsigned char c;
  68. unsigned char *to;
  69. unsigned char const *from, *end;
  70. from = (unsigned char *)s;
  71. end = (unsigned char *)s + len;
  72. to = (unsigned char *)out;
  73. while (from < end) {
  74. c = *from++;
  75. if (c == ' ') {
  76. *to++ = '+';
  77. } else if ((c < '0' && c != '-' && c != '.') ||
  78. (c < 'A' && c > '9') ||
  79. (c > 'Z' && c < 'a' && c != '_') ||
  80. (c > 'z')) {
  81. to[0] = '%';
  82. to[1] = hexchars[c >> 4];
  83. to[2] = hexchars[c & 15];
  84. to += 3;
  85. } else {
  86. *to++ = c;
  87. }
  88. }
  89. *to = '\0';
  90. *out_len = (char *)to - out;
  91. }
  92. void url_decode(char *str, size_t len, char *out, size_t *out_len)
  93. {
  94. char *data = str;
  95. char *dest = out;
  96. while (len--) {
  97. if (*data == '+') {
  98. *dest = ' ';
  99. }
  100. else if (*data == '%' && len >= 2 && isxdigit((int) *(data + 1))
  101. && isxdigit((int) *(data + 2))) {
  102. *dest = (char) htoi(data + 1);
  103. data += 2;
  104. len -= 2;
  105. } else {
  106. *dest = *data;
  107. }
  108. data++;
  109. dest++;
  110. }
  111. *dest = '\0';
  112. *out_len = dest - out;
  113. }
  114. void raw_url_encode(char const *s, size_t len, char *out, size_t *out_len)
  115. {
  116. register size_t x, y;
  117. char *ret = out;
  118. for (x = 0, y = 0; len--; x++, y++) {
  119. char c = s[x];
  120. ret[y] = c;
  121. if ((c < '0' && c != '-' && c != '.') ||
  122. (c < 'A' && c > '9') ||
  123. (c > 'Z' && c < 'a' && c != '_') ||
  124. (c > 'z' && c != '~')) {
  125. ret[y++] = '%';
  126. ret[y++] = hexchars[(unsigned char) c >> 4];
  127. ret[y] = hexchars[(unsigned char) c & 15];
  128. }
  129. }
  130. ret[y] = '\0';
  131. *out_len = ret - out;
  132. }
  133. void raw_url_decode(char *str, size_t len, char *out, size_t *out_len)
  134. {
  135. char *dest = out;
  136. char *data = str;
  137. while (len--) {
  138. if (*data == '%' && len >= 2 && isxdigit((int) *(data + 1))
  139. && isxdigit((int) *(data + 2))) {
  140. *dest = (char) htoi(data + 1);
  141. data += 2;
  142. len -= 2;
  143. } else {
  144. *dest = *data;
  145. }
  146. data++;
  147. dest++;
  148. }
  149. *dest = '\0';
  150. *out_len = dest - out;
  151. }
  152. /*
  153. * Local variables:
  154. * tab-width: 4
  155. * c-basic-offset: 4
  156. * End:
  157. * vim600: sw=4 ts=4 fdm=marker
  158. * vim<600: sw=4 ts=4
  159. */