diff options
Diffstat (limited to 'usr/src/lib/print/libpapi-common/common/uri.c')
-rw-r--r-- | usr/src/lib/print/libpapi-common/common/uri.c | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/usr/src/lib/print/libpapi-common/common/uri.c b/usr/src/lib/print/libpapi-common/common/uri.c new file mode 100644 index 0000000000..9cc6f59006 --- /dev/null +++ b/usr/src/lib/print/libpapi-common/common/uri.c @@ -0,0 +1,303 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + */ + +/* $Id: uri.c 146 2006-03-24 00:26:54Z njacobs $ */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/*LINTLIBRARY*/ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <errno.h> +#include "uri.h" + +static char * +strndup(char *string, size_t length) +{ + char *result = NULL; + + if (length > 0) { + length++; + + + if ((result = calloc(1, length)) != NULL) + (void) strlcat(result, string, length); + } + + return (result); +} + + +/* + * This will handle the following forms: + * scheme:scheme_data + * scheme://[[user[:password]@]host[:port]]/path[[#fragment]|[?query]] + */ +int +uri_from_string(char *string, uri_t **uri) +{ + char *ptr; + uri_t *u; + + if ((string == NULL) || (uri == NULL)) { + errno = EINVAL; + return (-1); + } + + /* find the scheme:scheme_part split */ + if ((ptr = strchr(string, ':')) == NULL) { + errno = EINVAL; + return (-1); + } + + if ((*uri = u = calloc(1, sizeof (*u))) == NULL) + return (-1); + + u->scheme = strndup(string, ptr - string); + + if ((ptr[1] == '/') && (ptr[2] == '/')) { + /* + * CSTYLED + * scheme://[host_part]/[path_part] + */ + char *end = NULL, *user = NULL, *host = NULL, *path = NULL; + + string = ptr + 3; /* skip the :// */ + + if ((path = end = strchr(string, '/')) == NULL) + for (end = string; *end != '\0'; end++); + + u->host_part = strndup(string, end - string); + + for (host = string; host < end; host ++) + if (*host == '@') { + /* string to host is the user part */ + u->user_part = strndup(string, host-string); + /* host+1 to end is the host part */ + u->host_part = strndup(host + 1, + end - (host+1)); + user = string; + host++; + break; + } + + if (user != NULL) { + char *password = NULL; + + for (password = user; (password < host - 1); password++) + if (*password == ':') { + u->password = strndup(password + 1, + host - password - 2); + break; + } + u->user = strndup(user, password - user); + } else + host = string; + + if (host != NULL) { + char *port = NULL; + + for (port = host; (port < path); port++) + if ((*port == ':') || (*port == '/')) + break; + + if (port < path) { + u->port = strndup(port + 1, path - port - 1); + } + + u->host = strndup(host, port - host); + } + + if (path != NULL) { + char *name = strrchr(path, '/'); + + u->path_part = strdup(path); + + if (name != NULL) { + char *query, *fragment; + + query = strrchr(name, '?'); + if ((query != NULL) && (*query != '\0')) { + u->query = strdup(query + 1); + end = query; + } else + for (end = path; *end != '\0'; end++); + + fragment = strrchr(name, '#'); + if ((fragment != NULL) && (*fragment != '\0')) { + u->fragment = strndup(fragment + 1, + end - fragment - 1); + end = fragment; + } + + u->path = strndup(path, end - path); + } + } + } else { /* scheme:scheme_part */ + u->scheme_part = strdup(&ptr[1]); + } + + return (0); +} + +int +uri_to_string(uri_t *uri, char *buffer, size_t buflen) +{ + if ((uri == NULL) || (buffer == NULL) || (buflen == 0) || + (uri->scheme == NULL) || + ((uri->password != NULL) && (uri->user == NULL)) || + ((uri->user != NULL) && (uri->host == NULL)) || + ((uri->port != NULL) && (uri->host == NULL)) || + ((uri->fragment != NULL) && (uri->path == NULL)) || + ((uri->query != NULL) && (uri->path == NULL))) { + errno = EINVAL; + return (-1); + } + + (void) memset(buffer, 0, buflen); + + if (uri->scheme_part == NULL) { + (void) snprintf(buffer, buflen, + "%s://%s%s%s%s%s%s%s%s%s%s%s%s%s", + uri->scheme, + (uri->user ? uri->user : ""), + (uri->password ? ":" : ""), + (uri->password ? uri->password : ""), + (uri->user ? "@": ""), + (uri->host ? uri->host : ""), + (uri->port ? ":" : ""), + (uri->port ? uri->port : ""), + (uri->path[0] != '/' ? "/" : ""), uri->path, + (uri->fragment ? "#" : ""), + (uri->fragment ? uri->fragment : ""), + (uri->query ? "?" : ""), + (uri->query ? uri->query : "")); + } else { + (void) snprintf(buffer, buflen, "%s:%s", uri->scheme, + uri->scheme_part); + } + + return (0); +} + +void +uri_free(uri_t *uri) +{ + if (uri != NULL) { + if (uri->scheme != NULL) + free(uri->scheme); + if (uri->scheme_part != NULL) + free(uri->scheme_part); + if (uri->user != NULL) + free(uri->user); + if (uri->password != NULL) + free(uri->password); + if (uri->host != NULL) + free(uri->host); + if (uri->port != NULL) + free(uri->port); + if (uri->path != NULL) + free(uri->path); + if (uri->fragment != NULL) + free(uri->fragment); + if (uri->query != NULL) + free(uri->query); + /* help me debug */ + if (uri->user_part != NULL) + free(uri->user_part); + if (uri->host_part != NULL) + free(uri->host_part); + if (uri->path_part != NULL) + free(uri->path_part); + free(uri); + } +} + +#ifdef DEADBEEF +static void +uri_dump(FILE *fp, uri_t *uri) +{ + if (uri != NULL) { + fprintf(fp, "URI:\n"); + if (uri->scheme != NULL) + fprintf(fp, "scheme: %s\n", uri->scheme); + if (uri->scheme_part != NULL) + fprintf(fp, "scheme_part: %s\n", uri->scheme_part); + if (uri->user != NULL) + fprintf(fp, "user: %s\n", uri->user); + if (uri->password != NULL) + fprintf(fp, "password: %s\n", uri->password); + if (uri->host != NULL) + fprintf(fp, "host: %s\n", uri->host); + if (uri->port != NULL) + fprintf(fp, "port: %s\n", uri->port); + if (uri->path != NULL) + fprintf(fp, "path: %s\n", uri->path); + if (uri->fragment != NULL) + fprintf(fp, "fragment: %s\n", uri->fragment); + if (uri->query != NULL) + fprintf(fp, "query: %s\n", uri->query); + /* help me debug */ + if (uri->user_part != NULL) + fprintf(fp, "user_part: %s\n", uri->user_part); + if (uri->host_part != NULL) + fprintf(fp, "host_part: %s\n", uri->host_part); + if (uri->path_part != NULL) + fprintf(fp, "path_part: %s\n", uri->path_part); + fflush(fp); + } +} + +int +main(int argc, char *argv[]) +{ + uri_t *u = NULL; + + if (argc != 2) { + fprintf(stderr, "Usage: %s uri\n", argv[0]); + exit(1); + } + + if (uri_from_string(argv[1], &u) == 0) { + char buf[BUFSIZ]; + + uri_dump(stdout, u); + uri_to_string(u, buf, sizeof (buf)); + fprintf(stdout, "reconstituted: %s\n", buf); + + uri_to_string(u, buf, 12); + fprintf(stdout, "reconstituted(12): %s\n", buf); + } else + printf(" failed for %s (%s)\n", argv[1], strerror(errno)); + + exit(0); +} +#endif /* DEADBEEF */ |