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 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 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 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 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 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