123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- /* libanode: the Anode C reference implementation
- * Copyright (C) 2009-2010 Adam Ierymenko <[email protected]>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>. */
- #include <stdio.h>
- #include <stdlib.h>
- #include "impl/misc.h"
- #include "anode.h"
- int AnodeURI_parse(AnodeURI *parsed_uri,const char *uri_string)
- {
- char buf[sizeof(AnodeURI)];
- unsigned long ptr = 0;
- char c;
- char *p1,*p2;
- Anode_zero((void *)parsed_uri,sizeof(AnodeURI));
- /* Get the scheme */
- for(;;) {
- c = *(uri_string++);
- if (!c) {
- parsed_uri->scheme[ptr] = (char)0;
- return ANODE_ERR_INVALID_URI;
- } else if (c == ':') {
- parsed_uri->scheme[ptr] = (char)0;
- break;
- } else {
- parsed_uri->scheme[ptr++] = c;
- if (ptr == sizeof(parsed_uri->scheme))
- return ANODE_ERR_BUFFER_TOO_SMALL;
- }
- }
- if (*uri_string == '/') {
- /* If it starts with /, it's a URL */
- /* Skip double slash */
- if (!(*(++uri_string)))
- return 0; /* Scheme with no path */
- if (*uri_string == '/') {
- if (!(*(++uri_string)))
- return 0; /* Scheme with no path */
- }
- /* Get the host section and put it in buf[] */
- ptr = 0;
- while ((*uri_string)&&(*uri_string != '/')) {
- buf[ptr++] = *(uri_string++);
- if (ptr == sizeof(buf))
- return ANODE_ERR_BUFFER_TOO_SMALL;
- }
- buf[ptr] = (char)0;
- /* Parse host section for host, username, password, and port */
- if (buf[0]) {
- p1 = (char *)Anode_strchr(buf,'@');
- if (p1) {
- *(p1++) = (char)0;
- if (*p1) {
- p2 = (char *)Anode_strchr(buf,':');
- if (p2) {
- *(p2++) = (char)0;
- Anode_str_copy(parsed_uri->password,p2,sizeof(parsed_uri->password));
- }
- Anode_str_copy(parsed_uri->username,buf,sizeof(parsed_uri->username));
- } else return ANODE_ERR_INVALID_URI;
- } else p1 = buf;
- p2 = (char *)Anode_strchr(p1,':');
- if (p2) {
- *(p2++) = (char)0;
- if (*p2)
- parsed_uri->port = (int)strtoul(p2,(char **)0,10);
- }
- Anode_str_copy(parsed_uri->host,p1,sizeof(parsed_uri->host));
- }
- /* Get the path, query, and fragment section and put it in buf[] */
- ptr = 0;
- while ((buf[ptr++] = *(uri_string++))) {
- if (ptr == sizeof(buf))
- return ANODE_ERR_BUFFER_TOO_SMALL;
- }
- /* Parse path section for path, query, and fragment */
- if (buf[0]) {
- p1 = (char *)Anode_strchr(buf,'?');
- if (p1) {
- *(p1++) = (char)0;
- p2 = (char *)Anode_strchr(p1,'#');
- if (p2) {
- *(p2++) = (char)0;
- Anode_str_copy(parsed_uri->fragment,p2,sizeof(parsed_uri->fragment));
- }
- Anode_str_copy(parsed_uri->query,p1,sizeof(parsed_uri->query));
- } else {
- p2 = (char *)Anode_strchr(buf,'#');
- if (p2) {
- *(p2++) = (char)0;
- Anode_str_copy(parsed_uri->fragment,p2,sizeof(parsed_uri->fragment));
- }
- }
- Anode_str_copy(parsed_uri->path,buf,sizeof(parsed_uri->path));
- }
- } else {
- /* Otherwise, it's a URN and what remains is all path */
- ptr = 0;
- while ((parsed_uri->path[ptr++] = *(uri_string++))) {
- if (ptr == sizeof(parsed_uri->path))
- return ANODE_ERR_BUFFER_TOO_SMALL;
- }
- }
- return 0;
- }
- char *AnodeURI_to_string(const AnodeURI *uri,char *buf,int len)
- {
- int i = 0;
- char portbuf[16];
- const char *p;
- p = uri->scheme;
- while (*p) { buf[i++] = *(p++); if (i >= len) return (char *)0; }
- buf[i++] = ':'; if (i >= len) return (char *)0;
- if (uri->host[0]) {
- buf[i++] = '/'; if (i >= len) return (char *)0;
- buf[i++] = '/'; if (i >= len) return (char *)0;
- if (uri->username[0]) {
- p = uri->username;
- while (*p) { buf[i++] = *(p++); if (i >= len) return (char *)0; }
- if (uri->password[0]) {
- buf[i++] = ':'; if (i >= len) return (char *)0;
- p = uri->password;
- while (*p) { buf[i++] = *(p++); if (i >= len) return (char *)0; }
- }
- buf[i++] = '@'; if (i >= len) return (char *)0;
- }
- p = uri->host;
- while (*p) { buf[i++] = *(p++); if (i >= len) return (char *)0; }
- if ((uri->port > 0)&&(uri->port <= 0xffff)) {
- buf[i++] = ':'; if (i >= len) return (char *)0;
- snprintf(portbuf,sizeof(portbuf),"%d",uri->port);
- p = portbuf;
- while (*p) { buf[i++] = *(p++); if (i >= len) return (char *)0; }
- }
- }
- p = uri->path;
- while (*p) { buf[i++] = *(p++); if (i >= len) return (char *)0; }
- if (uri->query[0]) {
- buf[i++] = '?'; if (i >= len) return (char *)0;
- p = uri->query;
- while (*p) { buf[i++] = *(p++); if (i >= len) return (char *)0; }
- }
- if (uri->fragment[0]) {
- buf[i++] = '#'; if (i >= len) return (char *)0;
- p = uri->fragment;
- while (*p) { buf[i++] = *(p++); if (i >= len) return (char *)0; }
- }
- buf[i] = (char)0;
- return buf;
- }
|