📄 uri.c
字号:
/**
* uri.c: set of generic URI related routines
*
* Reference: RFCs 2396, 2732 and 2373
*
* See Copyright for the status of this software.
*
* daniel@veillard.com
*/
#define IN_LIBXML
#include "libxml.h"
#include <string.h>
#include <libxml/xmlmemory.h>
#include <libxml/uri.h>
#include <libxml/globals.h>
#include <libxml/xmlerror.h>
/************************************************************************
* *
* Macros to differentiate various character type *
* directly extracted from RFC 2396 *
* *
************************************************************************/
/*
* alpha = lowalpha | upalpha
*/
#define IS_ALPHA(x) (IS_LOWALPHA(x) || IS_UPALPHA(x))
/*
* lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" |
* "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" |
* "u" | "v" | "w" | "x" | "y" | "z"
*/
#define IS_LOWALPHA(x) (((x) >= 'a') && ((x) <= 'z'))
/*
* upalpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" |
* "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" |
* "U" | "V" | "W" | "X" | "Y" | "Z"
*/
#define IS_UPALPHA(x) (((x) >= 'A') && ((x) <= 'Z'))
#ifdef IS_DIGIT
#undef IS_DIGIT
#endif
/*
* digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
*/
#define IS_DIGIT(x) (((x) >= '0') && ((x) <= '9'))
/*
* alphanum = alpha | digit
*/
#define IS_ALPHANUM(x) (IS_ALPHA(x) || IS_DIGIT(x))
/*
* hex = digit | "A" | "B" | "C" | "D" | "E" | "F" |
* "a" | "b" | "c" | "d" | "e" | "f"
*/
#define IS_HEX(x) ((IS_DIGIT(x)) || (((x) >= 'a') && ((x) <= 'f')) || \
(((x) >= 'A') && ((x) <= 'F')))
/*
* mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
*/
#define IS_MARK(x) (((x) == '-') || ((x) == '_') || ((x) == '.') || \
((x) == '!') || ((x) == '~') || ((x) == '*') || ((x) == '\'') || \
((x) == '(') || ((x) == ')'))
/*
* reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," |
* "[" | "]"
*/
#define IS_RESERVED(x) (((x) == ';') || ((x) == '/') || ((x) == '?') || \
((x) == ':') || ((x) == '@') || ((x) == '&') || ((x) == '=') || \
((x) == '+') || ((x) == '$') || ((x) == ',') || ((x) == '[') || \
((x) == ']'))
/*
* unreserved = alphanum | mark
*/
#define IS_UNRESERVED(x) (IS_ALPHANUM(x) || IS_MARK(x))
/*
* escaped = "%" hex hex
*/
#define IS_ESCAPED(p) ((*(p) == '%') && (IS_HEX((p)[1])) && \
(IS_HEX((p)[2])))
/*
* uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" |
* "&" | "=" | "+" | "$" | ","
*/
#define IS_URIC_NO_SLASH(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) ||\
((*(p) == ';')) || ((*(p) == '?')) || ((*(p) == ':')) ||\
((*(p) == '@')) || ((*(p) == '&')) || ((*(p) == '=')) ||\
((*(p) == '+')) || ((*(p) == '$')) || ((*(p) == ',')))
/*
* pchar = unreserved | escaped | ":" | "@" | "&" | "=" | "+" | "$" | ","
*/
#define IS_PCHAR(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) || \
((*(p) == ':')) || ((*(p) == '@')) || ((*(p) == '&')) ||\
((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) ||\
((*(p) == ',')))
/*
* rel_segment = 1*( unreserved | escaped |
* ";" | "@" | "&" | "=" | "+" | "$" | "," )
*/
#define IS_SEGMENT(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) || \
((*(p) == ';')) || ((*(p) == '@')) || ((*(p) == '&')) || \
((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) || \
((*(p) == ',')))
/*
* scheme = alpha *( alpha | digit | "+" | "-" | "." )
*/
#define IS_SCHEME(x) ((IS_ALPHA(x)) || (IS_DIGIT(x)) || \
((x) == '+') || ((x) == '-') || ((x) == '.'))
/*
* reg_name = 1*( unreserved | escaped | "$" | "," |
* ";" | ":" | "@" | "&" | "=" | "+" )
*/
#define IS_REG_NAME(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) || \
((*(p) == '$')) || ((*(p) == ',')) || ((*(p) == ';')) || \
((*(p) == ':')) || ((*(p) == '@')) || ((*(p) == '&')) || \
((*(p) == '=')) || ((*(p) == '+')))
/*
* userinfo = *( unreserved | escaped | ";" | ":" | "&" | "=" |
* "+" | "$" | "," )
*/
#define IS_USERINFO(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) || \
((*(p) == ';')) || ((*(p) == ':')) || ((*(p) == '&')) || \
((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) || \
((*(p) == ',')))
/*
* uric = reserved | unreserved | escaped
*/
#define IS_URIC(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) || \
(IS_RESERVED(*(p))))
/*
* unwise = "{" | "}" | "|" | "\" | "^" | "`"
*/
#define IS_UNWISE(p) \
(((*(p) == '{')) || ((*(p) == '}')) || ((*(p) == '|')) || \
((*(p) == '\\')) || ((*(p) == '^')) || ((*(p) == '[')) || \
((*(p) == ']')) || ((*(p) == '`')))
/*
* Skip to next pointer char, handle escaped sequences
*/
#define NEXT(p) ((*p == '%')? p += 3 : p++)
/*
* Productions from the spec.
*
* authority = server | reg_name
* reg_name = 1*( unreserved | escaped | "$" | "," |
* ";" | ":" | "@" | "&" | "=" | "+" )
*
* path = [ abs_path | opaque_part ]
*/
/************************************************************************
* *
* Generic URI structure functions *
* *
************************************************************************/
/**
* xmlCreateURI:
*
* Simply creates an empty xmlURI
*
* Returns the new structure or NULL in case of error
*/
xmlURIPtr
xmlCreateURI(void) {
xmlURIPtr ret;
ret = (xmlURIPtr) xmlMalloc(sizeof(xmlURI));
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlCreateURI: out of memory\n");
return(NULL);
}
memset(ret, 0, sizeof(xmlURI));
return(ret);
}
/**
* xmlSaveUri:
* @uri: pointer to an xmlURI
*
* Save the URI as an escaped string
*
* Returns a new string (to be deallocated by caller)
*/
xmlChar *
xmlSaveUri(xmlURIPtr uri) {
xmlChar *ret = NULL;
const char *p;
int len;
int max;
if (uri == NULL) return(NULL);
max = 80;
ret = (xmlChar *) xmlMallocAtomic((max + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlSaveUri: out of memory\n");
return(NULL);
}
len = 0;
if (uri->scheme != NULL) {
p = uri->scheme;
while (*p != 0) {
if (len >= max) {
max *= 2;
ret = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlSaveUri: out of memory\n");
return(NULL);
}
}
ret[len++] = *p++;
}
if (len >= max) {
max *= 2;
ret = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlSaveUri: out of memory\n");
return(NULL);
}
}
ret[len++] = ':';
}
if (uri->opaque != NULL) {
p = uri->opaque;
while (*p != 0) {
if (len + 3 >= max) {
max *= 2;
ret = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlSaveUri: out of memory\n");
return(NULL);
}
}
if (IS_RESERVED(*(p)) || IS_UNRESERVED(*(p)))
ret[len++] = *p++;
else {
int val = *(unsigned char *)p++;
int hi = val / 0x10, lo = val % 0x10;
ret[len++] = '%';
ret[len++] = hi + (hi > 9? 'A'-10 : '0');
ret[len++] = lo + (lo > 9? 'A'-10 : '0');
}
}
} else {
if (uri->server != NULL) {
if (len + 3 >= max) {
max *= 2;
ret = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlSaveUri: out of memory\n");
return(NULL);
}
}
ret[len++] = '/';
ret[len++] = '/';
if (uri->user != NULL) {
p = uri->user;
while (*p != 0) {
if (len + 3 >= max) {
max *= 2;
ret = (xmlChar *) xmlRealloc(ret,
(max + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlSaveUri: out of memory\n");
return(NULL);
}
}
if ((IS_UNRESERVED(*(p))) ||
((*(p) == ';')) || ((*(p) == ':')) ||
((*(p) == '&')) || ((*(p) == '=')) ||
((*(p) == '+')) || ((*(p) == '$')) ||
((*(p) == ',')))
ret[len++] = *p++;
else {
int val = *(unsigned char *)p++;
int hi = val / 0x10, lo = val % 0x10;
ret[len++] = '%';
ret[len++] = hi + (hi > 9? 'A'-10 : '0');
ret[len++] = lo + (lo > 9? 'A'-10 : '0');
}
}
if (len + 3 >= max) {
max *= 2;
ret = (xmlChar *) xmlRealloc(ret,
(max + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlSaveUri: out of memory\n");
return(NULL);
}
}
ret[len++] = '@';
}
p = uri->server;
while (*p != 0) {
if (len >= max) {
max *= 2;
ret = (xmlChar *) xmlRealloc(ret,
(max + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlSaveUri: out of memory\n");
return(NULL);
}
}
ret[len++] = *p++;
}
if (uri->port > 0) {
if (len + 10 >= max) {
max *= 2;
ret = (xmlChar *) xmlRealloc(ret,
(max + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlSaveUri: out of memory\n");
return(NULL);
}
}
len += snprintf((char *) &ret[len], max - len, ":%d", uri->port);
}
} else if (uri->authority != NULL) {
if (len + 3 >= max) {
max *= 2;
ret = (xmlChar *) xmlRealloc(ret,
(max + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlSaveUri: out of memory\n");
return(NULL);
}
}
ret[len++] = '/';
ret[len++] = '/';
p = uri->authority;
while (*p != 0) {
if (len + 3 >= max) {
max *= 2;
ret = (xmlChar *) xmlRealloc(ret,
(max + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlSaveUri: out of memory\n");
return(NULL);
}
}
if ((IS_UNRESERVED(*(p))) ||
((*(p) == '$')) || ((*(p) == ',')) || ((*(p) == ';')) ||
((*(p) == ':')) || ((*(p) == '@')) || ((*(p) == '&')) ||
((*(p) == '=')) || ((*(p) == '+')))
ret[len++] = *p++;
else {
int val = *(unsigned char *)p++;
int hi = val / 0x10, lo = val % 0x10;
ret[len++] = '%';
ret[len++] = hi + (hi > 9? 'A'-10 : '0');
ret[len++] = lo + (lo > 9? 'A'-10 : '0');
}
}
} else if (uri->scheme != NULL) {
if (len + 3 >= max) {
max *= 2;
ret = (xmlChar *) xmlRealloc(ret,
(max + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlSaveUri: out of memory\n");
return(NULL);
}
}
ret[len++] = '/';
ret[len++] = '/';
}
if (uri->path != NULL) {
p = uri->path;
while (*p != 0) {
if (len + 3 >= max) {
max *= 2;
ret = (xmlChar *) xmlRealloc(ret,
(max + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlSaveUri: out of memory\n");
return(NULL);
}
}
if ((IS_UNRESERVED(*(p))) || ((*(p) == '/')) ||
((*(p) == ';')) || ((*(p) == '@')) || ((*(p) == '&')) ||
((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) ||
((*(p) == ',')))
ret[len++] = *p++;
else {
int val = *(unsigned char *)p++;
int hi = val / 0x10, lo = val % 0x10;
ret[len++] = '%';
ret[len++] = hi + (hi > 9? 'A'-10 : '0');
ret[len++] = lo + (lo > 9? 'A'-10 : '0');
}
}
}
if (uri->query != NULL) {
if (len + 3 >= max) {
max *= 2;
ret = (xmlChar *) xmlRealloc(ret,
(max + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlSaveUri: out of memory\n");
return(NULL);
}
}
ret[len++] = '?';
p = uri->query;
while (*p != 0) {
if (len + 3 >= max) {
max *= 2;
ret = (xmlChar *) xmlRealloc(ret,
(max + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlSaveUri: out of memory\n");
return(NULL);
}
}
if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p))))
ret[len++] = *p++;
else {
int val = *(unsigned char *)p++;
int hi = val / 0x10, lo = val % 0x10;
ret[len++] = '%';
ret[len++] = hi + (hi > 9? 'A'-10 : '0');
ret[len++] = lo + (lo > 9? 'A'-10 : '0');
}
}
}
}
if (uri->fragment != NULL) {
if (len + 3 >= max) {
max *= 2;
ret = (xmlChar *) xmlRealloc(ret,
(max + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlSaveUri: out of memory\n");
return(NULL);
}
}
ret[len++] = '#';
p = uri->fragment;
while (*p != 0) {
if (len + 3 >= max) {
max *= 2;
ret = (xmlChar *) xmlRealloc(ret,
(max + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlSaveUri: out of memory\n");
return(NULL);
}
}
if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p))))
ret[len++] = *p++;
else {
int val = *(unsigned char *)p++;
int hi = val / 0x10, lo = val % 0x10;
ret[len++] = '%';
ret[len++] = hi + (hi > 9? 'A'-10 : '0');
ret[len++] = lo + (lo > 9? 'A'-10 : '0');
}
}
}
if (len >= max) {
max *= 2;
ret = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar));
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlSaveUri: out of memory\n");
return(NULL);
}
}
ret[len++] = 0;
return(ret);
}
/**
* xmlPrintURI:
* @stream: a FILE* for the output
* @uri: pointer to an xmlURI
*
* Prints the URI in the stream @stream.
*/
void
xmlPrintURI(FILE *stream, xmlURIPtr uri) {
xmlChar *out;
out = xmlSaveUri(uri);
if (out != NULL) {
fprintf(stream, "%s", (char *) out);
xmlFree(out);
}
}
/**
* xmlCleanURI:
* @uri: pointer to an xmlURI
*
* Make sure the xmlURI struct is free of content
*/
static void
xmlCleanURI(xmlURIPtr uri) {
if (uri == NULL) return;
if (uri->scheme != NULL) xmlFree(uri->scheme);
uri->scheme = NULL;
if (uri->server != NULL) xmlFree(uri->server);
uri->server = NULL;
if (uri->user != NULL) xmlFree(uri->user);
uri->user = NULL;
if (uri->path != NULL) xmlFree(uri->path);
uri->path = NULL;
if (uri->fragment != NULL) xmlFree(uri->fragment);
uri->fragment = NULL;
if (uri->opaque != NULL) xmlFree(uri->opaque);
uri->opaque = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -