12264Sjacobs /*
22264Sjacobs * CDDL HEADER START
32264Sjacobs *
42264Sjacobs * The contents of this file are subject to the terms of the
52264Sjacobs * Common Development and Distribution License (the "License").
62264Sjacobs * You may not use this file except in compliance with the License.
72264Sjacobs *
82264Sjacobs * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92264Sjacobs * or http://www.opensolaris.org/os/licensing.
102264Sjacobs * See the License for the specific language governing permissions
112264Sjacobs * and limitations under the License.
122264Sjacobs *
132264Sjacobs * When distributing Covered Code, include this CDDL HEADER in each
142264Sjacobs * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152264Sjacobs * If applicable, add the following below this CDDL HEADER, with the
162264Sjacobs * fields enclosed by brackets "[]" replaced with your own identifying
172264Sjacobs * information: Portions Copyright [yyyy] [name of copyright owner]
182264Sjacobs *
192264Sjacobs * CDDL HEADER END
202264Sjacobs */
212264Sjacobs
222264Sjacobs /*
23*13093SRoger.Faulkner@Oracle.COM * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
242264Sjacobs */
252264Sjacobs
262264Sjacobs /* $Id: uri.c 146 2006-03-24 00:26:54Z njacobs $ */
272264Sjacobs
282264Sjacobs /*LINTLIBRARY*/
292264Sjacobs
302264Sjacobs #include <stdio.h>
312264Sjacobs #include <stdlib.h>
322264Sjacobs #include <unistd.h>
332264Sjacobs #include <string.h>
342264Sjacobs #include <sys/types.h>
352264Sjacobs #include <errno.h>
362264Sjacobs #include "uri.h"
372264Sjacobs
382264Sjacobs /*
392264Sjacobs * This will handle the following forms:
402264Sjacobs * scheme:scheme_data
412264Sjacobs * scheme://[[user[:password]@]host[:port]]/path[[#fragment]|[?query]]
422264Sjacobs */
432264Sjacobs int
uri_from_string(char * string,uri_t ** uri)442264Sjacobs uri_from_string(char *string, uri_t **uri)
452264Sjacobs {
462264Sjacobs char *ptr;
472264Sjacobs uri_t *u;
482264Sjacobs
492264Sjacobs if ((string == NULL) || (uri == NULL)) {
502264Sjacobs errno = EINVAL;
512264Sjacobs return (-1);
522264Sjacobs }
532264Sjacobs
542264Sjacobs /* find the scheme:scheme_part split */
552264Sjacobs if ((ptr = strchr(string, ':')) == NULL) {
562264Sjacobs errno = EINVAL;
572264Sjacobs return (-1);
582264Sjacobs }
592264Sjacobs
602264Sjacobs if ((*uri = u = calloc(1, sizeof (*u))) == NULL)
612264Sjacobs return (-1);
622264Sjacobs
632264Sjacobs u->scheme = strndup(string, ptr - string);
642264Sjacobs
652264Sjacobs if ((ptr[1] == '/') && (ptr[2] == '/')) {
662264Sjacobs /*
672264Sjacobs * CSTYLED
682264Sjacobs * scheme://[host_part]/[path_part]
692264Sjacobs */
702264Sjacobs char *end = NULL, *user = NULL, *host = NULL, *path = NULL;
712264Sjacobs
722264Sjacobs string = ptr + 3; /* skip the :// */
732264Sjacobs
742264Sjacobs if ((path = end = strchr(string, '/')) == NULL)
75*13093SRoger.Faulkner@Oracle.COM for (end = string; *end != '\0'; end++)
76*13093SRoger.Faulkner@Oracle.COM continue;
772264Sjacobs
782264Sjacobs u->host_part = strndup(string, end - string);
792264Sjacobs
802264Sjacobs for (host = string; host < end; host ++)
812264Sjacobs if (*host == '@') {
822264Sjacobs /* string to host is the user part */
832264Sjacobs u->user_part = strndup(string, host-string);
842264Sjacobs /* host+1 to end is the host part */
852264Sjacobs u->host_part = strndup(host + 1,
86*13093SRoger.Faulkner@Oracle.COM end - (host+1));
872264Sjacobs user = string;
882264Sjacobs host++;
892264Sjacobs break;
902264Sjacobs }
912264Sjacobs
922264Sjacobs if (user != NULL) {
932264Sjacobs char *password = NULL;
942264Sjacobs
952264Sjacobs for (password = user; (password < host - 1); password++)
962264Sjacobs if (*password == ':') {
972264Sjacobs u->password = strndup(password + 1,
98*13093SRoger.Faulkner@Oracle.COM host - password - 2);
992264Sjacobs break;
1002264Sjacobs }
1012264Sjacobs u->user = strndup(user, password - user);
1022264Sjacobs } else
1032264Sjacobs host = string;
1042264Sjacobs
1052264Sjacobs if (host != NULL) {
1062264Sjacobs char *port = NULL;
1072264Sjacobs
1082264Sjacobs for (port = host; (port < path); port++)
1092264Sjacobs if ((*port == ':') || (*port == '/'))
1102264Sjacobs break;
1112264Sjacobs
1122264Sjacobs if (port < path) {
1132264Sjacobs u->port = strndup(port + 1, path - port - 1);
1142264Sjacobs }
1152264Sjacobs
1162264Sjacobs u->host = strndup(host, port - host);
1172264Sjacobs }
1182264Sjacobs
1192264Sjacobs if (path != NULL) {
1202264Sjacobs char *name = strrchr(path, '/');
1212264Sjacobs
1222264Sjacobs u->path_part = strdup(path);
1232264Sjacobs
1242264Sjacobs if (name != NULL) {
1252264Sjacobs char *query, *fragment;
1262264Sjacobs
1272264Sjacobs query = strrchr(name, '?');
1282264Sjacobs if ((query != NULL) && (*query != '\0')) {
1292264Sjacobs u->query = strdup(query + 1);
1302264Sjacobs end = query;
131*13093SRoger.Faulkner@Oracle.COM } else {
132*13093SRoger.Faulkner@Oracle.COM for (end = path; *end != '\0'; end++)
133*13093SRoger.Faulkner@Oracle.COM continue;
134*13093SRoger.Faulkner@Oracle.COM }
1352264Sjacobs
1362264Sjacobs fragment = strrchr(name, '#');
1372264Sjacobs if ((fragment != NULL) && (*fragment != '\0')) {
1382264Sjacobs u->fragment = strndup(fragment + 1,
139*13093SRoger.Faulkner@Oracle.COM end - fragment - 1);
1402264Sjacobs end = fragment;
1412264Sjacobs }
1422264Sjacobs
1432264Sjacobs u->path = strndup(path, end - path);
1442264Sjacobs }
1452264Sjacobs }
1462264Sjacobs } else { /* scheme:scheme_part */
1472264Sjacobs u->scheme_part = strdup(&ptr[1]);
1482264Sjacobs }
1492264Sjacobs
1507253Sjacobs if ((u->host_part == NULL) && (u->path_part == NULL) &&
1517253Sjacobs (u->scheme_part == NULL)) {
1527253Sjacobs errno = EINVAL;
1537253Sjacobs uri_free(u);
1547253Sjacobs *uri = NULL;
1557253Sjacobs return (-1);
1567253Sjacobs }
1577253Sjacobs
1582264Sjacobs return (0);
1592264Sjacobs }
1602264Sjacobs
1612264Sjacobs int
uri_to_string(uri_t * uri,char * buffer,size_t buflen)1622264Sjacobs uri_to_string(uri_t *uri, char *buffer, size_t buflen)
1632264Sjacobs {
1649411SKeerthi.Kondaka@Sun.COM char *uri_ppfix;
1659411SKeerthi.Kondaka@Sun.COM
1662264Sjacobs if ((uri == NULL) || (buffer == NULL) || (buflen == 0) ||
1672264Sjacobs (uri->scheme == NULL) ||
1682264Sjacobs ((uri->password != NULL) && (uri->user == NULL)) ||
1692264Sjacobs ((uri->user != NULL) && (uri->host == NULL)) ||
1702264Sjacobs ((uri->port != NULL) && (uri->host == NULL)) ||
1712264Sjacobs ((uri->fragment != NULL) && (uri->path == NULL)) ||
1722264Sjacobs ((uri->query != NULL) && (uri->path == NULL))) {
1732264Sjacobs errno = EINVAL;
1742264Sjacobs return (-1);
1752264Sjacobs }
1769411SKeerthi.Kondaka@Sun.COM if (uri->path == NULL || uri->path[0] == '/')
1779411SKeerthi.Kondaka@Sun.COM uri_ppfix = "";
1789411SKeerthi.Kondaka@Sun.COM else
1799411SKeerthi.Kondaka@Sun.COM uri_ppfix = "/";
1802264Sjacobs
1812264Sjacobs (void) memset(buffer, 0, buflen);
1822264Sjacobs
1832264Sjacobs if (uri->scheme_part == NULL) {
1842264Sjacobs (void) snprintf(buffer, buflen,
1859411SKeerthi.Kondaka@Sun.COM "%s://%s%s%s%s%s%s%s%s%s%s%s%s%s",
1869411SKeerthi.Kondaka@Sun.COM uri->scheme,
1879411SKeerthi.Kondaka@Sun.COM (uri->user ? uri->user : ""),
1889411SKeerthi.Kondaka@Sun.COM (uri->password ? ":" : ""),
1899411SKeerthi.Kondaka@Sun.COM (uri->password ? uri->password : ""),
1909411SKeerthi.Kondaka@Sun.COM (uri->user ? "@": ""),
1919411SKeerthi.Kondaka@Sun.COM (uri->host ? uri->host : ""),
1929411SKeerthi.Kondaka@Sun.COM (uri->port ? ":" : ""),
1939411SKeerthi.Kondaka@Sun.COM (uri->port ? uri->port : ""),
1949411SKeerthi.Kondaka@Sun.COM uri_ppfix,
1959411SKeerthi.Kondaka@Sun.COM (uri->path ? uri->path : ""),
1969411SKeerthi.Kondaka@Sun.COM (uri->fragment ? "#" : ""),
1979411SKeerthi.Kondaka@Sun.COM (uri->fragment ? uri->fragment : ""),
1989411SKeerthi.Kondaka@Sun.COM (uri->query ? "?" : ""),
1999411SKeerthi.Kondaka@Sun.COM (uri->query ? uri->query : ""));
2002264Sjacobs } else {
2012264Sjacobs (void) snprintf(buffer, buflen, "%s:%s", uri->scheme,
202*13093SRoger.Faulkner@Oracle.COM uri->scheme_part);
2032264Sjacobs }
2042264Sjacobs
2052264Sjacobs return (0);
2062264Sjacobs }
2072264Sjacobs
2082264Sjacobs void
uri_free(uri_t * uri)2092264Sjacobs uri_free(uri_t *uri)
2102264Sjacobs {
2112264Sjacobs if (uri != NULL) {
2122264Sjacobs if (uri->scheme != NULL)
2132264Sjacobs free(uri->scheme);
2142264Sjacobs if (uri->scheme_part != NULL)
2152264Sjacobs free(uri->scheme_part);
2162264Sjacobs if (uri->user != NULL)
2172264Sjacobs free(uri->user);
2182264Sjacobs if (uri->password != NULL)
2192264Sjacobs free(uri->password);
2202264Sjacobs if (uri->host != NULL)
2212264Sjacobs free(uri->host);
2222264Sjacobs if (uri->port != NULL)
2232264Sjacobs free(uri->port);
2242264Sjacobs if (uri->path != NULL)
2252264Sjacobs free(uri->path);
2262264Sjacobs if (uri->fragment != NULL)
2272264Sjacobs free(uri->fragment);
2282264Sjacobs if (uri->query != NULL)
2292264Sjacobs free(uri->query);
2302264Sjacobs /* help me debug */
2312264Sjacobs if (uri->user_part != NULL)
2322264Sjacobs free(uri->user_part);
2332264Sjacobs if (uri->host_part != NULL)
2342264Sjacobs free(uri->host_part);
2352264Sjacobs if (uri->path_part != NULL)
2362264Sjacobs free(uri->path_part);
2372264Sjacobs free(uri);
2382264Sjacobs }
2392264Sjacobs }
2402264Sjacobs
2412264Sjacobs #ifdef DEADBEEF
2422264Sjacobs static void
uri_dump(FILE * fp,uri_t * uri)2432264Sjacobs uri_dump(FILE *fp, uri_t *uri)
2442264Sjacobs {
2452264Sjacobs if (uri != NULL) {
2462264Sjacobs fprintf(fp, "URI:\n");
2472264Sjacobs if (uri->scheme != NULL)
2482264Sjacobs fprintf(fp, "scheme: %s\n", uri->scheme);
2492264Sjacobs if (uri->scheme_part != NULL)
2502264Sjacobs fprintf(fp, "scheme_part: %s\n", uri->scheme_part);
2512264Sjacobs if (uri->user != NULL)
2522264Sjacobs fprintf(fp, "user: %s\n", uri->user);
2532264Sjacobs if (uri->password != NULL)
2542264Sjacobs fprintf(fp, "password: %s\n", uri->password);
2552264Sjacobs if (uri->host != NULL)
2562264Sjacobs fprintf(fp, "host: %s\n", uri->host);
2572264Sjacobs if (uri->port != NULL)
2582264Sjacobs fprintf(fp, "port: %s\n", uri->port);
2592264Sjacobs if (uri->path != NULL)
2602264Sjacobs fprintf(fp, "path: %s\n", uri->path);
2612264Sjacobs if (uri->fragment != NULL)
2622264Sjacobs fprintf(fp, "fragment: %s\n", uri->fragment);
2632264Sjacobs if (uri->query != NULL)
2642264Sjacobs fprintf(fp, "query: %s\n", uri->query);
2652264Sjacobs /* help me debug */
2662264Sjacobs if (uri->user_part != NULL)
2672264Sjacobs fprintf(fp, "user_part: %s\n", uri->user_part);
2682264Sjacobs if (uri->host_part != NULL)
2692264Sjacobs fprintf(fp, "host_part: %s\n", uri->host_part);
2702264Sjacobs if (uri->path_part != NULL)
2712264Sjacobs fprintf(fp, "path_part: %s\n", uri->path_part);
2722264Sjacobs fflush(fp);
2732264Sjacobs }
2742264Sjacobs }
2752264Sjacobs
2762264Sjacobs int
main(int argc,char * argv[])2772264Sjacobs main(int argc, char *argv[])
2782264Sjacobs {
2792264Sjacobs uri_t *u = NULL;
2802264Sjacobs
2812264Sjacobs if (argc != 2) {
2822264Sjacobs fprintf(stderr, "Usage: %s uri\n", argv[0]);
2832264Sjacobs exit(1);
2842264Sjacobs }
2852264Sjacobs
2862264Sjacobs if (uri_from_string(argv[1], &u) == 0) {
2872264Sjacobs char buf[BUFSIZ];
2882264Sjacobs
2892264Sjacobs uri_dump(stdout, u);
2902264Sjacobs uri_to_string(u, buf, sizeof (buf));
2912264Sjacobs fprintf(stdout, "reconstituted: %s\n", buf);
2922264Sjacobs
2932264Sjacobs uri_to_string(u, buf, 12);
2942264Sjacobs fprintf(stdout, "reconstituted(12): %s\n", buf);
2952264Sjacobs } else
2962264Sjacobs printf(" failed for %s (%s)\n", argv[1], strerror(errno));
2972264Sjacobs
2982264Sjacobs exit(0);
2992264Sjacobs }
3002264Sjacobs #endif /* DEADBEEF */
301