⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uri.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 4 页
字号:
	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 + -