/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (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 (c) 1999 by Sun Microsystems, Inc. * All rights reserved. */ #pragma ident "%Z%%M% %I% %E% SMI" #include #include #include #include #include #include /* * URL parsing */ #define SLP_IANA "iana" #define SERVICE_PREFIX "service" /* service type struct */ typedef struct slp_type { SLPBoolean isServiceURL; char *atype; char *ctype; char *na; char *orig; } slp_type_t; static SLPError parseType(char *, slp_type_t *); static int validateTypeChars(char *); static int validateTransport(char *); static int checkURLString(char *); SLPError SLPParseSrvURL(char *pcSrvURL, SLPSrvURL** ppSrvURL) { char *p, *q, *r; SLPSrvURL *surl; slp_type_t type[1]; if (!pcSrvURL || !ppSrvURL) { return (SLP_PARAMETER_BAD); } *ppSrvURL = NULL; if (!checkURLString((char *)pcSrvURL)) return (SLP_PARSE_ERROR); if (!(surl = malloc(sizeof (*surl)))) { slp_err(LOG_CRIT, 0, "SLPParseSrvURL", "out of memory"); return (SLP_MEMORY_ALLOC_FAILED); } *ppSrvURL = surl; surl->s_pcSrvType = ""; surl->s_pcNetFamily = ""; surl->s_pcHost = ""; surl->s_iPort = 0; surl->s_pcSrvPart = ""; /* parse type */ p = strstr(pcSrvURL, ":/"); if (!p) goto error; q = pcSrvURL; *p++ = 0; p++; r = strdup(q); if (parseType(r, type) != SLP_OK) goto error; free(r); /* no need to free type since it is on the stack */ surl->s_pcSrvType = q; /* do we have a transport? */ q = strchr(p, '/'); if (!q) goto error; *q++ = 0; if (!validateTransport(p)) goto error; surl->s_pcNetFamily = p; /* may be \0 */ /* host part */ /* do we have a port #? */ p = strchr(q, ':'); r = strchr(q, '/'); if (!p && !r) { /* only host part */ surl->s_pcHost = q; return (SLP_OK); } if (p && !r) { /* host + port, no URL part */ int port; surl->s_pcHost = q; *p++ = 0; port = atoi(p); if (port <= 0) goto error; surl->s_iPort = port; return (SLP_OK); } *r++ = 0; if (!p || p > r) { /* no port */ surl->s_pcHost = q; } else { /* host + port + url part */ int port; surl->s_pcHost = q; *p++ = 0; port = atoi(p); if (port <= 0) goto error; surl->s_iPort = port; } /* r now points to the URL part */ surl->s_pcSrvPart = r; return (SLP_OK); error: free(surl); *ppSrvURL = NULL; return (SLP_PARSE_ERROR); } /* * typeString contains only the service type part of an URL. It should * point to a string which parseType can destructively modify. */ static SLPError parseType(char *typeString, slp_type_t *type) { char *p, *q; /* Initialize type structure */ type->isServiceURL = SLP_FALSE; type->atype = NULL; type->ctype = NULL; type->na = NULL; type->orig = typeString; if (!validateTypeChars(typeString)) return (SLP_PARSE_ERROR); /* Is this a service: URL? */ p = strchr(typeString, ':'); if (strncasecmp( typeString, SERVICE_PREFIX, strlen(SERVICE_PREFIX)) == 0) { type->isServiceURL = SLP_TRUE; if (!p) return (SLP_PARSE_ERROR); *p++ = 0; } else { if (p) /* can't have an abstract type in a non-service url */ return (SLP_PARSE_ERROR); p = typeString; } /* p now points to the beginning of the type */ /* is this an abstract type? */ q = strchr(p, ':'); if (q) { type->atype = p; *q++ = 0; if (!*p) return (SLP_PARSE_ERROR); } else { q = p; } /* q should now point to the concrete type */ /* is there a naming authority? */ p = strchr(q, '.'); if (p) { *p++ = 0; if (!*p) return (SLP_PARSE_ERROR); type->na = p; } if (!*q) return (SLP_PARSE_ERROR); type->ctype = q; return (SLP_OK); } static int validateTransport(char *t) { if (*t == 0 || strcasecmp(t, "ipx") == 0 || strcasecmp(t, "at") == 0) return (1); return (0); } static int checkURLString(char *s) { int i; size_t l = strlen(s); for (i = 0; i < l; i++) { if (isalnum(s[i]) || s[i] == '/' || s[i] == ':' || s[i] == '-' || s[i] == ':' || s[i] == '.' || s[i] == '%' || s[i] == '_' || s[i] == '\''|| s[i] == '*' || s[i] == '(' || s[i] == ')' || s[i] == '$' || s[i] == '!' || s[i] == ',' || s[i] == '+' || s[i] == '\\'|| s[i] == ';' || s[i] == '@' || s[i] == '?' || s[i] == '&' || s[i] == '=') continue; return (0); } return (1); } static int validateTypeChars(char *s) { int i; size_t l = strlen(s); for (i = 0; i < l; i++) if (!isalnum(s[i]) && s[i] != '-' && s[i] != '+' && s[i] != '.' && s[i] != ':') return (0); return (1); }