1355b4669Sjacobs /* 2355b4669Sjacobs * CDDL HEADER START 3355b4669Sjacobs * 4355b4669Sjacobs * The contents of this file are subject to the terms of the 5355b4669Sjacobs * Common Development and Distribution License (the "License"). 6355b4669Sjacobs * You may not use this file except in compliance with the License. 7355b4669Sjacobs * 8355b4669Sjacobs * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9355b4669Sjacobs * or http://www.opensolaris.org/os/licensing. 10355b4669Sjacobs * See the License for the specific language governing permissions 11355b4669Sjacobs * and limitations under the License. 12355b4669Sjacobs * 13355b4669Sjacobs * When distributing Covered Code, include this CDDL HEADER in each 14355b4669Sjacobs * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15355b4669Sjacobs * If applicable, add the following below this CDDL HEADER, with the 16355b4669Sjacobs * fields enclosed by brackets "[]" replaced with your own identifying 17355b4669Sjacobs * information: Portions Copyright [yyyy] [name of copyright owner] 18355b4669Sjacobs * 19355b4669Sjacobs * CDDL HEADER END 20355b4669Sjacobs */ 21355b4669Sjacobs 22355b4669Sjacobs /* 23*23a1cceaSRoger A. Faulkner * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 24355b4669Sjacobs */ 25355b4669Sjacobs 26355b4669Sjacobs /* $Id: uri.c 146 2006-03-24 00:26:54Z njacobs $ */ 27355b4669Sjacobs 28355b4669Sjacobs /*LINTLIBRARY*/ 29355b4669Sjacobs 30355b4669Sjacobs #include <stdio.h> 31355b4669Sjacobs #include <stdlib.h> 32355b4669Sjacobs #include <unistd.h> 33355b4669Sjacobs #include <string.h> 34355b4669Sjacobs #include <sys/types.h> 35355b4669Sjacobs #include <errno.h> 36355b4669Sjacobs #include "uri.h" 37355b4669Sjacobs 38355b4669Sjacobs /* 39355b4669Sjacobs * This will handle the following forms: 40355b4669Sjacobs * scheme:scheme_data 41355b4669Sjacobs * scheme://[[user[:password]@]host[:port]]/path[[#fragment]|[?query]] 42355b4669Sjacobs */ 43355b4669Sjacobs int 44355b4669Sjacobs uri_from_string(char *string, uri_t **uri) 45355b4669Sjacobs { 46355b4669Sjacobs char *ptr; 47355b4669Sjacobs uri_t *u; 48355b4669Sjacobs 49355b4669Sjacobs if ((string == NULL) || (uri == NULL)) { 50355b4669Sjacobs errno = EINVAL; 51355b4669Sjacobs return (-1); 52355b4669Sjacobs } 53355b4669Sjacobs 54355b4669Sjacobs /* find the scheme:scheme_part split */ 55355b4669Sjacobs if ((ptr = strchr(string, ':')) == NULL) { 56355b4669Sjacobs errno = EINVAL; 57355b4669Sjacobs return (-1); 58355b4669Sjacobs } 59355b4669Sjacobs 60355b4669Sjacobs if ((*uri = u = calloc(1, sizeof (*u))) == NULL) 61355b4669Sjacobs return (-1); 62355b4669Sjacobs 63355b4669Sjacobs u->scheme = strndup(string, ptr - string); 64355b4669Sjacobs 65355b4669Sjacobs if ((ptr[1] == '/') && (ptr[2] == '/')) { 66355b4669Sjacobs /* 67355b4669Sjacobs * CSTYLED 68355b4669Sjacobs * scheme://[host_part]/[path_part] 69355b4669Sjacobs */ 70355b4669Sjacobs char *end = NULL, *user = NULL, *host = NULL, *path = NULL; 71355b4669Sjacobs 72355b4669Sjacobs string = ptr + 3; /* skip the :// */ 73355b4669Sjacobs 74355b4669Sjacobs if ((path = end = strchr(string, '/')) == NULL) 75*23a1cceaSRoger A. Faulkner for (end = string; *end != '\0'; end++) 76*23a1cceaSRoger A. Faulkner continue; 77355b4669Sjacobs 78355b4669Sjacobs u->host_part = strndup(string, end - string); 79355b4669Sjacobs 80355b4669Sjacobs for (host = string; host < end; host ++) 81355b4669Sjacobs if (*host == '@') { 82355b4669Sjacobs /* string to host is the user part */ 83355b4669Sjacobs u->user_part = strndup(string, host-string); 84355b4669Sjacobs /* host+1 to end is the host part */ 85355b4669Sjacobs u->host_part = strndup(host + 1, 86355b4669Sjacobs end - (host+1)); 87355b4669Sjacobs user = string; 88355b4669Sjacobs host++; 89355b4669Sjacobs break; 90355b4669Sjacobs } 91355b4669Sjacobs 92355b4669Sjacobs if (user != NULL) { 93355b4669Sjacobs char *password = NULL; 94355b4669Sjacobs 95355b4669Sjacobs for (password = user; (password < host - 1); password++) 96355b4669Sjacobs if (*password == ':') { 97355b4669Sjacobs u->password = strndup(password + 1, 98355b4669Sjacobs host - password - 2); 99355b4669Sjacobs break; 100355b4669Sjacobs } 101355b4669Sjacobs u->user = strndup(user, password - user); 102355b4669Sjacobs } else 103355b4669Sjacobs host = string; 104355b4669Sjacobs 105355b4669Sjacobs if (host != NULL) { 106355b4669Sjacobs char *port = NULL; 107355b4669Sjacobs 108355b4669Sjacobs for (port = host; (port < path); port++) 109355b4669Sjacobs if ((*port == ':') || (*port == '/')) 110355b4669Sjacobs break; 111355b4669Sjacobs 112355b4669Sjacobs if (port < path) { 113355b4669Sjacobs u->port = strndup(port + 1, path - port - 1); 114355b4669Sjacobs } 115355b4669Sjacobs 116355b4669Sjacobs u->host = strndup(host, port - host); 117355b4669Sjacobs } 118355b4669Sjacobs 119355b4669Sjacobs if (path != NULL) { 120355b4669Sjacobs char *name = strrchr(path, '/'); 121355b4669Sjacobs 122355b4669Sjacobs u->path_part = strdup(path); 123355b4669Sjacobs 124355b4669Sjacobs if (name != NULL) { 125355b4669Sjacobs char *query, *fragment; 126355b4669Sjacobs 127355b4669Sjacobs query = strrchr(name, '?'); 128355b4669Sjacobs if ((query != NULL) && (*query != '\0')) { 129355b4669Sjacobs u->query = strdup(query + 1); 130355b4669Sjacobs end = query; 131*23a1cceaSRoger A. Faulkner } else { 132*23a1cceaSRoger A. Faulkner for (end = path; *end != '\0'; end++) 133*23a1cceaSRoger A. Faulkner continue; 134*23a1cceaSRoger A. Faulkner } 135355b4669Sjacobs 136355b4669Sjacobs fragment = strrchr(name, '#'); 137355b4669Sjacobs if ((fragment != NULL) && (*fragment != '\0')) { 138355b4669Sjacobs u->fragment = strndup(fragment + 1, 139355b4669Sjacobs end - fragment - 1); 140355b4669Sjacobs end = fragment; 141355b4669Sjacobs } 142355b4669Sjacobs 143355b4669Sjacobs u->path = strndup(path, end - path); 144355b4669Sjacobs } 145355b4669Sjacobs } 146355b4669Sjacobs } else { /* scheme:scheme_part */ 147355b4669Sjacobs u->scheme_part = strdup(&ptr[1]); 148355b4669Sjacobs } 149355b4669Sjacobs 150c1ecd8b9Sjacobs if ((u->host_part == NULL) && (u->path_part == NULL) && 151c1ecd8b9Sjacobs (u->scheme_part == NULL)) { 152c1ecd8b9Sjacobs errno = EINVAL; 153c1ecd8b9Sjacobs uri_free(u); 154c1ecd8b9Sjacobs *uri = NULL; 155c1ecd8b9Sjacobs return (-1); 156c1ecd8b9Sjacobs } 157c1ecd8b9Sjacobs 158355b4669Sjacobs return (0); 159355b4669Sjacobs } 160355b4669Sjacobs 161355b4669Sjacobs int 162355b4669Sjacobs uri_to_string(uri_t *uri, char *buffer, size_t buflen) 163355b4669Sjacobs { 164e059026eSKeerthi Kondaka char *uri_ppfix; 165e059026eSKeerthi Kondaka 166355b4669Sjacobs if ((uri == NULL) || (buffer == NULL) || (buflen == 0) || 167355b4669Sjacobs (uri->scheme == NULL) || 168355b4669Sjacobs ((uri->password != NULL) && (uri->user == NULL)) || 169355b4669Sjacobs ((uri->user != NULL) && (uri->host == NULL)) || 170355b4669Sjacobs ((uri->port != NULL) && (uri->host == NULL)) || 171355b4669Sjacobs ((uri->fragment != NULL) && (uri->path == NULL)) || 172355b4669Sjacobs ((uri->query != NULL) && (uri->path == NULL))) { 173355b4669Sjacobs errno = EINVAL; 174355b4669Sjacobs return (-1); 175355b4669Sjacobs } 176e059026eSKeerthi Kondaka if (uri->path == NULL || uri->path[0] == '/') 177e059026eSKeerthi Kondaka uri_ppfix = ""; 178e059026eSKeerthi Kondaka else 179e059026eSKeerthi Kondaka uri_ppfix = "/"; 180355b4669Sjacobs 181355b4669Sjacobs (void) memset(buffer, 0, buflen); 182355b4669Sjacobs 183355b4669Sjacobs if (uri->scheme_part == NULL) { 184355b4669Sjacobs (void) snprintf(buffer, buflen, 185355b4669Sjacobs "%s://%s%s%s%s%s%s%s%s%s%s%s%s%s", 186355b4669Sjacobs uri->scheme, 187355b4669Sjacobs (uri->user ? uri->user : ""), 188355b4669Sjacobs (uri->password ? ":" : ""), 189355b4669Sjacobs (uri->password ? uri->password : ""), 190355b4669Sjacobs (uri->user ? "@": ""), 191355b4669Sjacobs (uri->host ? uri->host : ""), 192355b4669Sjacobs (uri->port ? ":" : ""), 193355b4669Sjacobs (uri->port ? uri->port : ""), 194e059026eSKeerthi Kondaka uri_ppfix, 195e059026eSKeerthi Kondaka (uri->path ? uri->path : ""), 196355b4669Sjacobs (uri->fragment ? "#" : ""), 197355b4669Sjacobs (uri->fragment ? uri->fragment : ""), 198355b4669Sjacobs (uri->query ? "?" : ""), 199355b4669Sjacobs (uri->query ? uri->query : "")); 200355b4669Sjacobs } else { 201355b4669Sjacobs (void) snprintf(buffer, buflen, "%s:%s", uri->scheme, 202355b4669Sjacobs uri->scheme_part); 203355b4669Sjacobs } 204355b4669Sjacobs 205355b4669Sjacobs return (0); 206355b4669Sjacobs } 207355b4669Sjacobs 208355b4669Sjacobs void 209355b4669Sjacobs uri_free(uri_t *uri) 210355b4669Sjacobs { 211355b4669Sjacobs if (uri != NULL) { 212355b4669Sjacobs if (uri->scheme != NULL) 213355b4669Sjacobs free(uri->scheme); 214355b4669Sjacobs if (uri->scheme_part != NULL) 215355b4669Sjacobs free(uri->scheme_part); 216355b4669Sjacobs if (uri->user != NULL) 217355b4669Sjacobs free(uri->user); 218355b4669Sjacobs if (uri->password != NULL) 219355b4669Sjacobs free(uri->password); 220355b4669Sjacobs if (uri->host != NULL) 221355b4669Sjacobs free(uri->host); 222355b4669Sjacobs if (uri->port != NULL) 223355b4669Sjacobs free(uri->port); 224355b4669Sjacobs if (uri->path != NULL) 225355b4669Sjacobs free(uri->path); 226355b4669Sjacobs if (uri->fragment != NULL) 227355b4669Sjacobs free(uri->fragment); 228355b4669Sjacobs if (uri->query != NULL) 229355b4669Sjacobs free(uri->query); 230355b4669Sjacobs /* help me debug */ 231355b4669Sjacobs if (uri->user_part != NULL) 232355b4669Sjacobs free(uri->user_part); 233355b4669Sjacobs if (uri->host_part != NULL) 234355b4669Sjacobs free(uri->host_part); 235355b4669Sjacobs if (uri->path_part != NULL) 236355b4669Sjacobs free(uri->path_part); 237355b4669Sjacobs free(uri); 238355b4669Sjacobs } 239355b4669Sjacobs } 240355b4669Sjacobs 241355b4669Sjacobs #ifdef DEADBEEF 242355b4669Sjacobs static void 243355b4669Sjacobs uri_dump(FILE *fp, uri_t *uri) 244355b4669Sjacobs { 245355b4669Sjacobs if (uri != NULL) { 246355b4669Sjacobs fprintf(fp, "URI:\n"); 247355b4669Sjacobs if (uri->scheme != NULL) 248355b4669Sjacobs fprintf(fp, "scheme: %s\n", uri->scheme); 249355b4669Sjacobs if (uri->scheme_part != NULL) 250355b4669Sjacobs fprintf(fp, "scheme_part: %s\n", uri->scheme_part); 251355b4669Sjacobs if (uri->user != NULL) 252355b4669Sjacobs fprintf(fp, "user: %s\n", uri->user); 253355b4669Sjacobs if (uri->password != NULL) 254355b4669Sjacobs fprintf(fp, "password: %s\n", uri->password); 255355b4669Sjacobs if (uri->host != NULL) 256355b4669Sjacobs fprintf(fp, "host: %s\n", uri->host); 257355b4669Sjacobs if (uri->port != NULL) 258355b4669Sjacobs fprintf(fp, "port: %s\n", uri->port); 259355b4669Sjacobs if (uri->path != NULL) 260355b4669Sjacobs fprintf(fp, "path: %s\n", uri->path); 261355b4669Sjacobs if (uri->fragment != NULL) 262355b4669Sjacobs fprintf(fp, "fragment: %s\n", uri->fragment); 263355b4669Sjacobs if (uri->query != NULL) 264355b4669Sjacobs fprintf(fp, "query: %s\n", uri->query); 265355b4669Sjacobs /* help me debug */ 266355b4669Sjacobs if (uri->user_part != NULL) 267355b4669Sjacobs fprintf(fp, "user_part: %s\n", uri->user_part); 268355b4669Sjacobs if (uri->host_part != NULL) 269355b4669Sjacobs fprintf(fp, "host_part: %s\n", uri->host_part); 270355b4669Sjacobs if (uri->path_part != NULL) 271355b4669Sjacobs fprintf(fp, "path_part: %s\n", uri->path_part); 272355b4669Sjacobs fflush(fp); 273355b4669Sjacobs } 274355b4669Sjacobs } 275355b4669Sjacobs 276355b4669Sjacobs int 277355b4669Sjacobs main(int argc, char *argv[]) 278355b4669Sjacobs { 279355b4669Sjacobs uri_t *u = NULL; 280355b4669Sjacobs 281355b4669Sjacobs if (argc != 2) { 282355b4669Sjacobs fprintf(stderr, "Usage: %s uri\n", argv[0]); 283355b4669Sjacobs exit(1); 284355b4669Sjacobs } 285355b4669Sjacobs 286355b4669Sjacobs if (uri_from_string(argv[1], &u) == 0) { 287355b4669Sjacobs char buf[BUFSIZ]; 288355b4669Sjacobs 289355b4669Sjacobs uri_dump(stdout, u); 290355b4669Sjacobs uri_to_string(u, buf, sizeof (buf)); 291355b4669Sjacobs fprintf(stdout, "reconstituted: %s\n", buf); 292355b4669Sjacobs 293355b4669Sjacobs uri_to_string(u, buf, 12); 294355b4669Sjacobs fprintf(stdout, "reconstituted(12): %s\n", buf); 295355b4669Sjacobs } else 296355b4669Sjacobs printf(" failed for %s (%s)\n", argv[1], strerror(errno)); 297355b4669Sjacobs 298355b4669Sjacobs exit(0); 299355b4669Sjacobs } 300355b4669Sjacobs #endif /* DEADBEEF */ 301