📄 uri.c
字号:
return(-1);
cur = *str;
if (!IS_ALPHA(*cur))
return(2);
cur++;
while (IS_SCHEME(*cur)) cur++;
if (uri != NULL) {
if (uri->scheme != NULL) xmlFree(uri->scheme);
/* !!! strndup */
uri->scheme = xmlURIUnescapeString(*str, cur - *str, NULL);
}
*str = cur;
return(0);
}
/**
* xmlParseURIOpaquePart:
* @uri: pointer to an URI structure
* @str: pointer to the string to analyze
*
* Parse an URI opaque part
*
* opaque_part = uric_no_slash *uric
*
* Returns 0 or the error code
*/
static int
xmlParseURIOpaquePart(xmlURIPtr uri, const char **str)
{
const char *cur;
if (str == NULL)
return (-1);
cur = *str;
if (!(IS_URIC_NO_SLASH(cur) || ((uri != NULL) && (uri->cleanup) && (IS_UNWISE(cur))))) {
return (3);
}
NEXT(cur);
while (IS_URIC(cur) || ((uri != NULL) && (uri->cleanup) && (IS_UNWISE(cur))))
NEXT(cur);
if (uri != NULL) {
if (uri->opaque != NULL)
xmlFree(uri->opaque);
uri->opaque = xmlURIUnescapeString(*str, cur - *str, NULL);
}
*str = cur;
return (0);
}
/**
* xmlParseURIServer:
* @uri: pointer to an URI structure
* @str: pointer to the string to analyze
*
* Parse a server subpart of an URI, it's a finer grain analysis
* of the authority part.
*
* server = [ [ userinfo "@" ] hostport ]
* userinfo = *( unreserved | escaped |
* ";" | ":" | "&" | "=" | "+" | "$" | "," )
* hostport = host [ ":" port ]
* host = hostname | IPv4address | IPv6reference
* hostname = *( domainlabel "." ) toplabel [ "." ]
* domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
* toplabel = alpha | alpha *( alphanum | "-" ) alphanum
* IPv6reference = "[" IPv6address "]"
* IPv6address = hexpart [ ":" IPv4address ]
* IPv4address = 1*3digit "." 1*3digit "." 1*3digit "." 1*3digit
* hexpart = hexseq | hexseq "::" [ hexseq ]| "::" [ hexseq ]
* hexseq = hex4 *( ":" hex4)
* hex4 = 1*4hexdig
* port = *digit
*
* Returns 0 or the error code
*/
static int
xmlParseURIServer(xmlURIPtr uri, const char **str) {
const char *cur;
const char *host, *tmp;
const int IPV4max = 4;
const int IPV6max = 8;
int oct;
if (str == NULL)
return(-1);
cur = *str;
/*
* is there a userinfo ?
*/
while (IS_USERINFO(cur)) NEXT(cur);
if (*cur == '@') {
if (uri != NULL) {
if (uri->user != NULL) xmlFree(uri->user);
uri->user = xmlURIUnescapeString(*str, cur - *str, NULL);
}
cur++;
} else {
if (uri != NULL) {
if (uri->user != NULL) xmlFree(uri->user);
uri->user = NULL;
}
cur = *str;
}
/*
* This can be empty in the case where there is no server
*/
host = cur;
if (*cur == '/') {
if (uri != NULL) {
if (uri->authority != NULL) xmlFree(uri->authority);
uri->authority = NULL;
if (uri->server != NULL) xmlFree(uri->server);
uri->server = NULL;
uri->port = 0;
}
return(0);
}
/*
* host part of hostport can denote an IPV4 address, an IPV6 address
* or an unresolved name. Check the IP first, its easier to detect
* errors if wrong one.
* An IPV6 address must start with a '[' and end with a ']'.
*/
if (*cur == '[') {
int compress=0;
cur++;
for (oct = 0; oct < IPV6max; ++oct) {
if (*cur == ':') {
if (compress)
return(3); /* multiple compression attempted */
if (!oct) { /* initial char is compression */
if (*++cur != ':')
return(3);
}
compress = 1; /* set compression-encountered flag */
cur++; /* skip over the second ':' */
continue;
}
while(IS_HEX(*cur)) cur++;
if (oct == (IPV6max-1))
continue;
if (*cur != ':')
break;
cur++;
}
if ((!compress) && (oct != IPV6max))
return(3);
if (*cur != ']')
return(3);
if (uri != NULL) {
if (uri->server != NULL) xmlFree(uri->server);
uri->server = (char *)xmlStrndup((xmlChar *)host+1,
(cur-host)-1);
}
cur++;
} else {
/*
* Not IPV6, maybe IPV4
*/
for (oct = 0; oct < IPV4max; ++oct) {
if (*cur == '.')
return(3); /* e.g. http://.xml/ or http://18.29..30/ */
while(IS_DIGIT(*cur)) cur++;
if (oct == (IPV4max-1))
continue;
if (*cur != '.')
break;
cur++;
}
}
if ((host[0] != '[') && (oct < IPV4max || (*cur == '.' && cur++) ||
IS_ALPHA(*cur))) {
/* maybe host_name */
if (!IS_ALPHANUM(*cur))
return(4); /* e.g. http://xml.$oft */
do {
do ++cur; while (IS_ALPHANUM(*cur));
if (*cur == '-') {
--cur;
if (*cur == '.')
return(5); /* e.g. http://xml.-soft */
++cur;
continue;
}
if (*cur == '.') {
--cur;
if (*cur == '-')
return(6); /* e.g. http://xml-.soft */
if (*cur == '.')
return(7); /* e.g. http://xml..soft */
++cur;
continue;
}
break;
} while (1);
tmp = cur;
if (tmp[-1] == '.')
--tmp; /* e.g. http://xml.$Oft/ */
do --tmp; while (tmp >= host && IS_ALPHANUM(*tmp));
if ((++tmp == host || tmp[-1] == '.') && !IS_ALPHA(*tmp))
return(8); /* e.g. http://xmlsOft.0rg/ */
}
if (uri != NULL) {
if (uri->authority != NULL) xmlFree(uri->authority);
uri->authority = NULL;
if (host[0] != '[') { /* it's not an IPV6 addr */
if (uri->server != NULL) xmlFree(uri->server);
uri->server = xmlURIUnescapeString(host, cur - host, NULL);
}
}
/*
* finish by checking for a port presence.
*/
if (*cur == ':') {
cur++;
if (IS_DIGIT(*cur)) {
if (uri != NULL)
uri->port = 0;
while (IS_DIGIT(*cur)) {
if (uri != NULL)
uri->port = uri->port * 10 + (*cur - '0');
cur++;
}
}
}
*str = cur;
return(0);
}
/**
* xmlParseURIRelSegment:
* @uri: pointer to an URI structure
* @str: pointer to the string to analyze
*
* Parse an URI relative segment
*
* rel_segment = 1*( unreserved | escaped | ";" | "@" | "&" | "=" |
* "+" | "$" | "," )
*
* Returns 0 or the error code
*/
static int
xmlParseURIRelSegment(xmlURIPtr uri, const char **str)
{
const char *cur;
if (str == NULL)
return (-1);
cur = *str;
if (!(IS_SEGMENT(cur) || ((uri != NULL) && (uri->cleanup) && (IS_UNWISE(cur))))) {
return (3);
}
NEXT(cur);
while (IS_SEGMENT(cur) || ((uri != NULL) && (uri->cleanup) && (IS_UNWISE(cur))))
NEXT(cur);
if (uri != NULL) {
if (uri->path != NULL)
xmlFree(uri->path);
uri->path = xmlURIUnescapeString(*str, cur - *str, NULL);
}
*str = cur;
return (0);
}
/**
* xmlParseURIPathSegments:
* @uri: pointer to an URI structure
* @str: pointer to the string to analyze
* @slash: should we add a leading slash
*
* Parse an URI set of path segments
*
* path_segments = segment *( "/" segment )
* segment = *pchar *( ";" param )
* param = *pchar
*
* Returns 0 or the error code
*/
static int
xmlParseURIPathSegments(xmlURIPtr uri, const char **str, int slash)
{
const char *cur;
if (str == NULL)
return (-1);
cur = *str;
do {
while (IS_PCHAR(cur) || ((uri != NULL) && (uri->cleanup) && (IS_UNWISE(cur))))
NEXT(cur);
while (*cur == ';') {
cur++;
while (IS_PCHAR(cur) || ((uri != NULL) && (uri->cleanup) && (IS_UNWISE(cur))))
NEXT(cur);
}
if (*cur != '/')
break;
cur++;
} while (1);
if (uri != NULL) {
int len, len2 = 0;
char *path;
/*
* Concat the set of path segments to the current path
*/
len = cur - *str;
if (slash)
len++;
if (uri->path != NULL) {
len2 = strlen(uri->path);
len += len2;
}
path = (char *) xmlMallocAtomic(len + 1);
if (path == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlParseURIPathSegments: out of memory\n");
*str = cur;
return (-1);
}
if (uri->path != NULL)
memcpy(path, uri->path, len2);
if (slash) {
path[len2] = '/';
len2++;
}
path[len2] = 0;
if (cur - *str > 0)
xmlURIUnescapeString(*str, cur - *str, &path[len2]);
if (uri->path != NULL)
xmlFree(uri->path);
uri->path = path;
}
*str = cur;
return (0);
}
/**
* xmlParseURIAuthority:
* @uri: pointer to an URI structure
* @str: pointer to the string to analyze
*
* Parse the authority part of an URI.
*
* authority = server | reg_name
* server = [ [ userinfo "@" ] hostport ]
* reg_name = 1*( unreserved | escaped | "$" | "," | ";" | ":" |
* "@" | "&" | "=" | "+" )
*
* Note : this is completely ambiguous since reg_name is allowed to
* use the full set of chars in use by server:
*
* 3.2.1. Registry-based Naming Authority
*
* The structure of a registry-based naming authority is specific
* to the URI scheme, but constrained to the allowed characters
* for an authority component.
*
* Returns 0 or the error code
*/
static int
xmlParseURIAuthority(xmlURIPtr uri, const char **str) {
const char *cur;
int ret;
if (str == NULL)
return(-1);
cur = *str;
/*
* try first to parse it as a server string.
*/
ret = xmlParseURIServer(uri, str);
if ((ret == 0) && (*str != NULL) &&
((**str == 0) || (**str == '/') || (**str == '?')))
return(0);
*str = cur;
/*
* failed, fallback to reg_name
*/
if (!IS_REG_NAME(cur)) {
return(5);
}
NEXT(cur);
while (IS_REG_NAME(cur)) NEXT(cur);
if (uri != NULL) {
if (uri->server != NULL) xmlFree(uri->server);
uri->server = NULL;
if (uri->user != NULL) xmlFree(uri->user);
uri->user = NULL;
if (uri->authority != NULL) xmlFree(uri->authority);
uri->authority = xmlURIUnescapeString(*str, cur - *str, NULL);
}
*str = cur;
return(0);
}
/**
* xmlParseURIHierPart:
* @uri: pointer to an URI structure
* @str: pointer to the string to analyze
*
* Parse an URI hierarchical part
*
* hier_part = ( net_path | abs_path ) [ "?" query ]
* abs_path = "/" path_segments
* net_path = "//" authority [ abs_path ]
*
* Returns 0 or the error code
*/
static int
xmlParseURIHierPart(xmlURIPtr uri, const char **str) {
int ret;
const char *cur;
if (str == NULL)
return(-1);
cur = *str;
if ((cur[0] == '/') && (cur[1] == '/')) {
cur += 2;
ret = xmlParseURIAuthority(uri, &cur);
if (ret != 0)
return(ret);
if (cur[0] == '/') {
cur++;
ret = xmlParseURIPathSegments(uri, &cur, 1);
}
} else if (cur[0] == '/') {
cur++;
ret = xmlParseURIPathSegments(uri, &cur, 1);
} else {
return(4);
}
if (ret != 0)
return(ret);
if (*cur == '?') {
cur++;
ret = xmlParseURIQuery(uri, &cur);
if (ret != 0)
return(ret);
}
*str = cur;
return(0);
}
/**
* xmlParseAbsoluteURI:
* @uri: pointer to an URI structure
* @str: pointer to the string to analyze
*
* Parse an URI reference string and fills in the appropriate fields
* of the @uri structure
*
* absoluteURI = scheme ":" ( hier_part | opaque_part )
*
* Returns 0 or the error code
*/
static int
xmlParseAbsoluteURI(xmlURIPtr uri, const char **str) {
int ret;
const char *cur;
if (str == NULL)
return(-1);
cur = *str;
ret = xmlParseURIScheme(uri, str);
if (ret != 0) return(ret);
if (**str != ':') {
*str = cur;
return(1);
}
(*str)++;
if (**str == '/')
return(xmlParseURIHierPart(uri, str));
return(xmlParseURIOpaquePart(uri, str));
}
/**
* xmlParseRelativeURI:
* @uri: pointer to an URI structure
* @str: pointer to the string to analyze
*
* Parse an relative URI string and fills in the appropriate fields
* of the @uri structure
*
* relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ]
* abs_path = "/" path_segments
* net_path = "//" authority [ abs_path ]
* rel_path = rel_segment [ abs_path ]
*
* Returns 0 or the error code
*/
static int
xmlParseRelativeURI(xmlURIPtr uri, const char **str) {
int ret = 0;
const char *cur;
if (str == NULL)
return(-1);
cur = *str;
if ((cur[0] == '/') && (cur[1] == '/')) {
cur += 2;
ret = xmlParseURIAuthority(uri, &cur);
if (ret != 0)
return(ret);
if (cur[0] == '/') {
cur++;
ret = xmlParseURIPathSegments(uri, &cur, 1);
}
} else if (cur[0] == '/') {
cur++;
ret = xmlParseURIPathSegments(uri, &cur, 1);
} else if (cur[0] != '#' && cur[0] != '?') {
ret = xmlParseURIRelSegment(uri, &cur);
if (ret != 0)
return(ret);
if (cur[0] == '/') {
cur++;
ret = xmlParseURIPathSegments(uri, &cur, 1);
}
}
if (ret != 0)
return(ret);
if (*cur == '?') {
cur++;
ret = xmlParseURIQuery(uri, &cur);
if (ret != 0)
return(ret);
}
*str = cur;
return(ret);
}
/**
* xmlParseURIReference:
* @uri: pointer to an URI structure
* @str: the string to analyze
*
* Parse an URI reference string and fills in the appropriate fields
* of the @uri structure
*
* URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
*
* Returns 0 or the error code
*/
int
xmlParseURIReference(xmlURIPtr uri, const char *str) {
int ret;
const char *tmp = str;
if (str == NULL)
return(-1);
xmlCleanURI(uri);
/*
* Try first to parse absolute refs, then fallback to relative if
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -