1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 /* $Id: uri.c 146 2006-03-24 00:26:54Z njacobs $ */ 27 28 /*LINTLIBRARY*/ 29 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <unistd.h> 33 #include <string.h> 34 #include <sys/types.h> 35 #include <errno.h> 36 #include "uri.h" 37 38 /* 39 * This will handle the following forms: 40 * scheme:scheme_data 41 * scheme://[[user[:password]@]host[:port]]/path[[#fragment]|[?query]] 42 */ 43 int 44 uri_from_string(char *string, uri_t **uri) 45 { 46 char *ptr; 47 uri_t *u; 48 49 if ((string == NULL) || (uri == NULL)) { 50 errno = EINVAL; 51 return (-1); 52 } 53 54 /* find the scheme:scheme_part split */ 55 if ((ptr = strchr(string, ':')) == NULL) { 56 errno = EINVAL; 57 return (-1); 58 } 59 60 if ((*uri = u = calloc(1, sizeof (*u))) == NULL) 61 return (-1); 62 63 u->scheme = strndup(string, ptr - string); 64 65 if ((ptr[1] == '/') && (ptr[2] == '/')) { 66 /* 67 * CSTYLED 68 * scheme://[host_part]/[path_part] 69 */ 70 char *end = NULL, *user = NULL, *host = NULL, *path = NULL; 71 72 string = ptr + 3; /* skip the :// */ 73 74 if ((path = end = strchr(string, '/')) == NULL) 75 for (end = string; *end != '\0'; end++) 76 continue; 77 78 u->host_part = strndup(string, end - string); 79 80 for (host = string; host < end; host ++) 81 if (*host == '@') { 82 /* string to host is the user part */ 83 u->user_part = strndup(string, host-string); 84 /* host+1 to end is the host part */ 85 u->host_part = strndup(host + 1, 86 end - (host+1)); 87 user = string; 88 host++; 89 break; 90 } 91 92 if (user != NULL) { 93 char *password = NULL; 94 95 for (password = user; (password < host - 1); password++) 96 if (*password == ':') { 97 u->password = strndup(password + 1, 98 host - password - 2); 99 break; 100 } 101 u->user = strndup(user, password - user); 102 } else 103 host = string; 104 105 if (host != NULL) { 106 char *port = NULL; 107 108 for (port = host; (port < path); port++) 109 if ((*port == ':') || (*port == '/')) 110 break; 111 112 if (port < path) { 113 u->port = strndup(port + 1, path - port - 1); 114 } 115 116 u->host = strndup(host, port - host); 117 } 118 119 if (path != NULL) { 120 char *name = strrchr(path, '/'); 121 122 u->path_part = strdup(path); 123 124 if (name != NULL) { 125 char *query, *fragment; 126 127 query = strrchr(name, '?'); 128 if ((query != NULL) && (*query != '\0')) { 129 u->query = strdup(query + 1); 130 end = query; 131 } else { 132 for (end = path; *end != '\0'; end++) 133 continue; 134 } 135 136 fragment = strrchr(name, '#'); 137 if ((fragment != NULL) && (*fragment != '\0')) { 138 u->fragment = strndup(fragment + 1, 139 end - fragment - 1); 140 end = fragment; 141 } 142 143 u->path = strndup(path, end - path); 144 } 145 } 146 } else { /* scheme:scheme_part */ 147 u->scheme_part = strdup(&ptr[1]); 148 } 149 150 if ((u->host_part == NULL) && (u->path_part == NULL) && 151 (u->scheme_part == NULL)) { 152 errno = EINVAL; 153 uri_free(u); 154 *uri = NULL; 155 return (-1); 156 } 157 158 return (0); 159 } 160 161 int 162 uri_to_string(uri_t *uri, char *buffer, size_t buflen) 163 { 164 char *uri_ppfix; 165 166 if ((uri == NULL) || (buffer == NULL) || (buflen == 0) || 167 (uri->scheme == NULL) || 168 ((uri->password != NULL) && (uri->user == NULL)) || 169 ((uri->user != NULL) && (uri->host == NULL)) || 170 ((uri->port != NULL) && (uri->host == NULL)) || 171 ((uri->fragment != NULL) && (uri->path == NULL)) || 172 ((uri->query != NULL) && (uri->path == NULL))) { 173 errno = EINVAL; 174 return (-1); 175 } 176 if (uri->path == NULL || uri->path[0] == '/') 177 uri_ppfix = ""; 178 else 179 uri_ppfix = "/"; 180 181 (void) memset(buffer, 0, buflen); 182 183 if (uri->scheme_part == NULL) { 184 (void) snprintf(buffer, buflen, 185 "%s://%s%s%s%s%s%s%s%s%s%s%s%s%s", 186 uri->scheme, 187 (uri->user ? uri->user : ""), 188 (uri->password ? ":" : ""), 189 (uri->password ? uri->password : ""), 190 (uri->user ? "@": ""), 191 (uri->host ? uri->host : ""), 192 (uri->port ? ":" : ""), 193 (uri->port ? uri->port : ""), 194 uri_ppfix, 195 (uri->path ? uri->path : ""), 196 (uri->fragment ? "#" : ""), 197 (uri->fragment ? uri->fragment : ""), 198 (uri->query ? "?" : ""), 199 (uri->query ? uri->query : "")); 200 } else { 201 (void) snprintf(buffer, buflen, "%s:%s", uri->scheme, 202 uri->scheme_part); 203 } 204 205 return (0); 206 } 207 208 void 209 uri_free(uri_t *uri) 210 { 211 if (uri != NULL) { 212 if (uri->scheme != NULL) 213 free(uri->scheme); 214 if (uri->scheme_part != NULL) 215 free(uri->scheme_part); 216 if (uri->user != NULL) 217 free(uri->user); 218 if (uri->password != NULL) 219 free(uri->password); 220 if (uri->host != NULL) 221 free(uri->host); 222 if (uri->port != NULL) 223 free(uri->port); 224 if (uri->path != NULL) 225 free(uri->path); 226 if (uri->fragment != NULL) 227 free(uri->fragment); 228 if (uri->query != NULL) 229 free(uri->query); 230 /* help me debug */ 231 if (uri->user_part != NULL) 232 free(uri->user_part); 233 if (uri->host_part != NULL) 234 free(uri->host_part); 235 if (uri->path_part != NULL) 236 free(uri->path_part); 237 free(uri); 238 } 239 } 240 241 #ifdef DEADBEEF 242 static void 243 uri_dump(FILE *fp, uri_t *uri) 244 { 245 if (uri != NULL) { 246 fprintf(fp, "URI:\n"); 247 if (uri->scheme != NULL) 248 fprintf(fp, "scheme: %s\n", uri->scheme); 249 if (uri->scheme_part != NULL) 250 fprintf(fp, "scheme_part: %s\n", uri->scheme_part); 251 if (uri->user != NULL) 252 fprintf(fp, "user: %s\n", uri->user); 253 if (uri->password != NULL) 254 fprintf(fp, "password: %s\n", uri->password); 255 if (uri->host != NULL) 256 fprintf(fp, "host: %s\n", uri->host); 257 if (uri->port != NULL) 258 fprintf(fp, "port: %s\n", uri->port); 259 if (uri->path != NULL) 260 fprintf(fp, "path: %s\n", uri->path); 261 if (uri->fragment != NULL) 262 fprintf(fp, "fragment: %s\n", uri->fragment); 263 if (uri->query != NULL) 264 fprintf(fp, "query: %s\n", uri->query); 265 /* help me debug */ 266 if (uri->user_part != NULL) 267 fprintf(fp, "user_part: %s\n", uri->user_part); 268 if (uri->host_part != NULL) 269 fprintf(fp, "host_part: %s\n", uri->host_part); 270 if (uri->path_part != NULL) 271 fprintf(fp, "path_part: %s\n", uri->path_part); 272 fflush(fp); 273 } 274 } 275 276 int 277 main(int argc, char *argv[]) 278 { 279 uri_t *u = NULL; 280 281 if (argc != 2) { 282 fprintf(stderr, "Usage: %s uri\n", argv[0]); 283 exit(1); 284 } 285 286 if (uri_from_string(argv[1], &u) == 0) { 287 char buf[BUFSIZ]; 288 289 uri_dump(stdout, u); 290 uri_to_string(u, buf, sizeof (buf)); 291 fprintf(stdout, "reconstituted: %s\n", buf); 292 293 uri_to_string(u, buf, 12); 294 fprintf(stdout, "reconstituted(12): %s\n", buf); 295 } else 296 printf(" failed for %s (%s)\n", argv[1], strerror(errno)); 297 298 exit(0); 299 } 300 #endif /* DEADBEEF */ 301