From: Michael Wallner Date: Wed, 27 Apr 2005 13:37:05 +0000 (+0000) Subject: - separated http_check_method() from http_check_allowed_methods() X-Git-Tag: RELEASE_0_8_0~51 X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-http;a=commitdiff_plain;h=e434da0fad7db62d86c236c68b22150165f2647a - separated http_check_method() from http_check_allowed_methods() - message parser now recognizes nested messages if there's a content length header or chunked transfer encoding - added (still crashing) HttpMessage::getMessage() - some other fixes & adjustments --- diff --git a/http.c b/http.c index 6a28a5e..f574045 100644 --- a/http.c +++ b/http.c @@ -179,7 +179,7 @@ static inline void _http_globals_dtor(TSRMLS_D) efree(HTTP_G(ctype)); HTTP_G(ctype) = NULL; } - + #ifdef HTTP_HAVE_CURL # if LIBCURL_VERSION_NUM < 0x070c00 memset(&HTTP_G(curlerr), 0, sizeof(HTTP_G(curlerr))); @@ -193,21 +193,13 @@ static inline void _http_globals_dtor(TSRMLS_D) #define http_check_allowed_methods(m, l) _http_check_allowed_methods((m), (l) TSRMLS_CC) static inline void _http_check_allowed_methods(char *methods, int length TSRMLS_DC) { - char *found, *header; - - if (!length || !SG(request_info).request_method) { - return; + if (length && SG(request_info).request_method) { + if (SUCCESS != http_check_method(SG(request_info).request_method, methods)) { + char *header = emalloc(length + sizeof("Allow: ")); + sprintf(header, "Allow: %s", methods); + http_exit(405, header); + } } - - if ( (found = strstr(methods, SG(request_info).request_method)) && - (found == SG(request_info).request_method || !isalpha(found[-1])) && - (!isalpha(found[strlen(SG(request_info).request_method) + 1]))) { - return; - } - - header = emalloc(length + sizeof("Allow: ")); - sprintf(header, "Allow: %s", methods); - http_exit(405, header); } /* }}} */ diff --git a/http_api.c b/http_api.c index 5a0dd37..e76846c 100644 --- a/http_api.c +++ b/http_api.c @@ -101,6 +101,20 @@ STATUS _http_exit_ex(int status, char *header, zend_bool free_header TSRMLS_DC) } /* }}} */ +/* {{{ STATUS http_check_method(char *) */ +STATUS _http_check_method_ex(const char *method, const char *methods) +{ + const char *found; + + if ( (found = strstr(methods, method)) && + (found == method || !isalpha(found[-1])) && + (!isalpha(found[strlen(method) + 1]))) { + return SUCCESS; + } + return FAILURE; +} +/* }}} */ + /* {{{ zval *http_get_server_var_ex(char *, size_t) */ PHP_HTTP_API zval *_http_get_server_var_ex(const char *key, size_t key_size, zend_bool check TSRMLS_DC) { @@ -117,8 +131,8 @@ PHP_HTTP_API zval *_http_get_server_var_ex(const char *key, size_t key_size, zen /* }}} */ -/* {{{ STATUS http_chunked_decode(char *, size_t, char **, size_t *) */ -PHP_HTTP_API STATUS _http_chunked_decode(const char *encoded, size_t encoded_len, +/* {{{ char *http_chunked_decode(char *, size_t, char **, size_t *) */ +PHP_HTTP_API char *_http_chunked_decode(const char *encoded, size_t encoded_len, char **decoded, size_t *decoded_len TSRMLS_DC) { const char *e_ptr; @@ -139,7 +153,7 @@ PHP_HTTP_API STATUS _http_chunked_decode(const char *encoded, size_t encoded_len if (i == 9) { http_error_ex(E_WARNING, HTTP_E_PARSE, "Chunk size is too long: 0x%s...", hex_len); efree(*decoded); - return FAILURE; + return NULL; } hex_len[i++] = *e_ptr++; } @@ -151,9 +165,11 @@ PHP_HTTP_API STATUS _http_chunked_decode(const char *encoded, size_t encoded_len /* new line */ if (strncmp(e_ptr, HTTP_CRLF, 2)) { - http_error_ex(E_WARNING, HTTP_E_PARSE, "Invalid character (expected 0x0D 0x0A; got: %x %x)", *e_ptr, *(e_ptr + 1)); + http_error_ex(E_WARNING, HTTP_E_PARSE, + "Invalid character (expected 0x0D 0x0A; got: 0x%x(%c) 0x%x(%c))", + *e_ptr, *e_ptr, *(e_ptr + 1), *(e_ptr + 1)); efree(*decoded); - return FAILURE; + return NULL; } /* hex to long */ @@ -163,7 +179,7 @@ PHP_HTTP_API STATUS _http_chunked_decode(const char *encoded, size_t encoded_len if (error == hex_len) { http_error_ex(E_WARNING, HTTP_E_PARSE, "Invalid chunk size string: '%s'", hex_len); efree(*decoded); - return FAILURE; + return NULL; } } @@ -173,7 +189,7 @@ PHP_HTTP_API STATUS _http_chunked_decode(const char *encoded, size_t encoded_len *decoded_len += chunk_len; } - return SUCCESS; + return e_ptr; } /* }}} */ diff --git a/http_cache_api.c b/http_cache_api.c index 8d2b47f..c75b6dc 100644 --- a/http_cache_api.c +++ b/http_cache_api.c @@ -207,7 +207,7 @@ PHP_HTTP_API STATUS _http_cache_etag(const char *etag, size_t etag_len, if (!http_match_etag("HTTP_IF_NONE_MATCH", etag)) { return SUCCESS; } - return http_cache_exit_ex(etag, 1, 0); + return http_cache_exit_ex((char *)etag, 1, 0); } /* if no etag is given and we didn't already start ob_etaghandler -- start it */ diff --git a/http_functions.c b/http_functions.c index ffc84c3..5854e30 100644 --- a/http_functions.c +++ b/http_functions.c @@ -327,7 +327,7 @@ PHP_FUNCTION(http_match_etag) /* {{{ proto bool http_cache_last_modified([int timestamp_or_expires]]) * - * If timestamp_or_exires is greater than 0, it is handled as timestamp + * If timestamp_or_expires is greater than 0, it is handled as timestamp * and will be sent as date of last modification. If it is 0 or omitted, * the current time will be sent as Last-Modified date. If it's negative, * it is handled as expiration time in seconds, which means that if the @@ -491,7 +491,6 @@ PHP_FUNCTION(http_send_data) } convert_to_string_ex(&zdata); - http_send_header("Accept-Ranges: bytes"); RETURN_SUCCESS(http_send_data(Z_STRVAL_P(zdata), Z_STRLEN_P(zdata))); } /* }}} */ @@ -513,7 +512,6 @@ PHP_FUNCTION(http_send_file) RETURN_FALSE; } - http_send_header("Accept-Ranges: bytes"); RETURN_SUCCESS(http_send_file(file)); } /* }}} */ @@ -533,7 +531,6 @@ PHP_FUNCTION(http_send_stream) } php_stream_from_zval(file, &zstream); - http_send_header("Accept-Ranges: bytes"); RETURN_SUCCESS(http_send_stream(file)); } /* }}} */ diff --git a/http_message_api.c b/http_message_api.c index 04564af..76e1d22 100644 --- a/http_message_api.c +++ b/http_message_api.c @@ -23,10 +23,30 @@ #include "php_http.h" #include "php_http_std_defs.h" #include "php_http_message_api.h" +#include "php_http_api.h" #include "php_http_headers_api.h" #include "phpstr/phpstr.h" +#define http_message_parse_nested(msg, begin, length) _http_message_parse_nested((msg), (begin), (length) TSRMLS_CC) +static inline http_message *_http_message_parse_nested(http_message *msg, const char *begin, size_t length TSRMLS_DC) +{ + http_message *new; + + while (isspace(*begin)) { + ++begin; + if (!length--) { + return NULL; + } + } + + if (new = http_message_parse(begin, length)) { + new->nested = msg; + return new; + } + return NULL; +} + PHP_HTTP_API http_message *_http_message_init_ex(http_message *message, http_message_type type) { if (!message) { @@ -41,7 +61,7 @@ PHP_HTTP_API http_message *_http_message_init_ex(http_message *message, http_mes return message; } -PHP_HTTP_API http_message *_http_message_parse_ex(http_message *msg, char *message, size_t message_length, zend_bool dup TSRMLS_DC) +PHP_HTTP_API http_message *_http_message_parse_ex(http_message *msg, const char *message, size_t message_length TSRMLS_DC) { char *body = NULL; size_t header_length = 0; @@ -56,8 +76,6 @@ PHP_HTTP_API http_message *_http_message_parse_ex(http_message *msg, char *messa } msg = http_message_init(msg); - msg->len = message_length; - msg->raw = dup ? estrndup(message, message_length) : message; if (body = strstr(message, HTTP_CRLF HTTP_CRLF)) { body += lenof(HTTP_CRLF HTTP_CRLF); @@ -66,7 +84,7 @@ PHP_HTTP_API http_message *_http_message_parse_ex(http_message *msg, char *messa header_length = message_length; } - if (SUCCESS != http_parse_headers_cb(message, header_length, &msg->hdrs, 1, http_message_parse_headers_callback, (void **) &msg)) { + if (SUCCESS != http_parse_headers_cb((char *)message, header_length, &msg->hdrs, 1, http_message_parse_headers_callback, (void **) &msg)) { if (free_msg) { http_message_free(msg); } @@ -74,7 +92,32 @@ PHP_HTTP_API http_message *_http_message_parse_ex(http_message *msg, char *messa } if (body) { - phpstr_from_string_ex(PHPSTR(msg), body, message_length - header_length); + zval **c; + http_message *nested; + + if (SUCCESS == zend_hash_find(&msg->hdrs, "Content-Length", sizeof("Content-Length"), (void **) &c)) { + long len = atol(Z_STRVAL_PP(c)); + phpstr_from_string_ex(PHPSTR(msg), body, len); + if (nested = http_message_parse_nested(msg, body + len, message + message_length - body - len)) { + return nested; + } + } else if ( + SUCCESS == zend_hash_find(&msg->hdrs, "Transfer-Encoding", sizeof("Transfer-Encoding"), (void **) &c) && + !strcasecmp("chunked", Z_STRVAL_PP(c))) { + + char *decoded, *end; + size_t decoded_len; + + if (end = http_chunked_decode(body, message_length - header_length, &decoded, &decoded_len)) { + phpstr_from_string_ex(PHPSTR(msg), decoded, decoded_len); + efree(decoded); + if (nested = http_message_parse_nested(msg, end, message + message_length - end)) { + return nested; + } + } + } else { + phpstr_from_string_ex(PHPSTR(msg), body, message_length - header_length); + } } return msg; @@ -119,49 +162,52 @@ PHP_HTTP_API void _http_message_tostring(http_message *msg, char **string, size_ ulong idx; zval **header; - phpstr_init_ex(&str, msg->len, 1); - /* set sane alloc size */ - str.size = 4096; - - switch (msg->type) - { - case HTTP_MSG_REQUEST: - phpstr_appendf(&str, "%s %s HTTP/%1.1f" HTTP_CRLF, - msg->info.request.method, - msg->info.request.URI, - msg->info.request.http_version); - break; - - case HTTP_MSG_RESPONSE: - phpstr_appendf(&str, "HTTP/%1.1f %d" HTTP_CRLF, - msg->info.response.http_version, - msg->info.response.code); - break; - } + phpstr_init_ex(&str, 4096, 0); - FOREACH_HASH_KEYVAL(&msg->hdrs, key, idx, header) { - if (key) { - zval **single_header; - - switch (Z_TYPE_PP(header)) - { - case IS_STRING: - phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key, Z_STRVAL_PP(header)); - break; - - case IS_ARRAY: - FOREACH_VAL(*header, single_header) { - phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key, Z_STRVAL_PP(single_header)); - } - break; - } + do { + + switch (msg->type) + { + case HTTP_MSG_REQUEST: + phpstr_appendf(&str, "%s %s HTTP/%1.1f" HTTP_CRLF, + msg->info.request.method, + msg->info.request.URI, + msg->info.request.http_version); + break; - key = NULL; + case HTTP_MSG_RESPONSE: + phpstr_appendf(&str, "HTTP/%1.1f %d" HTTP_CRLF, + msg->info.response.http_version, + msg->info.response.code); + break; } - } - phpstr_appends(&str, HTTP_CRLF); - phpstr_append(&str, PHPSTR_VAL(msg), PHPSTR_LEN(msg)); + FOREACH_HASH_KEYVAL(&msg->hdrs, key, idx, header) { + if (key) { + zval **single_header; + + switch (Z_TYPE_PP(header)) + { + case IS_STRING: + phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key, Z_STRVAL_PP(header)); + break; + + case IS_ARRAY: + FOREACH_VAL(*header, single_header) { + phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key, Z_STRVAL_PP(single_header)); + } + break; + } + + key = NULL; + } + } + + phpstr_appends(&str, HTTP_CRLF); + phpstr_append(&str, PHPSTR_VAL(msg), PHPSTR_LEN(msg)); + phpstr_appends(&str, HTTP_CRLF); + + } while (msg = msg->nested); data = phpstr_data(&str, string, length); if (!string) { @@ -176,10 +222,6 @@ PHP_HTTP_API void _http_message_dtor(http_message *message) if (message) { zend_hash_destroy(&message->hdrs); phpstr_dtor(PHPSTR(message)); - if (message->raw) { - efree(message->raw); - message->raw = NULL; - } if (message->type == HTTP_MSG_REQUEST) { if (message->info.request.method) { efree(message->info.request.method); @@ -198,6 +240,7 @@ PHP_HTTP_API void _http_message_free(http_message *message) if (message) { if (message->nested) { http_message_free(message->nested); + message->nested = NULL; } http_message_dtor(message); efree(message); diff --git a/http_message_object.c b/http_message_object.c index fee935e..ffb3198 100644 --- a/http_message_object.c +++ b/http_message_object.c @@ -55,6 +55,7 @@ zend_function_entry http_message_object_fe[] = { PHP_ME(HttpMessage, setRequestUri, NULL, ZEND_ACC_PUBLIC) PHP_ME(HttpMessage, getHttpVersion, NULL, ZEND_ACC_PUBLIC) PHP_ME(HttpMessage, setHttpVersion, NULL, ZEND_ACC_PUBLIC) + PHP_ME(HttpMessage, getNestedMessage, NULL, ZEND_ACC_PUBLIC) PHP_ME(HttpMessage, toString, NULL, ZEND_ACC_PUBLIC) ZEND_MALIAS(HttpMessage, __toString, toString, NULL, ZEND_ACC_PUBLIC) @@ -106,7 +107,6 @@ static inline void _http_message_object_declare_default_properties(TSRMLS_D) DCL_PROP(PROTECTED, long, type, HTTP_MSG_NONE); - DCL_PROP(PROTECTED, string, raw, ""); DCL_PROP(PROTECTED, string, body, ""); DCL_PROP(PROTECTED, string, requestMethod, ""); @@ -144,7 +144,7 @@ static zval *_http_message_object_read_prop(zval *object, zval *member, int type return EG(uninitialized_zval_ptr); } - zval_dtor(return_value); + zval_ptr_dtor(&return_value); #if 0 fprintf(stderr, "Reading property: %s(%d==%d) (%lu)\n", Z_STRVAL_P(member), Z_STRLEN_P(member), strlen(Z_STRVAL_P(member)), @@ -175,18 +175,6 @@ static zval *_http_message_object_read_prop(zval *object, zval *member, int type } break; - case HTTP_MSG_PROPHASH_RAW: - if (msg->raw) { - if (msg->len) { - RETVAL_STRINGL(msg->raw, msg->len, 1); - } else { - RETVAL_STRINGL("", 0, 1); - } - } else { - RETVAL_NULL(); - } - break; - case HTTP_MSG_PROPHASH_BODY: phpstr_fix(PHPSTR(msg)); RETVAL_PHPSTR(PHPSTR(msg), 0, 1); @@ -198,7 +186,12 @@ static zval *_http_message_object_read_prop(zval *object, zval *member, int type break; case HTTP_MSG_PROPHASH_NESTED_MESSAGE: - RETVAL_NULL(); + if (msg->nested) { + Z_TYPE_P(return_value) = IS_OBJECT; + return_value->value.obj = http_message_object_from_msg(msg->nested); + } else { + RETVAL_NULL(); + } break; case HTTP_MSG_PROPHASH_REQUEST_METHOD: @@ -282,11 +275,6 @@ static void _http_message_object_write_prop(zval *object, zval *member, zval *va } break; - case HTTP_MSG_PROPHASH_RAW: - http_message_dtor(msg); - http_message_parse_ex(msg, Z_STRVAL_P(value), Z_STRLEN_P(value), 1); - break; - case HTTP_MSG_PROPHASH_BODY: phpstr_dtor(PHPSTR(msg)); phpstr_from_string_ex(PHPSTR(msg), Z_STRVAL_P(value), Z_STRLEN_P(value)); @@ -357,7 +345,6 @@ static HashTable *_http_message_object_get_props(zval *object TSRMLS_DC) zend_hash_clean(OBJ_PROP(obj)); ASSOC_PROP(obj, long, "type", msg->type); - ASSOC_STRINGL(obj, "raw", msg->raw, msg->len) ASSOC_STRINGL(obj, "body", PHPSTR_VAL(msg), PHPSTR_LEN(msg)); MAKE_STD_ZVAL(headers); diff --git a/http_methods.c b/http_methods.c index 49c57a4..dfbc712 100644 --- a/http_methods.c +++ b/http_methods.c @@ -875,7 +875,7 @@ PHP_METHOD(HttpMessage, setHttpVersion) zval *zv, *version; getObject(http_message_object, obj); - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zv)) { + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &zv)) { return; } @@ -890,6 +890,29 @@ PHP_METHOD(HttpMessage, setHttpVersion) } /* }}} */ +/* {{{ proto HttpMessage HttpMessage::getNestedMessage() + * + * Get nested HTTP Message. + */ +PHP_METHOD(HttpMessage, getNestedMessage) +{ + zval *nested; + getObject(http_message_object, obj); + + NO_ARGS; + + nested = GET_PROP(obj, nestedMessage); + if (Z_TYPE_P(nested) == IS_OBJECT) { + Z_TYPE_P(return_value) = IS_OBJECT; + return_value->is_ref = 1; + return_value->value.obj = nested->value.obj; + zval_add_ref(&return_value); + } else { + RETVAL_NULL(); + } +} +/* }}} */ + /* {{{ proto string HttpMessage::toString() * * Get the string representation of the Message. diff --git a/http_send_api.c b/http_send_api.c index 0fa18da..41ba305 100644 --- a/http_send_api.c +++ b/http_send_api.c @@ -330,6 +330,9 @@ PHP_HTTP_API STATUS _http_send(const void *data_ptr, size_t data_size, http_send HTTP_G(etag_started) = 0; } + /* enable partial dl and resume */ + http_send_header("Accept-Ranges: bytes"); + zend_hash_init(&ranges, 0, NULL, ZVAL_PTR_DTOR, 0); range_status = http_get_request_ranges(&ranges, data_size); @@ -362,14 +365,14 @@ PHP_HTTP_API STATUS _http_send(const void *data_ptr, size_t data_size, http_send return FAILURE; } if (http_match_etag("HTTP_IF_NONE_MATCH", etag)) { - return http_cache_exit(etag, 1, 1); + return http_cache_exit_ex(etag, 1, 1); } efree(etag); } /* send 304 Not Modified if last modified matches */ if (http_match_last_modified("HTTP_IF_MODIFIED_SINCE", HTTP_G(lmod))) { - return http_cache_exit(http_date(HTTP_G(lmod)), 0, 1); + return http_cache_exit_ex(http_date(HTTP_G(lmod)), 0, 1); } /* send full entity */ diff --git a/php_http_api.h b/php_http_api.h index 3e596ba..27e0bab 100644 --- a/php_http_api.h +++ b/php_http_api.h @@ -31,6 +31,10 @@ extern void _http_error_ex(long type, long code, const char *format, ...); #define http_exit_ex(s, h, f) _http_exit_ex((s), (h), (f) TSRMLS_CC) extern STATUS _http_exit_ex(int status, char *header, zend_bool free_header TSRMLS_DC); +#define http_check_method(m) http_check_method_ex((m), HTTP_KNOWN_METHODS) +#define http_check_method_ex(m, a) _http_check_method_ex((m), (a)) +extern STATUS _http_check_method(const char *method, const char *methods); + #define HTTP_GSC(var, name, ret) HTTP_GSP(var, name, return ret) #define HTTP_GSP(var, name, ret) \ if (!(var = _http_get_server_var_ex(name, strlen(name)+1, 1 TSRMLS_CC))) { \ @@ -42,7 +46,7 @@ extern STATUS _http_exit_ex(int status, char *header, zend_bool free_header TSRM PHP_HTTP_API zval *_http_get_server_var_ex(const char *key, size_t key_size, zend_bool check TSRMLS_DC); #define http_chunked_decode(e, el, d, dl) _http_chunked_decode((e), (el), (d), (dl) TSRMLS_CC) -PHP_HTTP_API STATUS _http_chunked_decode(const char *encoded, size_t encoded_len, char **decoded, size_t *decoded_len TSRMLS_DC); +PHP_HTTP_API char *_http_chunked_decode(const char *encoded, size_t encoded_len, char **decoded, size_t *decoded_len TSRMLS_DC); #define http_split_response(r, h, b) _http_split_response((r), (h), (b) TSRMLS_CC) PHP_HTTP_API STATUS _http_split_response(zval *response, zval *headers, zval *body TSRMLS_DC); diff --git a/php_http_message_api.h b/php_http_message_api.h index 78355a6..d60dc98 100644 --- a/php_http_message_api.h +++ b/php_http_message_api.h @@ -59,9 +59,6 @@ struct _http_message { } info; - size_t len; - char *raw; - http_message *nested; }; @@ -73,9 +70,9 @@ struct _http_message { #define http_message_init_ex(m, t) _http_message_init_ex((m), (t)) PHP_HTTP_API http_message *_http_message_init_ex(http_message *m, http_message_type t); -#define http_message_parse(m, l) http_message_parse_ex(NULL, (m), (l), 1) -#define http_message_parse_ex(h, m, l, d) _http_message_parse_ex((h), (m), (l), (d) TSRMLS_CC) -PHP_HTTP_API http_message *_http_message_parse_ex(http_message *msg, char *message, size_t length, zend_bool duplicate TSRMLS_DC); +#define http_message_parse(m, l) http_message_parse_ex(NULL, (m), (l)) +#define http_message_parse_ex(h, m, l) _http_message_parse_ex((h), (m), (l) TSRMLS_CC) +PHP_HTTP_API http_message *_http_message_parse_ex(http_message *msg, const char *message, size_t length TSRMLS_DC); #define http_message_parse_headers_callback _http_message_parse_headers_callback PHP_HTTP_API void _http_message_parse_headers_callback(void *message, char *http_line, size_t line_length, HashTable **headers TSRMLS_DC); diff --git a/php_http_message_object.h b/php_http_message_object.h index ba5a073..46a1dd5 100644 --- a/php_http_message_object.h +++ b/php_http_message_object.h @@ -67,9 +67,20 @@ PHP_METHOD(HttpMessage, getRequestUri); PHP_METHOD(HttpMessage, setRequestUri); PHP_METHOD(HttpMessage, getHttpVersion); PHP_METHOD(HttpMessage, setHttpVersion); +PHP_METHOD(HttpMessage, getNestedMessage); PHP_METHOD(HttpMessage, toString); PHP_METHOD(HttpMessage, fromString); #endif #endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ + diff --git a/php_http_std_defs.h b/php_http_std_defs.h index 59edb29..953d4ac 100644 --- a/php_http_std_defs.h +++ b/php_http_std_defs.h @@ -64,12 +64,12 @@ typedef int STATUS; /* HTTP 1.1 */ \ "GET, HEAD, POST, PUT, DELETE, OPTIONS, TRACE, CONNECT, " \ /* WebDAV - RFC 2518 */ \ - /* "PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK, " */ \ + "PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK, " \ /* WebDAV Versioning - RFC 3253 */ \ - /* "VERSION-CONTROL, REPORT, CHECKOUT, CHECKIN, UNCHECKOUT, " */ \ - /* "MKWORKSPACE, UPDATE, LABEL, MERGE, BASELINE-CONTROL, MKACTIVITY, " */ \ + "VERSION-CONTROL, REPORT, CHECKOUT, CHECKIN, UNCHECKOUT, " \ + "MKWORKSPACE, UPDATE, LABEL, MERGE, BASELINE-CONTROL, MKACTIVITY, " \ /* WebDAV Access Control - RFC 3744 */ \ - /* "ACL, " */ \ + "ACL, " \ /* END */