📄 util.c
字号:
}
cdata = s = apr_palloc(pool, len + 1);
for (scan = elem->first_cdata.first; scan != NULL; scan = scan->next) {
tlen = strlen(scan->text);
memcpy(s, scan->text, tlen);
s += tlen;
}
for (child = elem->first_child; child != NULL; child = child->next) {
for (scan = child->following_cdata.first;
scan != NULL;
scan = scan->next) {
tlen = strlen(scan->text);
memcpy(s, scan->text, tlen);
s += tlen;
}
}
*s = '\0';
if (strip_white) {
/* trim leading whitespace */
while (apr_isspace(*cdata)) /* assume: return false for '\0' */
++cdata;
/* trim trailing whitespace */
while (len-- > 0 && apr_isspace(cdata[len]))
continue;
cdata[len + 1] = '\0';
}
return cdata;
}
DAV_DECLARE(dav_xmlns_info *) dav_xmlns_create(apr_pool_t *pool)
{
dav_xmlns_info *xi = apr_pcalloc(pool, sizeof(*xi));
xi->pool = pool;
xi->uri_prefix = apr_hash_make(pool);
xi->prefix_uri = apr_hash_make(pool);
return xi;
}
DAV_DECLARE(void) dav_xmlns_add(dav_xmlns_info *xi,
const char *prefix, const char *uri)
{
/* this "should" not overwrite a prefix mapping */
apr_hash_set(xi->prefix_uri, prefix, APR_HASH_KEY_STRING, uri);
/* note: this may overwrite an existing URI->prefix mapping, but it
doesn't matter -- any prefix is usuable to specify the URI. */
apr_hash_set(xi->uri_prefix, uri, APR_HASH_KEY_STRING, prefix);
}
DAV_DECLARE(const char *) dav_xmlns_add_uri(dav_xmlns_info *xi,
const char *uri)
{
const char *prefix;
if ((prefix = apr_hash_get(xi->uri_prefix, uri,
APR_HASH_KEY_STRING)) != NULL)
return prefix;
prefix = apr_psprintf(xi->pool, "g%d", xi->count++);
dav_xmlns_add(xi, prefix, uri);
return prefix;
}
DAV_DECLARE(const char *) dav_xmlns_get_uri(dav_xmlns_info *xi,
const char *prefix)
{
return apr_hash_get(xi->prefix_uri, prefix, APR_HASH_KEY_STRING);
}
DAV_DECLARE(const char *) dav_xmlns_get_prefix(dav_xmlns_info *xi,
const char *uri)
{
return apr_hash_get(xi->uri_prefix, uri, APR_HASH_KEY_STRING);
}
DAV_DECLARE(void) dav_xmlns_generate(dav_xmlns_info *xi,
apr_text_header *phdr)
{
apr_hash_index_t *hi = apr_hash_first(xi->pool, xi->prefix_uri);
for (; hi != NULL; hi = apr_hash_next(hi)) {
const void *prefix;
void *uri;
const char *s;
apr_hash_this(hi, &prefix, NULL, &uri);
s = apr_psprintf(xi->pool, " xmlns:%s=\"%s\"",
(const char *)prefix, (const char *)uri);
apr_text_append(xi->pool, phdr, s);
}
}
/* ---------------------------------------------------------------
**
** Timeout header processing
**
*/
/* dav_get_timeout: If the Timeout: header exists, return a time_t
* when this lock is expected to expire. Otherwise, return
* a time_t of DAV_TIMEOUT_INFINITE.
*
* It's unclear if DAV clients are required to understand
* Seconds-xxx and Infinity time values. We assume that they do.
* In addition, for now, that's all we understand, too.
*/
DAV_DECLARE(time_t) dav_get_timeout(request_rec *r)
{
time_t now, expires = DAV_TIMEOUT_INFINITE;
const char *timeout_const = apr_table_get(r->headers_in, "Timeout");
const char *timeout = apr_pstrdup(r->pool, timeout_const), *val;
if (timeout == NULL)
return DAV_TIMEOUT_INFINITE;
/* Use the first thing we understand, or infinity if
* we don't understand anything.
*/
while ((val = ap_getword_white(r->pool, &timeout)) && strlen(val)) {
if (!strncmp(val, "Infinite", 8)) {
return DAV_TIMEOUT_INFINITE;
}
if (!strncmp(val, "Second-", 7)) {
val += 7;
/* ### We need to handle overflow better:
* ### timeout will be <= 2^32 - 1
*/
expires = atol(val);
now = time(NULL);
return now + expires;
}
}
return DAV_TIMEOUT_INFINITE;
}
/* ---------------------------------------------------------------
**
** If Header processing
**
*/
/* add_if_resource returns a new if_header, linking it to next_ih.
*/
static dav_if_header *dav_add_if_resource(apr_pool_t *p, dav_if_header *next_ih,
const char *uri, apr_size_t uri_len)
{
dav_if_header *ih;
if ((ih = apr_pcalloc(p, sizeof(*ih))) == NULL)
return NULL;
ih->uri = uri;
ih->uri_len = uri_len;
ih->next = next_ih;
return ih;
}
/* add_if_state adds a condition to an if_header.
*/
static dav_error * dav_add_if_state(apr_pool_t *p, dav_if_header *ih,
const char *state_token,
dav_if_state_type t, int condition,
const dav_hooks_locks *locks_hooks)
{
dav_if_state_list *new_sl;
new_sl = apr_pcalloc(p, sizeof(*new_sl));
new_sl->condition = condition;
new_sl->type = t;
if (t == dav_if_opaquelock) {
dav_error *err;
if ((err = (*locks_hooks->parse_locktoken)(p, state_token,
&new_sl->locktoken)) != NULL) {
/* In cases where the state token is invalid, we'll just skip
* it rather than return 400.
*/
if (err->error_id == DAV_ERR_LOCK_UNK_STATE_TOKEN) {
return NULL;
}
else {
/* ### maybe add a higher-level description */
return err;
}
}
}
else
new_sl->etag = state_token;
new_sl->next = ih->state;
ih->state = new_sl;
return NULL;
}
/* fetch_next_token returns the substring from str+1
* to the next occurence of char term, or \0, whichever
* occurs first. Leading whitespace is ignored.
*/
static char *dav_fetch_next_token(char **str, char term)
{
char *sp;
char *token;
token = *str + 1;
while (*token && (*token == ' ' || *token == '\t'))
token++;
if ((sp = strchr(token, term)) == NULL)
return NULL;
*sp = '\0';
*str = sp;
return token;
}
/* dav_process_if_header:
*
* If NULL (no error) is returned, then **if_header points to the
* "If" productions structure (or NULL if "If" is not present).
*
* ### this part is bogus:
* If an error is encountered, the error is logged. Parent should
* return err->status.
*/
static dav_error * dav_process_if_header(request_rec *r, dav_if_header **p_ih)
{
dav_error *err;
char *str;
char *list;
const char *state_token;
const char *uri = NULL; /* scope of current production; NULL=no-tag */
apr_size_t uri_len = 0;
dav_if_header *ih = NULL;
apr_uri_t parsed_uri;
const dav_hooks_locks *locks_hooks = DAV_GET_HOOKS_LOCKS(r);
enum {no_tagged, tagged, unknown} list_type = unknown;
int condition;
*p_ih = NULL;
if ((str = apr_pstrdup(r->pool, apr_table_get(r->headers_in, "If"))) == NULL)
return NULL;
while (*str) {
switch(*str) {
case '<':
/* Tagged-list production - following states apply to this uri */
if (list_type == no_tagged
|| ((uri = dav_fetch_next_token(&str, '>')) == NULL)) {
return dav_new_error(r->pool, HTTP_BAD_REQUEST,
DAV_ERR_IF_TAGGED,
"Invalid If-header: unclosed \"<\" or "
"unexpected tagged-list production.");
}
/* 2518 specifies this must be an absolute URI; just take the
* relative part for later comparison against r->uri */
if (apr_uri_parse(r->pool, uri, &parsed_uri) != APR_SUCCESS) {
return dav_new_error(r->pool, HTTP_BAD_REQUEST,
DAV_ERR_IF_TAGGED,
"Invalid URI in tagged If-header.");
}
/* note that parsed_uri.path is allocated; we can trash it */
/* clean up the URI a bit */
ap_getparents(parsed_uri.path);
uri_len = strlen(parsed_uri.path);
if (uri_len > 1 && parsed_uri.path[uri_len - 1] == '/')
parsed_uri.path[--uri_len] = '\0';
uri = parsed_uri.path;
list_type = tagged;
break;
case '(':
/* List production */
/* If a uri has not been encountered, this is a No-Tagged-List */
if (list_type == unknown)
list_type = no_tagged;
if ((list = dav_fetch_next_token(&str, ')')) == NULL) {
return dav_new_error(r->pool, HTTP_BAD_REQUEST,
DAV_ERR_IF_UNCLOSED_PAREN,
"Invalid If-header: unclosed \"(\".");
}
if ((ih = dav_add_if_resource(r->pool, ih, uri, uri_len)) == NULL) {
/* ### dav_add_if_resource() should return an error for us! */
return dav_new_error(r->pool, HTTP_BAD_REQUEST,
DAV_ERR_IF_PARSE,
"Internal server error parsing \"If:\" "
"header.");
}
condition = DAV_IF_COND_NORMAL;
while (*list) {
/* List is the entire production (in a uri scope) */
switch (*list) {
case '<':
if ((state_token = dav_fetch_next_token(&list, '>')) == NULL) {
/* ### add a description to this error */
return dav_new_error(r->pool, HTTP_BAD_REQUEST,
DAV_ERR_IF_PARSE, NULL);
}
if ((err = dav_add_if_state(r->pool, ih, state_token, dav_if_opaquelock,
condition, locks_hooks)) != NULL) {
/* ### maybe add a higher level description */
return err;
}
condition = DAV_IF_COND_NORMAL;
break;
case '[':
if ((state_token = dav_fetch_next_token(&list, ']')) == NULL) {
/* ### add a description to this error */
return dav_new_error(r->pool, HTTP_BAD_REQUEST,
DAV_ERR_IF_PARSE, NULL);
}
if ((err = dav_add_if_state(r->pool, ih, state_token, dav_if_etag,
condition, locks_hooks)) != NULL) {
/* ### maybe add a higher level description */
return err;
}
condition = DAV_IF_COND_NORMAL;
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -