uri.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /* libanode: the Anode C reference implementation
  2. * Copyright (C) 2009-2010 Adam Ierymenko <[email protected]>
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>. */
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include "impl/misc.h"
  19. #include "anode.h"
  20. int AnodeURI_parse(AnodeURI *parsed_uri,const char *uri_string)
  21. {
  22. char buf[sizeof(AnodeURI)];
  23. unsigned long ptr = 0;
  24. char c;
  25. char *p1,*p2;
  26. Anode_zero((void *)parsed_uri,sizeof(AnodeURI));
  27. /* Get the scheme */
  28. for(;;) {
  29. c = *(uri_string++);
  30. if (!c) {
  31. parsed_uri->scheme[ptr] = (char)0;
  32. return ANODE_ERR_INVALID_URI;
  33. } else if (c == ':') {
  34. parsed_uri->scheme[ptr] = (char)0;
  35. break;
  36. } else {
  37. parsed_uri->scheme[ptr++] = c;
  38. if (ptr == sizeof(parsed_uri->scheme))
  39. return ANODE_ERR_BUFFER_TOO_SMALL;
  40. }
  41. }
  42. if (*uri_string == '/') {
  43. /* If it starts with /, it's a URL */
  44. /* Skip double slash */
  45. if (!(*(++uri_string)))
  46. return 0; /* Scheme with no path */
  47. if (*uri_string == '/') {
  48. if (!(*(++uri_string)))
  49. return 0; /* Scheme with no path */
  50. }
  51. /* Get the host section and put it in buf[] */
  52. ptr = 0;
  53. while ((*uri_string)&&(*uri_string != '/')) {
  54. buf[ptr++] = *(uri_string++);
  55. if (ptr == sizeof(buf))
  56. return ANODE_ERR_BUFFER_TOO_SMALL;
  57. }
  58. buf[ptr] = (char)0;
  59. /* Parse host section for host, username, password, and port */
  60. if (buf[0]) {
  61. p1 = (char *)Anode_strchr(buf,'@');
  62. if (p1) {
  63. *(p1++) = (char)0;
  64. if (*p1) {
  65. p2 = (char *)Anode_strchr(buf,':');
  66. if (p2) {
  67. *(p2++) = (char)0;
  68. Anode_str_copy(parsed_uri->password,p2,sizeof(parsed_uri->password));
  69. }
  70. Anode_str_copy(parsed_uri->username,buf,sizeof(parsed_uri->username));
  71. } else return ANODE_ERR_INVALID_URI;
  72. } else p1 = buf;
  73. p2 = (char *)Anode_strchr(p1,':');
  74. if (p2) {
  75. *(p2++) = (char)0;
  76. if (*p2)
  77. parsed_uri->port = (int)strtoul(p2,(char **)0,10);
  78. }
  79. Anode_str_copy(parsed_uri->host,p1,sizeof(parsed_uri->host));
  80. }
  81. /* Get the path, query, and fragment section and put it in buf[] */
  82. ptr = 0;
  83. while ((buf[ptr++] = *(uri_string++))) {
  84. if (ptr == sizeof(buf))
  85. return ANODE_ERR_BUFFER_TOO_SMALL;
  86. }
  87. /* Parse path section for path, query, and fragment */
  88. if (buf[0]) {
  89. p1 = (char *)Anode_strchr(buf,'?');
  90. if (p1) {
  91. *(p1++) = (char)0;
  92. p2 = (char *)Anode_strchr(p1,'#');
  93. if (p2) {
  94. *(p2++) = (char)0;
  95. Anode_str_copy(parsed_uri->fragment,p2,sizeof(parsed_uri->fragment));
  96. }
  97. Anode_str_copy(parsed_uri->query,p1,sizeof(parsed_uri->query));
  98. } else {
  99. p2 = (char *)Anode_strchr(buf,'#');
  100. if (p2) {
  101. *(p2++) = (char)0;
  102. Anode_str_copy(parsed_uri->fragment,p2,sizeof(parsed_uri->fragment));
  103. }
  104. }
  105. Anode_str_copy(parsed_uri->path,buf,sizeof(parsed_uri->path));
  106. }
  107. } else {
  108. /* Otherwise, it's a URN and what remains is all path */
  109. ptr = 0;
  110. while ((parsed_uri->path[ptr++] = *(uri_string++))) {
  111. if (ptr == sizeof(parsed_uri->path))
  112. return ANODE_ERR_BUFFER_TOO_SMALL;
  113. }
  114. }
  115. return 0;
  116. }
  117. char *AnodeURI_to_string(const AnodeURI *uri,char *buf,int len)
  118. {
  119. int i = 0;
  120. char portbuf[16];
  121. const char *p;
  122. p = uri->scheme;
  123. while (*p) { buf[i++] = *(p++); if (i >= len) return (char *)0; }
  124. buf[i++] = ':'; if (i >= len) return (char *)0;
  125. if (uri->host[0]) {
  126. buf[i++] = '/'; if (i >= len) return (char *)0;
  127. buf[i++] = '/'; if (i >= len) return (char *)0;
  128. if (uri->username[0]) {
  129. p = uri->username;
  130. while (*p) { buf[i++] = *(p++); if (i >= len) return (char *)0; }
  131. if (uri->password[0]) {
  132. buf[i++] = ':'; if (i >= len) return (char *)0;
  133. p = uri->password;
  134. while (*p) { buf[i++] = *(p++); if (i >= len) return (char *)0; }
  135. }
  136. buf[i++] = '@'; if (i >= len) return (char *)0;
  137. }
  138. p = uri->host;
  139. while (*p) { buf[i++] = *(p++); if (i >= len) return (char *)0; }
  140. if ((uri->port > 0)&&(uri->port <= 0xffff)) {
  141. buf[i++] = ':'; if (i >= len) return (char *)0;
  142. snprintf(portbuf,sizeof(portbuf),"%d",uri->port);
  143. p = portbuf;
  144. while (*p) { buf[i++] = *(p++); if (i >= len) return (char *)0; }
  145. }
  146. }
  147. p = uri->path;
  148. while (*p) { buf[i++] = *(p++); if (i >= len) return (char *)0; }
  149. if (uri->query[0]) {
  150. buf[i++] = '?'; if (i >= len) return (char *)0;
  151. p = uri->query;
  152. while (*p) { buf[i++] = *(p++); if (i >= len) return (char *)0; }
  153. }
  154. if (uri->fragment[0]) {
  155. buf[i++] = '#'; if (i >= len) return (char *)0;
  156. p = uri->fragment;
  157. while (*p) { buf[i++] = *(p++); if (i >= len) return (char *)0; }
  158. }
  159. buf[i] = (char)0;
  160. return buf;
  161. }