// -*- mode: c++; indent-tabs-mode: nil -*-

/*  WebDavHandler module Copyright 2019 - 2021 Qore Technologies, s.r.o.

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/


//! Main public WebDavHandler namespace
namespace WebDavHandler {
//! PROPPATCH action info
hashdecl PropPatchActionInfo {
    //! Action
    string action;
    //! Namespace
    string ns;
    //! Property
    string prop;
    //! Value
    auto val;
}

//! Abstract WebDavHandler interface class
class AbstractWebDavHandler : public HttpServer::AbstractHttpRequestHandler {

public:
        //! A hash of all supported WebDavHandler methods mapped to method names
        const RequestMethods = ...;


        //! A hash of methods that require a Destination header
        const DestMethods = ...;


        //! List of WebDavHandler methods in a string suitable for use in HTTP responses
        const AllowHeaderValue = RequestMethods.keys().join(",");

        //! List of WebDavHandler methods
        const MethodList = keys RequestMethods;

        //! PROPPATCH action: remove
        const PPA_Remove = "R";

        //! PROPPATCH action: set
        const PPA_Set = "S";

protected:
        //! The property handler object
        AbstractWebDavPropertyHandler property_handler;

        //! The virtual base path for resources served by the WebDavHandler handler
        string virtual_base_path;

        //! The Logger for this object
        Logger logger;

public:

    //! Creates the object with an empty logger and an in-memory property handler
/** @param auth the authentication object to use to authenticate connections
    */
    constructor(__7_ AbstractAuthenticator auth) ;


    //! Creates the object with the given argument and an in-memory property handler
/** @param auth the authentication object to use to authenticate connections
        @param virtual_relative_path_base the virtual base path for WebDavHandler requests; this path will be
        stripped from requests internally when serving WebDavHandler resources
    */
    constructor(__7_ AbstractAuthenticator auth, string virtual_relative_path_base) 
 ;


    //! Creates the object with the given arguments
/** @param auth the authentication object to use to authenticate connections
        @param property_handler to handle properties
        @param virtual_relative_path_base the virtual base path for WebDavHandler requests; this path will be
        stripped from requests internally when serving WebDavHandler resources
    */
constructor(__7_ AbstractAuthenticator auth, AbstractWebDavPropertyHandler property_handler, string virtual_relative_path_base = '/') ;


    //! Creates the object with the given arguments
/** @param auth the authentication object to use to authenticate connections
        @param logger the logger
        @param property_handler to handle properties
        @param virtual_relative_path_base the virtual base path for WebDavHandler requests; this path will be
        stripped from requests internally when serving WebDavHandler resources
    */
constructor(__7_ AbstractAuthenticator auth, Logger logger, AbstractWebDavPropertyHandler property_handler = new InMemoryWebDavPropertyHandler(), string virtual_relative_path_base = '/') ;


    //! Returnd a list of WebDavHandler methods
    list<string> getHttpMethods();


    //! Replace the logger
    setLogger(Logger logger);


    //! Handles HTTP/WebDavHandler requests and returns the response
hash<HttpResponseInfo> handleRequest(HttpListenerInterface listener, Socket s, hash<auto> cx, hash<auto> hdr, *data body);


    //! Returns a relative path from an absolute path
/** @param raw_path the rar path to process

        @return a relative path generated by stripping any virtual base path (set in the constructor) from the
        argument
    */
    string getRelativePath(string raw_path);


    //! Returns a hash that can be used as an HTTP response with the given HTTP response code and response message
    hash<HttpResponseInfo> response(int response_code = 200, data msg = 'OK');


    //! Returns a hash that can be used as an HTTP response with the given HTTP response code and response headers
    hash<HttpResponseInfo> response(int response_code = 200, hash<auto> hdr);


    //! Returns a hash that can be used as an HTTP response with a 400 response code and response message
    hash<HttpResponseInfo> resp400(data msg = 'Bad Request');


    //! Returns a hash that can be used as an HTTP response with a 404 response code and response message
    hash<HttpResponseInfo> resp404();


    //! Returns a hash that can be used as an HTTP response with a 500 response code and response message
    hash<HttpResponseInfo> resp500(data msg = 'General Server Error');


    //! Returns a hash that can be used as an HTTP response with a 501 response code and response message
    hash<HttpResponseInfo> resp501();


    //! Common constructor code
protected:
 init(Logger logger, AbstractWebDavPropertyHandler property_handler, string virtual_relative_path_base = '/');
public:


    //! Converts a request path to a normalized real path on the filesystem in the root WebDavHandler directory
/** @throw WEBDAVHANDLER-FORBIDDEN if the path is not valid
    */
protected:
     string getRealPath(string raw_path);
public:


    //! Checks if the request is authorized; if not, this method must return a value
/** Override this in a subclass to implement authorization controls
    */
protected:
     __7_ hash<HttpResponseInfo> checkAuth(string method, hash<auto> cx, hash<auto> hdr, __7_ data body);
public:


    //! Copies all properties from the given source URL to the target URL
protected:
     copyProperties(string source_url, string target_url);
public:


    //! Moves all properties from the given source URL to the target URL
protected:
     moveProperties(string source_url, string target_url);
public:


    //! Deletes all properties from the given URL
protected:
     deleteProperties(string source_url);
public:


    //! Returns a hash that can be serialized to an XML string for a PROPFIND request
protected:
 hash<auto> preparePropFindXmlResponse(string local_path, string href, bool is_collection, hash<auto> base_props, bool all_props = False, *hash<string, hash<string, bool>> additional_props);
public:


protected:
     hash<auto> propStatXmlHash(string href, __7_ hash<auto> code_map);
public:


    //! Returns a status message for the given HTTP response code
/** @throw RESPONSE-ERROR the code is unknown
    */
protected:
     string getStatusMessage(softstring http_code);
public:


    //! Handles a WebDavHandler OPTIONS request
/**  @param cx call context hash; this hash will have the following keys:
        - \c header-info: a hash of information about the request header with the following keys:
          - \c accept-charset: this key will be set to an appropriate value from any \c "Accept-Charset" header; if
            any of \c "*", \c "utf8", or \c "utf-8" are present, then this will be set to \c "utf8", otherwise it will
            be set to the first requested character encoding in the list
          - \c accept-encoding: a hash where keys are values from any \c "Accept-Encoding" header and the values are
            @ref True
          - \c body-content-type: this is the \c "Content-Type" header without any charset declaration
          - \c charset: if there is a charset declaration in the \c "Content-Type" header, the value is returned in
            this key
          - \c client-cert: if the server is configured to capture remote client certificates, and the client supplied
            a certificate, this key will be populated with the @ref Qore::SSLCertificate "SSLCertificate" for the client
          - \c close: set to @ref True "True" if the connection should be closed after responding,
            @ref False "False" if not (as derived from the request header)
          - \c headers-raw: a hash of raw request headers without any case conversions or other processing
          - \c request-uri: gives the request URI in an HTTP request
        - \c socket: the bind address used to bind the listener (\c "socket-info" provides more detailed information)
        - \c socket-info: a hash of socket information for the listening socket (as returned by
          @ref Qore::Socket::getSocketInfo())
        - \c peer-info: a hash of socket information for the remote socket (as returned by @ref Qore::Socket::getPeerInfo())
        - \c url: a hash of broken-down URL information (as returned from @ref Qore::parse_url())
        - \c id: the unique HTTP connection ID
        - \c ssl: @ref True "True" if the request was encrypted with HTTPS, @ref False "False" if not
        - \c listener-id: the HTTP server listener ID (see HttpServer::getListenerInfo())
        - \c user: the current RBAC username (if any)
        - \c root_path: the root URL path matched if the request was matched by a URL prefix
        @param hdr incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
        - \c method: the HTTP method received (ie \c "GET", \c "POST", etc)
        - \c path: the HTTP path given in the request, after processing by @ref Qore::decode_uri_request()
        - \c http_version: the HTTP version number in the request (either \c "1.0" or \c "1.1")
        @param body message body, if any

        @return a 200 response with headers indicating WebDavHandler support

        @note this base class method calls handleOptionsImpl() to process the request
    */
    hash<HttpResponseInfo> handleOptions(Socket s, hash<auto> cx, hash<auto> hdr, __7_ data body);


    //! Handles HTTP GET requests for WebDavHandler resources
/**  @param cx call context hash; this hash will have the following keys:
        - \c header-info: a hash of information about the request header with the following keys:
          - \c accept-charset: this key will be set to an appropriate value from any \c "Accept-Charset" header; if
            any of \c "*", \c "utf8", or \c "utf-8" are present, then this will be set to \c "utf8", otherwise it will
            be set to the first requested character encoding in the list
          - \c accept-encoding: a hash where keys are values from any \c "Accept-Encoding" header and the values are
            @ref True
          - \c body-content-type: this is the \c "Content-Type" header without any charset declaration
          - \c charset: if there is a charset declaration in the \c "Content-Type" header, the value is returned in
            this key
          - \c client-cert: if the server is configured to capture remote client certificates, and the client supplied
            a certificate, this key will be populated with the @ref Qore::SSLCertificate "SSLCertificate" for the client
          - \c close: set to @ref True "True" if the connection should be closed after responding,
            @ref False "False" if not (as derived from the request header)
          - \c headers-raw: a hash of raw request headers without any case conversions or other processing
          - \c request-uri: gives the request URI in an HTTP request
        - \c socket: the bind address used to bind the listener (\c "socket-info" provides more detailed information)
        - \c socket-info: a hash of socket information for the listening socket (as returned by
          @ref Qore::Socket::getSocketInfo())
        - \c peer-info: a hash of socket information for the remote socket (as returned by @ref Qore::Socket::getPeerInfo())
        - \c url: a hash of broken-down URL information (as returned from @ref Qore::parse_url())
        - \c id: the unique HTTP connection ID
        - \c ssl: @ref True "True" if the request was encrypted with HTTPS, @ref False "False" if not
        - \c listener-id: the HTTP server listener ID (see HttpServer::getListenerInfo())
        - \c user: the current RBAC username (if any)
        - \c root_path: the root URL path matched if the request was matched by a URL prefix
        @param hdr incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
        - \c method: the HTTP method received (ie \c "GET", \c "POST", etc)
        - \c path: the HTTP path given in the request, after processing by @ref Qore::decode_uri_request()
        - \c http_version: the HTTP version number in the request (either \c "1.0" or \c "1.1")
        @param body message body, if any

        @return the response to the HTTP request

        @note this base class method calls handleGetImpl() to process the request
    */
    hash<HttpResponseInfo> handleGet(Socket s, hash<auto> cx, hash<auto> hdr, __7_ data body);


    //! Handles HTTP HEAD requests for WebDavHandler resources
/**  @param cx call context hash; this hash will have the following keys:
        - \c header-info: a hash of information about the request header with the following keys:
          - \c accept-charset: this key will be set to an appropriate value from any \c "Accept-Charset" header; if
            any of \c "*", \c "utf8", or \c "utf-8" are present, then this will be set to \c "utf8", otherwise it will
            be set to the first requested character encoding in the list
          - \c accept-encoding: a hash where keys are values from any \c "Accept-Encoding" header and the values are
            @ref True
          - \c body-content-type: this is the \c "Content-Type" header without any charset declaration
          - \c charset: if there is a charset declaration in the \c "Content-Type" header, the value is returned in
            this key
          - \c client-cert: if the server is configured to capture remote client certificates, and the client supplied
            a certificate, this key will be populated with the @ref Qore::SSLCertificate "SSLCertificate" for the client
          - \c close: set to @ref True "True" if the connection should be closed after responding,
            @ref False "False" if not (as derived from the request header)
          - \c headers-raw: a hash of raw request headers without any case conversions or other processing
          - \c request-uri: gives the request URI in an HTTP request
        - \c socket: the bind address used to bind the listener (\c "socket-info" provides more detailed information)
        - \c socket-info: a hash of socket information for the listening socket (as returned by
          @ref Qore::Socket::getSocketInfo())
        - \c peer-info: a hash of socket information for the remote socket (as returned by @ref Qore::Socket::getPeerInfo())
        - \c url: a hash of broken-down URL information (as returned from @ref Qore::parse_url())
        - \c id: the unique HTTP connection ID
        - \c ssl: @ref True "True" if the request was encrypted with HTTPS, @ref False "False" if not
        - \c listener-id: the HTTP server listener ID (see HttpServer::getListenerInfo())
        - \c user: the current RBAC username (if any)
        - \c root_path: the root URL path matched if the request was matched by a URL prefix
        @param hdr incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
        - \c method: the HTTP method received (ie \c "GET", \c "POST", etc)
        - \c path: the HTTP path given in the request, after processing by @ref Qore::decode_uri_request()
        - \c http_version: the HTTP version number in the request (either \c "1.0" or \c "1.1")
        @param body message body, if any

        @return the response to the HTTP request

        @note this base class method calls handleHeadImpl() to process the request
    */
    hash<HttpResponseInfo> handleHead(Socket s, hash<auto> cx, hash<auto> hdr, __7_ data body);


    //! Handles HTTP POST requests for WebDavHandler resources
/**  @param cx call context hash; this hash will have the following keys:
        - \c header-info: a hash of information about the request header with the following keys:
          - \c accept-charset: this key will be set to an appropriate value from any \c "Accept-Charset" header; if
            any of \c "*", \c "utf8", or \c "utf-8" are present, then this will be set to \c "utf8", otherwise it will
            be set to the first requested character encoding in the list
          - \c accept-encoding: a hash where keys are values from any \c "Accept-Encoding" header and the values are
            @ref True
          - \c body-content-type: this is the \c "Content-Type" header without any charset declaration
          - \c charset: if there is a charset declaration in the \c "Content-Type" header, the value is returned in
            this key
          - \c client-cert: if the server is configured to capture remote client certificates, and the client supplied
            a certificate, this key will be populated with the @ref Qore::SSLCertificate "SSLCertificate" for the client
          - \c close: set to @ref True "True" if the connection should be closed after responding,
            @ref False "False" if not (as derived from the request header)
          - \c headers-raw: a hash of raw request headers without any case conversions or other processing
          - \c request-uri: gives the request URI in an HTTP request
        - \c socket: the bind address used to bind the listener (\c "socket-info" provides more detailed information)
        - \c socket-info: a hash of socket information for the listening socket (as returned by
          @ref Qore::Socket::getSocketInfo())
        - \c peer-info: a hash of socket information for the remote socket (as returned by @ref Qore::Socket::getPeerInfo())
        - \c url: a hash of broken-down URL information (as returned from @ref Qore::parse_url())
        - \c id: the unique HTTP connection ID
        - \c ssl: @ref True "True" if the request was encrypted with HTTPS, @ref False "False" if not
        - \c listener-id: the HTTP server listener ID (see HttpServer::getListenerInfo())
        - \c user: the current RBAC username (if any)
        - \c root_path: the root URL path matched if the request was matched by a URL prefix
        @param hdr incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
        - \c method: the HTTP method received (ie \c "GET", \c "POST", etc)
        - \c path: the HTTP path given in the request, after processing by @ref Qore::decode_uri_request()
        - \c http_version: the HTTP version number in the request (either \c "1.0" or \c "1.1")
        @param body message body, if any

        @return the response to the HTTP request

        @note this base class method calls handlePostImpl() to process the request
    */
    hash<HttpResponseInfo> handlePost(Socket s, hash<auto> cx, hash<auto> hdr, __7_ data body);


    //! Handles HTTP PUT requests for WebDavHandler resources
/**  @param cx call context hash; this hash will have the following keys:
        - \c header-info: a hash of information about the request header with the following keys:
          - \c accept-charset: this key will be set to an appropriate value from any \c "Accept-Charset" header; if
            any of \c "*", \c "utf8", or \c "utf-8" are present, then this will be set to \c "utf8", otherwise it will
            be set to the first requested character encoding in the list
          - \c accept-encoding: a hash where keys are values from any \c "Accept-Encoding" header and the values are
            @ref True
          - \c body-content-type: this is the \c "Content-Type" header without any charset declaration
          - \c charset: if there is a charset declaration in the \c "Content-Type" header, the value is returned in
            this key
          - \c client-cert: if the server is configured to capture remote client certificates, and the client supplied
            a certificate, this key will be populated with the @ref Qore::SSLCertificate "SSLCertificate" for the client
          - \c close: set to @ref True "True" if the connection should be closed after responding,
            @ref False "False" if not (as derived from the request header)
          - \c headers-raw: a hash of raw request headers without any case conversions or other processing
          - \c request-uri: gives the request URI in an HTTP request
        - \c socket: the bind address used to bind the listener (\c "socket-info" provides more detailed information)
        - \c socket-info: a hash of socket information for the listening socket (as returned by
          @ref Qore::Socket::getSocketInfo())
        - \c peer-info: a hash of socket information for the remote socket (as returned by @ref Qore::Socket::getPeerInfo())
        - \c url: a hash of broken-down URL information (as returned from @ref Qore::parse_url())
        - \c id: the unique HTTP connection ID
        - \c ssl: @ref True "True" if the request was encrypted with HTTPS, @ref False "False" if not
        - \c listener-id: the HTTP server listener ID (see HttpServer::getListenerInfo())
        - \c user: the current RBAC username (if any)
        - \c root_path: the root URL path matched if the request was matched by a URL prefix
        @param hdr incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
        - \c method: the HTTP method received (ie \c "GET", \c "POST", etc)
        - \c path: the HTTP path given in the request, after processing by @ref Qore::decode_uri_request()
        - \c http_version: the HTTP version number in the request (either \c "1.0" or \c "1.1")
        @param body message body, if any

        @return the response to the HTTP request

        @note this base class method calls handlePutImpl() to process the request
    */
    hash<HttpResponseInfo> handlePut(Socket s, hash<auto> cx, hash<auto> hdr, __7_ data body);


    //! Handles HTTP DELETE requests for WebDavHandler resources
/**  @param cx call context hash; this hash will have the following keys:
        - \c header-info: a hash of information about the request header with the following keys:
          - \c accept-charset: this key will be set to an appropriate value from any \c "Accept-Charset" header; if
            any of \c "*", \c "utf8", or \c "utf-8" are present, then this will be set to \c "utf8", otherwise it will
            be set to the first requested character encoding in the list
          - \c accept-encoding: a hash where keys are values from any \c "Accept-Encoding" header and the values are
            @ref True
          - \c body-content-type: this is the \c "Content-Type" header without any charset declaration
          - \c charset: if there is a charset declaration in the \c "Content-Type" header, the value is returned in
            this key
          - \c client-cert: if the server is configured to capture remote client certificates, and the client supplied
            a certificate, this key will be populated with the @ref Qore::SSLCertificate "SSLCertificate" for the client
          - \c close: set to @ref True "True" if the connection should be closed after responding,
            @ref False "False" if not (as derived from the request header)
          - \c headers-raw: a hash of raw request headers without any case conversions or other processing
          - \c request-uri: gives the request URI in an HTTP request
        - \c socket: the bind address used to bind the listener (\c "socket-info" provides more detailed information)
        - \c socket-info: a hash of socket information for the listening socket (as returned by
          @ref Qore::Socket::getSocketInfo())
        - \c peer-info: a hash of socket information for the remote socket (as returned by @ref Qore::Socket::getPeerInfo())
        - \c url: a hash of broken-down URL information (as returned from @ref Qore::parse_url())
        - \c id: the unique HTTP connection ID
        - \c ssl: @ref True "True" if the request was encrypted with HTTPS, @ref False "False" if not
        - \c listener-id: the HTTP server listener ID (see HttpServer::getListenerInfo())
        - \c user: the current RBAC username (if any)
        - \c root_path: the root URL path matched if the request was matched by a URL prefix
        @param hdr incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
        - \c method: the HTTP method received (ie \c "GET", \c "POST", etc)
        - \c path: the HTTP path given in the request, after processing by @ref Qore::decode_uri_request()
        - \c http_version: the HTTP version number in the request (either \c "1.0" or \c "1.1")
        @param body message body, if any

        @return the response to the HTTP request

        @note this base class method calls handleDeleteImpl() to process the request
    */
    hash<HttpResponseInfo> handleDelete(Socket s, hash<auto> cx, hash<auto> hdr, __7_ data body);


    //! Handles WebDavHandler COPY requests for WebDavHandler resources
/**  @param cx call context hash; this hash will have the following keys:
        - \c header-info: a hash of information about the request header with the following keys:
          - \c accept-charset: this key will be set to an appropriate value from any \c "Accept-Charset" header; if
            any of \c "*", \c "utf8", or \c "utf-8" are present, then this will be set to \c "utf8", otherwise it will
            be set to the first requested character encoding in the list
          - \c accept-encoding: a hash where keys are values from any \c "Accept-Encoding" header and the values are
            @ref True
          - \c body-content-type: this is the \c "Content-Type" header without any charset declaration
          - \c charset: if there is a charset declaration in the \c "Content-Type" header, the value is returned in
            this key
          - \c client-cert: if the server is configured to capture remote client certificates, and the client supplied
            a certificate, this key will be populated with the @ref Qore::SSLCertificate "SSLCertificate" for the client
          - \c close: set to @ref True "True" if the connection should be closed after responding,
            @ref False "False" if not (as derived from the request header)
          - \c headers-raw: a hash of raw request headers without any case conversions or other processing
          - \c request-uri: gives the request URI in an HTTP request
        - \c socket: the bind address used to bind the listener (\c "socket-info" provides more detailed information)
        - \c socket-info: a hash of socket information for the listening socket (as returned by
          @ref Qore::Socket::getSocketInfo())
        - \c peer-info: a hash of socket information for the remote socket (as returned by @ref Qore::Socket::getPeerInfo())
        - \c url: a hash of broken-down URL information (as returned from @ref Qore::parse_url())
        - \c id: the unique HTTP connection ID
        - \c ssl: @ref True "True" if the request was encrypted with HTTPS, @ref False "False" if not
        - \c listener-id: the HTTP server listener ID (see HttpServer::getListenerInfo())
        - \c user: the current RBAC username (if any)
        - \c root_path: the root URL path matched if the request was matched by a URL prefix
        @param hdr incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
        - \c method: the HTTP method received (ie \c "GET", \c "POST", etc)
        - \c path: the HTTP path given in the request, after processing by @ref Qore::decode_uri_request()
        - \c http_version: the HTTP version number in the request (either \c "1.0" or \c "1.1")
        @param body message body, if any

        @return the response to the WebDavHandler request

        @note this base class method calls handleCopyImpl() to process the request
    */
    hash<HttpResponseInfo> handleCopy(Socket s, hash<auto> cx, hash<auto> hdr, __7_ data body);


    //! Handles WebDavHandler MOVE requests for WebDavHandler resources
/**  @param cx call context hash; this hash will have the following keys:
        - \c header-info: a hash of information about the request header with the following keys:
          - \c accept-charset: this key will be set to an appropriate value from any \c "Accept-Charset" header; if
            any of \c "*", \c "utf8", or \c "utf-8" are present, then this will be set to \c "utf8", otherwise it will
            be set to the first requested character encoding in the list
          - \c accept-encoding: a hash where keys are values from any \c "Accept-Encoding" header and the values are
            @ref True
          - \c body-content-type: this is the \c "Content-Type" header without any charset declaration
          - \c charset: if there is a charset declaration in the \c "Content-Type" header, the value is returned in
            this key
          - \c client-cert: if the server is configured to capture remote client certificates, and the client supplied
            a certificate, this key will be populated with the @ref Qore::SSLCertificate "SSLCertificate" for the client
          - \c close: set to @ref True "True" if the connection should be closed after responding,
            @ref False "False" if not (as derived from the request header)
          - \c headers-raw: a hash of raw request headers without any case conversions or other processing
          - \c request-uri: gives the request URI in an HTTP request
        - \c socket: the bind address used to bind the listener (\c "socket-info" provides more detailed information)
        - \c socket-info: a hash of socket information for the listening socket (as returned by
          @ref Qore::Socket::getSocketInfo())
        - \c peer-info: a hash of socket information for the remote socket (as returned by @ref Qore::Socket::getPeerInfo())
        - \c url: a hash of broken-down URL information (as returned from @ref Qore::parse_url())
        - \c id: the unique HTTP connection ID
        - \c ssl: @ref True "True" if the request was encrypted with HTTPS, @ref False "False" if not
        - \c listener-id: the HTTP server listener ID (see HttpServer::getListenerInfo())
        - \c user: the current RBAC username (if any)
        - \c root_path: the root URL path matched if the request was matched by a URL prefix
        @param hdr incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
        - \c method: the HTTP method received (ie \c "GET", \c "POST", etc)
        - \c path: the HTTP path given in the request, after processing by @ref Qore::decode_uri_request()
        - \c http_version: the HTTP version number in the request (either \c "1.0" or \c "1.1")
        @param body message body, if any

        @return the response to the WebDavHandler request

        @note this base class method calls handleMoveImpl() to process the request
    */
    hash<HttpResponseInfo> handleMove(Socket s, hash<auto> cx, hash<auto> hdr, __7_ data body);


    //! Handles WebDavHandler LOCK requests for WebDavHandler resources
/**  @param cx call context hash; this hash will have the following keys:
        - \c header-info: a hash of information about the request header with the following keys:
          - \c accept-charset: this key will be set to an appropriate value from any \c "Accept-Charset" header; if
            any of \c "*", \c "utf8", or \c "utf-8" are present, then this will be set to \c "utf8", otherwise it will
            be set to the first requested character encoding in the list
          - \c accept-encoding: a hash where keys are values from any \c "Accept-Encoding" header and the values are
            @ref True
          - \c body-content-type: this is the \c "Content-Type" header without any charset declaration
          - \c charset: if there is a charset declaration in the \c "Content-Type" header, the value is returned in
            this key
          - \c client-cert: if the server is configured to capture remote client certificates, and the client supplied
            a certificate, this key will be populated with the @ref Qore::SSLCertificate "SSLCertificate" for the client
          - \c close: set to @ref True "True" if the connection should be closed after responding,
            @ref False "False" if not (as derived from the request header)
          - \c headers-raw: a hash of raw request headers without any case conversions or other processing
          - \c request-uri: gives the request URI in an HTTP request
        - \c socket: the bind address used to bind the listener (\c "socket-info" provides more detailed information)
        - \c socket-info: a hash of socket information for the listening socket (as returned by
          @ref Qore::Socket::getSocketInfo())
        - \c peer-info: a hash of socket information for the remote socket (as returned by @ref Qore::Socket::getPeerInfo())
        - \c url: a hash of broken-down URL information (as returned from @ref Qore::parse_url())
        - \c id: the unique HTTP connection ID
        - \c ssl: @ref True "True" if the request was encrypted with HTTPS, @ref False "False" if not
        - \c listener-id: the HTTP server listener ID (see HttpServer::getListenerInfo())
        - \c user: the current RBAC username (if any)
        - \c root_path: the root URL path matched if the request was matched by a URL prefix
        @param hdr incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
        - \c method: the HTTP method received (ie \c "GET", \c "POST", etc)
        - \c path: the HTTP path given in the request, after processing by @ref Qore::decode_uri_request()
        - \c http_version: the HTTP version number in the request (either \c "1.0" or \c "1.1")
        @param body message body, if any

        @return the response to the WebDavHandler request

        @note this base class method calls handleLockImpl() to process the request
    */
    hash<HttpResponseInfo> handleLock(Socket s, hash<auto> cx, hash<auto> hdr, __7_ data body);


    //! Handles WebDavHandler UNLOCK requests for WebDavHandler resources
/**  @param cx call context hash; this hash will have the following keys:
        - \c header-info: a hash of information about the request header with the following keys:
          - \c accept-charset: this key will be set to an appropriate value from any \c "Accept-Charset" header; if
            any of \c "*", \c "utf8", or \c "utf-8" are present, then this will be set to \c "utf8", otherwise it will
            be set to the first requested character encoding in the list
          - \c accept-encoding: a hash where keys are values from any \c "Accept-Encoding" header and the values are
            @ref True
          - \c body-content-type: this is the \c "Content-Type" header without any charset declaration
          - \c charset: if there is a charset declaration in the \c "Content-Type" header, the value is returned in
            this key
          - \c client-cert: if the server is configured to capture remote client certificates, and the client supplied
            a certificate, this key will be populated with the @ref Qore::SSLCertificate "SSLCertificate" for the client
          - \c close: set to @ref True "True" if the connection should be closed after responding,
            @ref False "False" if not (as derived from the request header)
          - \c headers-raw: a hash of raw request headers without any case conversions or other processing
          - \c request-uri: gives the request URI in an HTTP request
        - \c socket: the bind address used to bind the listener (\c "socket-info" provides more detailed information)
        - \c socket-info: a hash of socket information for the listening socket (as returned by
          @ref Qore::Socket::getSocketInfo())
        - \c peer-info: a hash of socket information for the remote socket (as returned by @ref Qore::Socket::getPeerInfo())
        - \c url: a hash of broken-down URL information (as returned from @ref Qore::parse_url())
        - \c id: the unique HTTP connection ID
        - \c ssl: @ref True "True" if the request was encrypted with HTTPS, @ref False "False" if not
        - \c listener-id: the HTTP server listener ID (see HttpServer::getListenerInfo())
        - \c user: the current RBAC username (if any)
        - \c root_path: the root URL path matched if the request was matched by a URL prefix
        @param hdr incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
        - \c method: the HTTP method received (ie \c "GET", \c "POST", etc)
        - \c path: the HTTP path given in the request, after processing by @ref Qore::decode_uri_request()
        - \c http_version: the HTTP version number in the request (either \c "1.0" or \c "1.1")
        @param body message body, if any

        @return the response to the WebDavHandler request

        @note this base class method calls handleUnlockImpl() to process the request
    */
    hash<HttpResponseInfo> handleUnlock(Socket s, hash<auto> cx, hash<auto> hdr, __7_ data body);


    //! Handles WebDavHandler MKCOL requests for WebDavHandler resources
/**  @param cx call context hash; this hash will have the following keys:
        - \c header-info: a hash of information about the request header with the following keys:
          - \c accept-charset: this key will be set to an appropriate value from any \c "Accept-Charset" header; if
            any of \c "*", \c "utf8", or \c "utf-8" are present, then this will be set to \c "utf8", otherwise it will
            be set to the first requested character encoding in the list
          - \c accept-encoding: a hash where keys are values from any \c "Accept-Encoding" header and the values are
            @ref True
          - \c body-content-type: this is the \c "Content-Type" header without any charset declaration
          - \c charset: if there is a charset declaration in the \c "Content-Type" header, the value is returned in
            this key
          - \c client-cert: if the server is configured to capture remote client certificates, and the client supplied
            a certificate, this key will be populated with the @ref Qore::SSLCertificate "SSLCertificate" for the client
          - \c close: set to @ref True "True" if the connection should be closed after responding,
            @ref False "False" if not (as derived from the request header)
          - \c headers-raw: a hash of raw request headers without any case conversions or other processing
          - \c request-uri: gives the request URI in an HTTP request
        - \c socket: the bind address used to bind the listener (\c "socket-info" provides more detailed information)
        - \c socket-info: a hash of socket information for the listening socket (as returned by
          @ref Qore::Socket::getSocketInfo())
        - \c peer-info: a hash of socket information for the remote socket (as returned by @ref Qore::Socket::getPeerInfo())
        - \c url: a hash of broken-down URL information (as returned from @ref Qore::parse_url())
        - \c id: the unique HTTP connection ID
        - \c ssl: @ref True "True" if the request was encrypted with HTTPS, @ref False "False" if not
        - \c listener-id: the HTTP server listener ID (see HttpServer::getListenerInfo())
        - \c user: the current RBAC username (if any)
        - \c root_path: the root URL path matched if the request was matched by a URL prefix
        @param hdr incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
        - \c method: the HTTP method received (ie \c "GET", \c "POST", etc)
        - \c path: the HTTP path given in the request, after processing by @ref Qore::decode_uri_request()
        - \c http_version: the HTTP version number in the request (either \c "1.0" or \c "1.1")
        @param body message body, if any

        @return the response to the WebDavHandler request

        @note this base class method calls handleMkcolImpl() to process the request
    */
    hash<HttpResponseInfo> handleMkcol(Socket s, hash<auto> cx, hash<auto> hdr, __7_ data body);


    //! Handles WebDavHandler PROPFIND requests for WebDavHandler resources; reetrieves properties from WebDavHandler resources
/**
        @param cx call context hash; this hash will have the following keys:
        - \c header-info: a hash of information about the request header with the following keys:
          - \c accept-charset: this key will be set to an appropriate value from any \c "Accept-Charset" header; if
            any of \c "*", \c "utf8", or \c "utf-8" are present, then this will be set to \c "utf8", otherwise it will
            be set to the first requested character encoding in the list
          - \c accept-encoding: a hash where keys are values from any \c "Accept-Encoding" header and the values are
            @ref True
          - \c body-content-type: this is the \c "Content-Type" header without any charset declaration
          - \c charset: if there is a charset declaration in the \c "Content-Type" header, the value is returned in
            this key
          - \c client-cert: if the server is configured to capture remote client certificates, and the client supplied
            a certificate, this key will be populated with the @ref Qore::SSLCertificate "SSLCertificate" for the client
          - \c close: set to @ref True "True" if the connection should be closed after responding,
            @ref False "False" if not (as derived from the request header)
          - \c headers-raw: a hash of raw request headers without any case conversions or other processing
          - \c request-uri: gives the request URI in an HTTP request
        - \c socket: the bind address used to bind the listener (\c "socket-info" provides more detailed information)
        - \c socket-info: a hash of socket information for the listening socket (as returned by
          @ref Qore::Socket::getSocketInfo())
        - \c peer-info: a hash of socket information for the remote socket (as returned by @ref Qore::Socket::getPeerInfo())
        - \c url: a hash of broken-down URL information (as returned from @ref Qore::parse_url())
        - \c id: the unique HTTP connection ID
        - \c ssl: @ref True "True" if the request was encrypted with HTTPS, @ref False "False" if not
        - \c listener-id: the HTTP server listener ID (see HttpServer::getListenerInfo())
        - \c user: the current RBAC username (if any)
        - \c root_path: the root URL path matched if the request was matched by a URL prefix
        @param hdr incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
        - \c method: the HTTP method received (ie \c "GET", \c "POST", etc)
        - \c path: the HTTP path given in the request, after processing by @ref Qore::decode_uri_request()
        - \c http_version: the HTTP version number in the request (either \c "1.0" or \c "1.1")
        @param body message body, if any

        @return the response to the WebDavHandler request

        @note this base class method calls handlePropfindImpl() to process the request
    */
    hash<HttpResponseInfo> handlePropfind(Socket s, hash<auto> cx, hash<auto> hdr, __7_ data body);


    //! Handles WebDavHandler PROPPATCH requests for WebDavHandler resources; sets or removes properties on WebDavHandler resources
/**
        @param cx call context hash; this hash will have the following keys:
        - \c header-info: a hash of information about the request header with the following keys:
          - \c accept-charset: this key will be set to an appropriate value from any \c "Accept-Charset" header; if
            any of \c "*", \c "utf8", or \c "utf-8" are present, then this will be set to \c "utf8", otherwise it will
            be set to the first requested character encoding in the list
          - \c accept-encoding: a hash where keys are values from any \c "Accept-Encoding" header and the values are
            @ref True
          - \c body-content-type: this is the \c "Content-Type" header without any charset declaration
          - \c charset: if there is a charset declaration in the \c "Content-Type" header, the value is returned in
            this key
          - \c client-cert: if the server is configured to capture remote client certificates, and the client supplied
            a certificate, this key will be populated with the @ref Qore::SSLCertificate "SSLCertificate" for the client
          - \c close: set to @ref True "True" if the connection should be closed after responding,
            @ref False "False" if not (as derived from the request header)
          - \c headers-raw: a hash of raw request headers without any case conversions or other processing
          - \c request-uri: gives the request URI in an HTTP request
        - \c socket: the bind address used to bind the listener (\c "socket-info" provides more detailed information)
        - \c socket-info: a hash of socket information for the listening socket (as returned by
          @ref Qore::Socket::getSocketInfo())
        - \c peer-info: a hash of socket information for the remote socket (as returned by @ref Qore::Socket::getPeerInfo())
        - \c url: a hash of broken-down URL information (as returned from @ref Qore::parse_url())
        - \c id: the unique HTTP connection ID
        - \c ssl: @ref True "True" if the request was encrypted with HTTPS, @ref False "False" if not
        - \c listener-id: the HTTP server listener ID (see HttpServer::getListenerInfo())
        - \c user: the current RBAC username (if any)
        - \c root_path: the root URL path matched if the request was matched by a URL prefix
        @param hdr incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
        - \c method: the HTTP method received (ie \c "GET", \c "POST", etc)
        - \c path: the HTTP path given in the request, after processing by @ref Qore::decode_uri_request()
        - \c http_version: the HTTP version number in the request (either \c "1.0" or \c "1.1")
        @param body message body, if any

        @return the response to the WebDavHandler request

        @note this base class method calls handleProppatchImpl() to process the request
    */
    hash<HttpResponseInfo> handleProppatch(Socket s, hash<auto> cx, hash<auto> hdr, __7_ data body);


    //! This method is called with informational log messages
/** 
    */
    logInfo(string fmt);


    //! This method is called with error log messages
/** 
    */
    logError(string fmt);


    //! This method is called with debug log messages
/** 
    */
    logDebug(string fmt);


    //! Parse incoming XML and handle namespaces
protected:
     hash<auto> getXml(string body);
public:


    //! Handles an HTTP/WebDavHandler OPTIONS request
/**  @param cx call context hash; this hash will have the following keys:
        - \c header-info: a hash of information about the request header with the following keys:
          - \c accept-charset: this key will be set to an appropriate value from any \c "Accept-Charset" header; if
            any of \c "*", \c "utf8", or \c "utf-8" are present, then this will be set to \c "utf8", otherwise it will
            be set to the first requested character encoding in the list
          - \c accept-encoding: a hash where keys are values from any \c "Accept-Encoding" header and the values are
            @ref True
          - \c body-content-type: this is the \c "Content-Type" header without any charset declaration
          - \c charset: if there is a charset declaration in the \c "Content-Type" header, the value is returned in
            this key
          - \c client-cert: if the server is configured to capture remote client certificates, and the client supplied
            a certificate, this key will be populated with the @ref Qore::SSLCertificate "SSLCertificate" for the client
          - \c close: set to @ref True "True" if the connection should be closed after responding,
            @ref False "False" if not (as derived from the request header)
          - \c headers-raw: a hash of raw request headers without any case conversions or other processing
          - \c request-uri: gives the request URI in an HTTP request
        - \c socket: the bind address used to bind the listener (\c "socket-info" provides more detailed information)
        - \c socket-info: a hash of socket information for the listening socket (as returned by
          @ref Qore::Socket::getSocketInfo())
        - \c peer-info: a hash of socket information for the remote socket (as returned by @ref Qore::Socket::getPeerInfo())
        - \c url: a hash of broken-down URL information (as returned from @ref Qore::parse_url())
        - \c id: the unique HTTP connection ID
        - \c ssl: @ref True "True" if the request was encrypted with HTTPS, @ref False "False" if not
        - \c listener-id: the HTTP server listener ID (see HttpServer::getListenerInfo())
        - \c user: the current RBAC username (if any)
        - \c root_path: the root URL path matched if the request was matched by a URL prefix
        @param hdr incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
        - \c method: the HTTP method received (ie \c "GET", \c "POST", etc)
        - \c path: the HTTP path given in the request, after processing by @ref Qore::decode_uri_request()
        - \c http_version: the HTTP version number in the request (either \c "1.0" or \c "1.1")
        @param body message body, if any

        @return a 200 response with headers indicating WebDavHandler support
    */
protected:
     hash<HttpResponseInfo> handleOptionsImpl(Socket s, hash<auto> cx, hash<auto> hdr, __7_ data body);
public:


    //! Handles HTTP GET requests for WebDavHandler resources
/**  @param cx call context hash; this hash will have the following keys:
        - \c header-info: a hash of information about the request header with the following keys:
          - \c accept-charset: this key will be set to an appropriate value from any \c "Accept-Charset" header; if
            any of \c "*", \c "utf8", or \c "utf-8" are present, then this will be set to \c "utf8", otherwise it will
            be set to the first requested character encoding in the list
          - \c accept-encoding: a hash where keys are values from any \c "Accept-Encoding" header and the values are
            @ref True
          - \c body-content-type: this is the \c "Content-Type" header without any charset declaration
          - \c charset: if there is a charset declaration in the \c "Content-Type" header, the value is returned in
            this key
          - \c client-cert: if the server is configured to capture remote client certificates, and the client supplied
            a certificate, this key will be populated with the @ref Qore::SSLCertificate "SSLCertificate" for the client
          - \c close: set to @ref True "True" if the connection should be closed after responding,
            @ref False "False" if not (as derived from the request header)
          - \c headers-raw: a hash of raw request headers without any case conversions or other processing
          - \c request-uri: gives the request URI in an HTTP request
        - \c socket: the bind address used to bind the listener (\c "socket-info" provides more detailed information)
        - \c socket-info: a hash of socket information for the listening socket (as returned by
          @ref Qore::Socket::getSocketInfo())
        - \c peer-info: a hash of socket information for the remote socket (as returned by @ref Qore::Socket::getPeerInfo())
        - \c url: a hash of broken-down URL information (as returned from @ref Qore::parse_url())
        - \c id: the unique HTTP connection ID
        - \c ssl: @ref True "True" if the request was encrypted with HTTPS, @ref False "False" if not
        - \c listener-id: the HTTP server listener ID (see HttpServer::getListenerInfo())
        - \c user: the current RBAC username (if any)
        - \c root_path: the root URL path matched if the request was matched by a URL prefix
        @param hdr incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
        - \c method: the HTTP method received (ie \c "GET", \c "POST", etc)
        - \c path: the HTTP path given in the request, after processing by @ref Qore::decode_uri_request()
        - \c http_version: the HTTP version number in the request (either \c "1.0" or \c "1.1")
        @param body message body, if any

        @return the response to the HTTP request
    */
protected:
     abstract hash<HttpResponseInfo> handleGetImpl(Socket s, hash<auto> cx, hash<auto> hdr, __7_ data body);
public:

    //! Handles HTTP HEAD requests for WebDavHandler resources
/**  @param cx call context hash; this hash will have the following keys:
        - \c header-info: a hash of information about the request header with the following keys:
          - \c accept-charset: this key will be set to an appropriate value from any \c "Accept-Charset" header; if
            any of \c "*", \c "utf8", or \c "utf-8" are present, then this will be set to \c "utf8", otherwise it will
            be set to the first requested character encoding in the list
          - \c accept-encoding: a hash where keys are values from any \c "Accept-Encoding" header and the values are
            @ref True
          - \c body-content-type: this is the \c "Content-Type" header without any charset declaration
          - \c charset: if there is a charset declaration in the \c "Content-Type" header, the value is returned in
            this key
          - \c client-cert: if the server is configured to capture remote client certificates, and the client supplied
            a certificate, this key will be populated with the @ref Qore::SSLCertificate "SSLCertificate" for the client
          - \c close: set to @ref True "True" if the connection should be closed after responding,
            @ref False "False" if not (as derived from the request header)
          - \c headers-raw: a hash of raw request headers without any case conversions or other processing
          - \c request-uri: gives the request URI in an HTTP request
        - \c socket: the bind address used to bind the listener (\c "socket-info" provides more detailed information)
        - \c socket-info: a hash of socket information for the listening socket (as returned by
          @ref Qore::Socket::getSocketInfo())
        - \c peer-info: a hash of socket information for the remote socket (as returned by @ref Qore::Socket::getPeerInfo())
        - \c url: a hash of broken-down URL information (as returned from @ref Qore::parse_url())
        - \c id: the unique HTTP connection ID
        - \c ssl: @ref True "True" if the request was encrypted with HTTPS, @ref False "False" if not
        - \c listener-id: the HTTP server listener ID (see HttpServer::getListenerInfo())
        - \c user: the current RBAC username (if any)
        - \c root_path: the root URL path matched if the request was matched by a URL prefix
        @param hdr incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
        - \c method: the HTTP method received (ie \c "GET", \c "POST", etc)
        - \c path: the HTTP path given in the request, after processing by @ref Qore::decode_uri_request()
        - \c http_version: the HTTP version number in the request (either \c "1.0" or \c "1.1")
        @param body message body, if any

        @return the response to the HTTP request
    */
protected:
     abstract hash<HttpResponseInfo> handleHeadImpl(Socket s, hash<auto> cx, hash<auto> hdr, __7_ data body);
public:

    //! Handles HTTP POST requests for WebDavHandler resources
/**  @param cx call context hash; this hash will have the following keys:
        - \c header-info: a hash of information about the request header with the following keys:
          - \c accept-charset: this key will be set to an appropriate value from any \c "Accept-Charset" header; if
            any of \c "*", \c "utf8", or \c "utf-8" are present, then this will be set to \c "utf8", otherwise it will
            be set to the first requested character encoding in the list
          - \c accept-encoding: a hash where keys are values from any \c "Accept-Encoding" header and the values are
            @ref True
          - \c body-content-type: this is the \c "Content-Type" header without any charset declaration
          - \c charset: if there is a charset declaration in the \c "Content-Type" header, the value is returned in
            this key
          - \c client-cert: if the server is configured to capture remote client certificates, and the client supplied
            a certificate, this key will be populated with the @ref Qore::SSLCertificate "SSLCertificate" for the client
          - \c close: set to @ref True "True" if the connection should be closed after responding,
            @ref False "False" if not (as derived from the request header)
          - \c headers-raw: a hash of raw request headers without any case conversions or other processing
          - \c request-uri: gives the request URI in an HTTP request
        - \c socket: the bind address used to bind the listener (\c "socket-info" provides more detailed information)
        - \c socket-info: a hash of socket information for the listening socket (as returned by
          @ref Qore::Socket::getSocketInfo())
        - \c peer-info: a hash of socket information for the remote socket (as returned by @ref Qore::Socket::getPeerInfo())
        - \c url: a hash of broken-down URL information (as returned from @ref Qore::parse_url())
        - \c id: the unique HTTP connection ID
        - \c ssl: @ref True "True" if the request was encrypted with HTTPS, @ref False "False" if not
        - \c listener-id: the HTTP server listener ID (see HttpServer::getListenerInfo())
        - \c user: the current RBAC username (if any)
        - \c root_path: the root URL path matched if the request was matched by a URL prefix
        @param hdr incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
        - \c method: the HTTP method received (ie \c "GET", \c "POST", etc)
        - \c path: the HTTP path given in the request, after processing by @ref Qore::decode_uri_request()
        - \c http_version: the HTTP version number in the request (either \c "1.0" or \c "1.1")
        @param body message body, if any

        @return the response to the HTTP request
    */
protected:
     abstract hash<HttpResponseInfo> handlePostImpl(Socket s, hash<auto> cx, hash<auto> hdr, __7_ data body);
public:

    //! Handles HTTP PUT requests for WebDavHandler resources
/**  @param cx call context hash; this hash will have the following keys:
        - \c header-info: a hash of information about the request header with the following keys:
          - \c accept-charset: this key will be set to an appropriate value from any \c "Accept-Charset" header; if
            any of \c "*", \c "utf8", or \c "utf-8" are present, then this will be set to \c "utf8", otherwise it will
            be set to the first requested character encoding in the list
          - \c accept-encoding: a hash where keys are values from any \c "Accept-Encoding" header and the values are
            @ref True
          - \c body-content-type: this is the \c "Content-Type" header without any charset declaration
          - \c charset: if there is a charset declaration in the \c "Content-Type" header, the value is returned in
            this key
          - \c client-cert: if the server is configured to capture remote client certificates, and the client supplied
            a certificate, this key will be populated with the @ref Qore::SSLCertificate "SSLCertificate" for the client
          - \c close: set to @ref True "True" if the connection should be closed after responding,
            @ref False "False" if not (as derived from the request header)
          - \c headers-raw: a hash of raw request headers without any case conversions or other processing
          - \c request-uri: gives the request URI in an HTTP request
        - \c socket: the bind address used to bind the listener (\c "socket-info" provides more detailed information)
        - \c socket-info: a hash of socket information for the listening socket (as returned by
          @ref Qore::Socket::getSocketInfo())
        - \c peer-info: a hash of socket information for the remote socket (as returned by @ref Qore::Socket::getPeerInfo())
        - \c url: a hash of broken-down URL information (as returned from @ref Qore::parse_url())
        - \c id: the unique HTTP connection ID
        - \c ssl: @ref True "True" if the request was encrypted with HTTPS, @ref False "False" if not
        - \c listener-id: the HTTP server listener ID (see HttpServer::getListenerInfo())
        - \c user: the current RBAC username (if any)
        - \c root_path: the root URL path matched if the request was matched by a URL prefix
        @param hdr incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
        - \c method: the HTTP method received (ie \c "GET", \c "POST", etc)
        - \c path: the HTTP path given in the request, after processing by @ref Qore::decode_uri_request()
        - \c http_version: the HTTP version number in the request (either \c "1.0" or \c "1.1")
        @param body message body, if any

        @return the response to the HTTP request
    */
protected:
     abstract hash<HttpResponseInfo> handlePutImpl(Socket s, hash<auto> cx, hash<auto> hdr, __7_ data body);
public:

    //! Handles HTTP DELETE requests for WebDavHandler resources
/**  @param cx call context hash; this hash will have the following keys:
        - \c header-info: a hash of information about the request header with the following keys:
          - \c accept-charset: this key will be set to an appropriate value from any \c "Accept-Charset" header; if
            any of \c "*", \c "utf8", or \c "utf-8" are present, then this will be set to \c "utf8", otherwise it will
            be set to the first requested character encoding in the list
          - \c accept-encoding: a hash where keys are values from any \c "Accept-Encoding" header and the values are
            @ref True
          - \c body-content-type: this is the \c "Content-Type" header without any charset declaration
          - \c charset: if there is a charset declaration in the \c "Content-Type" header, the value is returned in
            this key
          - \c client-cert: if the server is configured to capture remote client certificates, and the client supplied
            a certificate, this key will be populated with the @ref Qore::SSLCertificate "SSLCertificate" for the client
          - \c close: set to @ref True "True" if the connection should be closed after responding,
            @ref False "False" if not (as derived from the request header)
          - \c headers-raw: a hash of raw request headers without any case conversions or other processing
          - \c request-uri: gives the request URI in an HTTP request
        - \c socket: the bind address used to bind the listener (\c "socket-info" provides more detailed information)
        - \c socket-info: a hash of socket information for the listening socket (as returned by
          @ref Qore::Socket::getSocketInfo())
        - \c peer-info: a hash of socket information for the remote socket (as returned by @ref Qore::Socket::getPeerInfo())
        - \c url: a hash of broken-down URL information (as returned from @ref Qore::parse_url())
        - \c id: the unique HTTP connection ID
        - \c ssl: @ref True "True" if the request was encrypted with HTTPS, @ref False "False" if not
        - \c listener-id: the HTTP server listener ID (see HttpServer::getListenerInfo())
        - \c user: the current RBAC username (if any)
        - \c root_path: the root URL path matched if the request was matched by a URL prefix
        @param hdr incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
        - \c method: the HTTP method received (ie \c "GET", \c "POST", etc)
        - \c path: the HTTP path given in the request, after processing by @ref Qore::decode_uri_request()
        - \c http_version: the HTTP version number in the request (either \c "1.0" or \c "1.1")
        @param body message body, if any

        @return the response to the HTTP request
    */
protected:
     abstract hash<HttpResponseInfo> handleDeleteImpl(Socket s, hash<auto> cx, hash<auto> hdr, __7_ data body);
public:

    //! Handles WebDavHandler COPY requests for WebDavHandler resources
/**  @param cx call context hash; this hash will have the following keys:
        - \c header-info: a hash of information about the request header with the following keys:
          - \c accept-charset: this key will be set to an appropriate value from any \c "Accept-Charset" header; if
            any of \c "*", \c "utf8", or \c "utf-8" are present, then this will be set to \c "utf8", otherwise it will
            be set to the first requested character encoding in the list
          - \c accept-encoding: a hash where keys are values from any \c "Accept-Encoding" header and the values are
            @ref True
          - \c body-content-type: this is the \c "Content-Type" header without any charset declaration
          - \c charset: if there is a charset declaration in the \c "Content-Type" header, the value is returned in
            this key
          - \c client-cert: if the server is configured to capture remote client certificates, and the client supplied
            a certificate, this key will be populated with the @ref Qore::SSLCertificate "SSLCertificate" for the client
          - \c close: set to @ref True "True" if the connection should be closed after responding,
            @ref False "False" if not (as derived from the request header)
          - \c headers-raw: a hash of raw request headers without any case conversions or other processing
          - \c request-uri: gives the request URI in an HTTP request
        - \c socket: the bind address used to bind the listener (\c "socket-info" provides more detailed information)
        - \c socket-info: a hash of socket information for the listening socket (as returned by
          @ref Qore::Socket::getSocketInfo())
        - \c peer-info: a hash of socket information for the remote socket (as returned by @ref Qore::Socket::getPeerInfo())
        - \c url: a hash of broken-down URL information (as returned from @ref Qore::parse_url())
        - \c id: the unique HTTP connection ID
        - \c ssl: @ref True "True" if the request was encrypted with HTTPS, @ref False "False" if not
        - \c listener-id: the HTTP server listener ID (see HttpServer::getListenerInfo())
        - \c user: the current RBAC username (if any)
        - \c root_path: the root URL path matched if the request was matched by a URL prefix
        @param hdr incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
        - \c method: the HTTP method received (ie \c "GET", \c "POST", etc)
        - \c path: the HTTP path given in the request, after processing by @ref Qore::decode_uri_request()
        - \c http_version: the HTTP version number in the request (either \c "1.0" or \c "1.1")
        @param body message body, if any

        @return the response to the WebDavHandler request
    */
protected:
     abstract hash<HttpResponseInfo> handleCopyImpl(Socket s, hash<auto> cx, hash<auto> hdr, __7_ data body);
public:

    //! Handles WebDavHandler MOVE requests for WebDavHandler resources
/**  @param cx call context hash; this hash will have the following keys:
        - \c header-info: a hash of information about the request header with the following keys:
          - \c accept-charset: this key will be set to an appropriate value from any \c "Accept-Charset" header; if
            any of \c "*", \c "utf8", or \c "utf-8" are present, then this will be set to \c "utf8", otherwise it will
            be set to the first requested character encoding in the list
          - \c accept-encoding: a hash where keys are values from any \c "Accept-Encoding" header and the values are
            @ref True
          - \c body-content-type: this is the \c "Content-Type" header without any charset declaration
          - \c charset: if there is a charset declaration in the \c "Content-Type" header, the value is returned in
            this key
          - \c client-cert: if the server is configured to capture remote client certificates, and the client supplied
            a certificate, this key will be populated with the @ref Qore::SSLCertificate "SSLCertificate" for the client
          - \c close: set to @ref True "True" if the connection should be closed after responding,
            @ref False "False" if not (as derived from the request header)
          - \c headers-raw: a hash of raw request headers without any case conversions or other processing
          - \c request-uri: gives the request URI in an HTTP request
        - \c socket: the bind address used to bind the listener (\c "socket-info" provides more detailed information)
        - \c socket-info: a hash of socket information for the listening socket (as returned by
          @ref Qore::Socket::getSocketInfo())
        - \c peer-info: a hash of socket information for the remote socket (as returned by @ref Qore::Socket::getPeerInfo())
        - \c url: a hash of broken-down URL information (as returned from @ref Qore::parse_url())
        - \c id: the unique HTTP connection ID
        - \c ssl: @ref True "True" if the request was encrypted with HTTPS, @ref False "False" if not
        - \c listener-id: the HTTP server listener ID (see HttpServer::getListenerInfo())
        - \c user: the current RBAC username (if any)
        - \c root_path: the root URL path matched if the request was matched by a URL prefix
        @param hdr incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
        - \c method: the HTTP method received (ie \c "GET", \c "POST", etc)
        - \c path: the HTTP path given in the request, after processing by @ref Qore::decode_uri_request()
        - \c http_version: the HTTP version number in the request (either \c "1.0" or \c "1.1")
        @param body message body, if any

        @return the response to the WebDavHandler request
    */
protected:
     abstract hash<HttpResponseInfo> handleMoveImpl(Socket s, hash<auto> cx, hash<auto> hdr, __7_ data body);
public:

    //! Handles WebDavHandler LOCK requests for WebDavHandler resources
/**  @param cx call context hash; this hash will have the following keys:
        - \c header-info: a hash of information about the request header with the following keys:
          - \c accept-charset: this key will be set to an appropriate value from any \c "Accept-Charset" header; if
            any of \c "*", \c "utf8", or \c "utf-8" are present, then this will be set to \c "utf8", otherwise it will
            be set to the first requested character encoding in the list
          - \c accept-encoding: a hash where keys are values from any \c "Accept-Encoding" header and the values are
            @ref True
          - \c body-content-type: this is the \c "Content-Type" header without any charset declaration
          - \c charset: if there is a charset declaration in the \c "Content-Type" header, the value is returned in
            this key
          - \c client-cert: if the server is configured to capture remote client certificates, and the client supplied
            a certificate, this key will be populated with the @ref Qore::SSLCertificate "SSLCertificate" for the client
          - \c close: set to @ref True "True" if the connection should be closed after responding,
            @ref False "False" if not (as derived from the request header)
          - \c headers-raw: a hash of raw request headers without any case conversions or other processing
          - \c request-uri: gives the request URI in an HTTP request
        - \c socket: the bind address used to bind the listener (\c "socket-info" provides more detailed information)
        - \c socket-info: a hash of socket information for the listening socket (as returned by
          @ref Qore::Socket::getSocketInfo())
        - \c peer-info: a hash of socket information for the remote socket (as returned by @ref Qore::Socket::getPeerInfo())
        - \c url: a hash of broken-down URL information (as returned from @ref Qore::parse_url())
        - \c id: the unique HTTP connection ID
        - \c ssl: @ref True "True" if the request was encrypted with HTTPS, @ref False "False" if not
        - \c listener-id: the HTTP server listener ID (see HttpServer::getListenerInfo())
        - \c user: the current RBAC username (if any)
        - \c root_path: the root URL path matched if the request was matched by a URL prefix
        @param hdr incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
        - \c method: the HTTP method received (ie \c "GET", \c "POST", etc)
        - \c path: the HTTP path given in the request, after processing by @ref Qore::decode_uri_request()
        - \c http_version: the HTTP version number in the request (either \c "1.0" or \c "1.1")
        @param body message body, if any

        @return the response to the WebDavHandler request
    */
protected:
     abstract hash<HttpResponseInfo> handleLockImpl(Socket s, hash<auto> cx, hash<auto> hdr, __7_ data body);
public:

    //! Handles WebDavHandler UNLOCK requests for WebDavHandler resources
/**  @param cx call context hash; this hash will have the following keys:
        - \c header-info: a hash of information about the request header with the following keys:
          - \c accept-charset: this key will be set to an appropriate value from any \c "Accept-Charset" header; if
            any of \c "*", \c "utf8", or \c "utf-8" are present, then this will be set to \c "utf8", otherwise it will
            be set to the first requested character encoding in the list
          - \c accept-encoding: a hash where keys are values from any \c "Accept-Encoding" header and the values are
            @ref True
          - \c body-content-type: this is the \c "Content-Type" header without any charset declaration
          - \c charset: if there is a charset declaration in the \c "Content-Type" header, the value is returned in
            this key
          - \c client-cert: if the server is configured to capture remote client certificates, and the client supplied
            a certificate, this key will be populated with the @ref Qore::SSLCertificate "SSLCertificate" for the client
          - \c close: set to @ref True "True" if the connection should be closed after responding,
            @ref False "False" if not (as derived from the request header)
          - \c headers-raw: a hash of raw request headers without any case conversions or other processing
          - \c request-uri: gives the request URI in an HTTP request
        - \c socket: the bind address used to bind the listener (\c "socket-info" provides more detailed information)
        - \c socket-info: a hash of socket information for the listening socket (as returned by
          @ref Qore::Socket::getSocketInfo())
        - \c peer-info: a hash of socket information for the remote socket (as returned by @ref Qore::Socket::getPeerInfo())
        - \c url: a hash of broken-down URL information (as returned from @ref Qore::parse_url())
        - \c id: the unique HTTP connection ID
        - \c ssl: @ref True "True" if the request was encrypted with HTTPS, @ref False "False" if not
        - \c listener-id: the HTTP server listener ID (see HttpServer::getListenerInfo())
        - \c user: the current RBAC username (if any)
        - \c root_path: the root URL path matched if the request was matched by a URL prefix
        @param hdr incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
        - \c method: the HTTP method received (ie \c "GET", \c "POST", etc)
        - \c path: the HTTP path given in the request, after processing by @ref Qore::decode_uri_request()
        - \c http_version: the HTTP version number in the request (either \c "1.0" or \c "1.1")
        @param body message body, if any

        @return the response to the WebDavHandler request
    */
protected:
     abstract hash<HttpResponseInfo> handleUnlockImpl(Socket s, hash<auto> cx, hash<auto> hdr, __7_ data body);
public:

    //! Handles WebDavHandler MKCOL requests for WebDavHandler resources
/**  @param cx call context hash; this hash will have the following keys:
        - \c header-info: a hash of information about the request header with the following keys:
          - \c accept-charset: this key will be set to an appropriate value from any \c "Accept-Charset" header; if
            any of \c "*", \c "utf8", or \c "utf-8" are present, then this will be set to \c "utf8", otherwise it will
            be set to the first requested character encoding in the list
          - \c accept-encoding: a hash where keys are values from any \c "Accept-Encoding" header and the values are
            @ref True
          - \c body-content-type: this is the \c "Content-Type" header without any charset declaration
          - \c charset: if there is a charset declaration in the \c "Content-Type" header, the value is returned in
            this key
          - \c client-cert: if the server is configured to capture remote client certificates, and the client supplied
            a certificate, this key will be populated with the @ref Qore::SSLCertificate "SSLCertificate" for the client
          - \c close: set to @ref True "True" if the connection should be closed after responding,
            @ref False "False" if not (as derived from the request header)
          - \c headers-raw: a hash of raw request headers without any case conversions or other processing
          - \c request-uri: gives the request URI in an HTTP request
        - \c socket: the bind address used to bind the listener (\c "socket-info" provides more detailed information)
        - \c socket-info: a hash of socket information for the listening socket (as returned by
          @ref Qore::Socket::getSocketInfo())
        - \c peer-info: a hash of socket information for the remote socket (as returned by @ref Qore::Socket::getPeerInfo())
        - \c url: a hash of broken-down URL information (as returned from @ref Qore::parse_url())
        - \c id: the unique HTTP connection ID
        - \c ssl: @ref True "True" if the request was encrypted with HTTPS, @ref False "False" if not
        - \c listener-id: the HTTP server listener ID (see HttpServer::getListenerInfo())
        - \c user: the current RBAC username (if any)
        - \c root_path: the root URL path matched if the request was matched by a URL prefix
        @param hdr incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
        - \c method: the HTTP method received (ie \c "GET", \c "POST", etc)
        - \c path: the HTTP path given in the request, after processing by @ref Qore::decode_uri_request()
        - \c http_version: the HTTP version number in the request (either \c "1.0" or \c "1.1")
        @param body message body, if any

        @return the response to the WebDavHandler request
    */
protected:
     abstract hash<HttpResponseInfo> handleMkcolImpl(Socket s, hash<auto> cx, hash<auto> hdr, __7_ data body);
public:

    //! Handles WebDavHandler PROPFIND requests for WebDavHandler resources; reetrieves properties from WebDavHandler resources
/**
        @param cx call context hash; this hash will have the following keys:
        - \c header-info: a hash of information about the request header with the following keys:
          - \c accept-charset: this key will be set to an appropriate value from any \c "Accept-Charset" header; if
            any of \c "*", \c "utf8", or \c "utf-8" are present, then this will be set to \c "utf8", otherwise it will
            be set to the first requested character encoding in the list
          - \c accept-encoding: a hash where keys are values from any \c "Accept-Encoding" header and the values are
            @ref True
          - \c body-content-type: this is the \c "Content-Type" header without any charset declaration
          - \c charset: if there is a charset declaration in the \c "Content-Type" header, the value is returned in
            this key
          - \c client-cert: if the server is configured to capture remote client certificates, and the client supplied
            a certificate, this key will be populated with the @ref Qore::SSLCertificate "SSLCertificate" for the client
          - \c close: set to @ref True "True" if the connection should be closed after responding,
            @ref False "False" if not (as derived from the request header)
          - \c headers-raw: a hash of raw request headers without any case conversions or other processing
          - \c request-uri: gives the request URI in an HTTP request
        - \c socket: the bind address used to bind the listener (\c "socket-info" provides more detailed information)
        - \c socket-info: a hash of socket information for the listening socket (as returned by
          @ref Qore::Socket::getSocketInfo())
        - \c peer-info: a hash of socket information for the remote socket (as returned by @ref Qore::Socket::getPeerInfo())
        - \c url: a hash of broken-down URL information (as returned from @ref Qore::parse_url())
        - \c id: the unique HTTP connection ID
        - \c ssl: @ref True "True" if the request was encrypted with HTTPS, @ref False "False" if not
        - \c listener-id: the HTTP server listener ID (see HttpServer::getListenerInfo())
        - \c user: the current RBAC username (if any)
        - \c root_path: the root URL path matched if the request was matched by a URL prefix
        @param hdr incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
        - \c method: the HTTP method received (ie \c "GET", \c "POST", etc)
        - \c path: the HTTP path given in the request, after processing by @ref Qore::decode_uri_request()
        - \c http_version: the HTTP version number in the request (either \c "1.0" or \c "1.1")
        @param body message body, if any

        @return the response to the WebDavHandler request
    */
protected:
     abstract hash<HttpResponseInfo> handlePropfindImpl(Socket s, hash<auto> cx, hash<auto> hdr, __7_ data body);
public:

    //! Internal method for handling PROPPATCH requests
/** @param href the href for the response
        @param cx the HTTP call context
        @param hdr as hash HTTP headers
        @param request_xml the parsed XML in the request
        @param actions a list of set and remove actions to execute on the given properties

        @return a status map of HTTP code -> namespace -> property -> True

        @throw WEBDAVHANDLER-ERROR an error occured
    */
private:
 abstract __7_ hash<string, hash<string, hash<string, bool>>> handleProppatchImpl(reference<string> href, hash<auto> cx, hash<auto> hdr, *hash<auto> request_xml, *list<hash<PropPatchActionInfo>> actions);  *hash<auto> fixDavPrefixes(string ns, hash<auto> h, *string pfx);
public:


    //! Combines values recursively
      static combineValue(reference<auto> h, auto v);

    //! Returns a new namespace prefix
private:
     string getNsPrefix(string ns);
public:


private:
     string getKey(string key, __7_ string nsa);
public:


private:
     list<auto> fixDavPrefixes(string ns, list<auto> l, __7_ string pfx);
public:


private:
     auto fixDavPrefixes(string ns, auto v, __7_ string pfx);
public:

};
}

// unexperted namespace
namespace Priv {
// for namespace handling while parsing
hashdecl NsInfo {
    // map of namespace abbreviations to namespace URIs
    hash<string, string> nsmap = {
        DavNs: DavNs,
    };
    // reverse of nsmap
    hash<string, string> nsrmap = {
        DavNs: DavNs,
    };
}

thread_local hash<NsInfo> nsinfo;
}