fix etag normalization

This commit is contained in:
wbaumann 2009-05-01 18:26:40 +00:00
parent c5872e5833
commit cde78e7069
2 changed files with 52 additions and 62 deletions

View File

@ -1,6 +1,10 @@
ChangeLog for davfs2 ChangeLog for davfs2
-------------------- --------------------


2009-05-01 Werner Baumann (werner.baumann@onlinehome.de)
* webdav.c:
Fix Etag normalization.

2009-05-01 Werner Baumann (werner.baumann@onlinehome.de) 2009-05-01 Werner Baumann (werner.baumann@onlinehome.de)
* cache.h, dav_open: * cache.h, dav_open:
Add parameter open_create to allow Add parameter open_create to allow

View File

@ -165,8 +165,8 @@ static int use_expect100;
static int has_if_match_bug; static int has_if_match_bug;


/* Some servers sends a weak invalid etag that turns into a valid strong etag /* Some servers sends a weak invalid etag that turns into a valid strong etag
after one second. With this flag set, the weakness indicator is removed, after one second. With this flag set weak etags are not used at all,
otherwise the etag is not used at all. */ otherwise the weakness indicator is removed. */
static int drop_weak_etags; static int drop_weak_etags;


/* Check with HEAD for existence or modification of a file, before locking or /* Check with HEAD for existence or modification of a file, before locking or
@ -233,6 +233,9 @@ lock_refresh(struct ne_lock *lock, time_t *expire);
static ssize_t static ssize_t
log_writer(void *cookie, const char *buffer, size_t size); log_writer(void *cookie, const char *buffer, size_t size);


static char *
normalize_etag(const char *etag);

static void static void
replace_slashes(char **name); replace_slashes(char **name);


@ -697,21 +700,8 @@ dav_get_file(const char *path, const char *cache_path, off_t *size,
*mtime = ne_httpdate_parse(value); *mtime = ne_httpdate_parse(value);


if (etag) { if (etag) {
if (*etag) if (*etag) free(*etag);
free(*etag); *etag = normalize_etag(ne_get_response_header(req, "ETag"));
value = ne_get_response_header(req, "ETag");
if (value && *value == 'W') {
if (drop_weak_etags) {
value = strchr(value, '\"');
} else {
value = NULL;
}
}
if (value) {
*etag = ne_strdup(value);
} else {
*etag = NULL;
}
} }


value = ne_get_response_header(req, "Content-Type"); value = ne_get_response_header(req, "Content-Type");
@ -749,20 +739,8 @@ dav_head(const char *path, char **etag, time_t *mtime, off_t *length,


const char *value = ne_get_response_header(req, "ETag"); const char *value = ne_get_response_header(req, "ETag");
if (!ret && etag && value) { if (!ret && etag && value) {
if (*etag) if (*etag) free(*etag);
free(*etag); *etag = normalize_etag(value);
if (*value == 'W') {
if (drop_weak_etags) {
value = NULL;
} else {
value = strchr(value, '\"');
}
}
if (value) {
*etag = ne_strdup(value);
} else {
*etag = NULL;
}
} }


value = ne_get_response_header(req, "Last-Modified"); value = ne_get_response_header(req, "Last-Modified");
@ -1044,23 +1022,8 @@ dav_put(const char *path, const char *cache_path, int *exists, time_t *expire,
const char *value; const char *value;


if (etag) { if (etag) {
if (*etag) { if (*etag) free(*etag);
free(*etag); *etag = normalize_etag(ne_get_response_header(req, "ETag"));
*etag = NULL;
}
value = ne_get_response_header(req, "ETag");
if (value && *value == 'W') {
if (drop_weak_etags) {
value = strchr(value, '\"');
} else {
value = NULL;
}
}
if (value) {
*etag = ne_strdup(value);
} else {
need_head = 1;
}
} }


if (mtime) { if (mtime) {
@ -1448,6 +1411,42 @@ log_writer(void *cookie, const char *buffer, size_t size)
} }




/* Checks etag for weakness indicator and quotation marks.
The reurn value is either a strong etag with quotation marks or NULL.
Depending on global variable drop_weak_etags weak etags are either
dropped or convertet into strong ones. */
static char *
normalize_etag(const char *etag)
{
if (!etag) return NULL;

const char * e = etag;
if (*e == 'W') {
if (drop_weak_etags) {
return NULL;
} else {
e++;
if (*e == '/') {
e++;
} else {
return NULL;
}
}
}
if (!*e) return NULL;

char *ne = NULL;
if (*e == '\"') {
ne = strdup(e);
} else {
if (asprintf(&ne, "\"%s\"", e) < 0)
ne = NULL;;
}

return ne;
}


/* Replaces slashes in name by "slash-", "-slash-" or "-slash", depending /* Replaces slashes in name by "slash-", "-slash-" or "-slash", depending
on the position of the slash within name. */ on the position of the slash within name. */
static void static void
@ -1694,20 +1693,7 @@ prop_result(void *userdata, const ne_uri *uri, const ne_prop_result_set *set)
} }


data = ne_propset_value(set, &prop_names[ETAG]); data = ne_propset_value(set, &prop_names[ETAG]);
if (data && *data == 'W') { result->etag = normalize_etag(data);
if (drop_weak_etags) {
data = NULL;
} else {
data += 2;
}
}
if (data) {
if (*data == '\"') {
result->etag = ne_strdup(data);
} else {
result->etag = ne_concat("\"", data, "\"", NULL);
}
}


data = ne_propset_value(set, &prop_names[LENGTH]); data = ne_propset_value(set, &prop_names[LENGTH]);
if (data) if (data)