Plasma GitLab Archive
Projects Blog Knowledge

(* $Id: webdav_xml.mli 1 2011-08-26 21:00:39Z gerd $ *)

(** Parsing and printing XML for WebDAV messages *)

open Webdav_http


(** {2 Properties} *)

type property =
    'node Pxp_document.extension Pxp_document.node as 'node
  (** A property is an XML tree. It is required that the XML tree is
      namespace-aware. For trees passed in to this module, the DTD object
      can be arbitrary. The character encoding must be UTF-8 ([`Enc_utf8]).

      The root node of the property tree must be an XML element.
      Namespace processing is done as in PXP, i.e. namespace prefixes
      are normalized. For checking that a property has a certain name,
      one should either:
       - use the pair [(localname, namespace_uri)] as compound name
       - define prefixes in the namespace manager for the expected
         namespace URIs, and use the normalized name (the argument of
         [T_element])

      Example for the first method (assumed [p] is a [property]):
      {[ p#localname = "notes" && 
         p#namespace_uri = "http://www.w3.org/1999/xhtml" ]}

      Example for the second method:
      {[
         let m = namespace_manager()
         m # add_namespace "h" "http://www.w3.org/1999/xhtml";
         let r = parse_multistatus_body ~namespace_manager:m  ...
         let p = List.hd ((List.hd r) # propstat)   (* p : property *)
         match p # node_type with
          | T_element "h:notes" -> true
          | _ -> false
      ]}

      The values of the properties are also normalized in this way, and
      must be handled accordingly. There is no guarantee that the prefixes
      are presented in the same way as they come from the server.
   *)

val create_propname : ?namespace_manager:Pxp_dtd.namespace_manager ->
                      string -> property
  (** Creates a property element without children. This element can be
      used in PROPFIND queries as property name

      The passed string must have the form "prefix:localname",
      and the prefix must be declared in the namespace manager.
      The default namespace manager only defines the prefix "DAV".

      Example:
      {[ create_propname "DAV:creationdate" ]}
   *)

val propname_creationdate : property
val propname_displayname : property
val propname_getcontentlanguage : property
val propname_getcontentlength : property
val propname_getcontenttype : property
val propname_getetag : property
val propname_getlastmodified : property
val propname_resourcetype : property
  (** Standard WebDAV properties *)

val decode_string : property -> string
  (** Returns the included string from any property *)

val decode_creationdate : property -> float
val decode_displayname : property -> string
val decode_getcontentlanguage : property -> string
val decode_getcontentlength : property -> int64
val decode_getcontenttype : property -> string * (string * string) list
val decode_getetag : property -> Nethttp.etag
val decode_getlastmodified : property -> float
val decode_resourcetype : property -> bool
  (** Decodes standard WebDAV properties *)

val encode_string : string -> string -> property
  (** [encode_string name value]: Creates a property with [name] that
      includes the [value] as string
   *)

val encode_creationdate : float -> property
val encode_displayname : string -> property
val encode_getcontentlanguage : string -> property
val encode_getcontentlength : int64 -> property
val encode_getcontenttype : string * (string * string) list -> property
val encode_getetag : Nethttp.etag -> property
val encode_getlastmodified : float -> property
val encode_resourcetype : bool -> property
  (** Encodes standard WebDAV properties *)

(** {2 Precondition/postcondition elements} *)

type prepost_code =
    'node Pxp_document.extension Pxp_document.node as 'node
  (** A precondition/postcondition element. Works in the same way
      as [property].
   *)

type known_prepost_code =
    [ `No_external_entities 
    | `Preserved_live_properties
    | `Propfind_finite_depth
    | `Cannot_modify_protected_property
    ]
  (** The precondition/postcondition codes this implementation understands *)

val create_prepost_code : ?namespace_manager:Pxp_dtd.namespace_manager ->
                           string -> prepost_code
  (** Creates a pre/postcondition code without children. Content, if any,
      can be added to the returned XML node.

      The passed string must have the form "prefix:localname",
      and the prefix must be declared in the namespace manager.
      The default namespace manager only defines the prefix "DAV".

      Example:
      {[ create_propname "DAV:no-external-entities" ]}
   *)


val parse_prepost_code : prepost_code -> known_prepost_code
  (** Checks whether the pre/postcondition code is known and returns
      the code. Raise [Not_found] if unknown
   *)

val emit_prepost_code : known_prepost_code -> prepost_code
  (** reverse *)

(** {2 General XML stuff} *)

val namespace_manager : unit -> Pxp_dtd.namespace_manager
  (** The namespace manager used by XML trees that are returned from this 
      module. Defines the prefixes:
       - ["DAV"]: This is the prefix for WebDAV requests
   *)

val check_dtd : Pxp_dtd.dtd -> unit
  (** Checks whether the DTD satisfies the minimum requirements:
      - The encoding is UTF-8
      - There are no element, attribute, or notation declarations
      - Checking such declarations is turned off
      - All entities are internal
      - The namespace manager defines "DAV".
   *)

val dtd : unit -> Pxp_dtd.dtd
  (** The DTD used by XML trees that are returned from this module.
      This DTD can also be used for trees generated by the user.
   *)


(** {2 URLs} *)

val url_path : ?strip_prefix:string -> string -> string
  (** Extracts the URL path from a URL. Parsing is error-tolerant to
      some extent.

      It is checked, however, whether the resulting string is UTF-8.
   *)

(** {2 Support for [propstat]} *)

(** Same as {!Webdav_client_methods.propstat_t} *)
class type propstat_t =
object
  method properties : property list
  method status : webdav_status
  method status_code : int
  method status_text : string
  method status_protocol : string
  method error : prepost_code list
  method responsedescription : string
end


val create_propstat : 
       properties:property list ->
       status:webdav_status ->
       ?status_code:int ->
       ?status_text:string ->
       ?status_protocol:string ->
       ?error:prepost_code list ->
       ?responsedescription:string ->
       unit -> propstat_t
  (** Creates a [propstat_t].

      - The [status_code] method will return the code corresponding to the
        [status] argument unless the [status_code] argument overrides it
      - The [status_text] method will return the text corresponding to the
        [status] argument unless the [status_text] argument overrides it
      - The [status_protocol] method will return {!Webdav_http.webdav_proto}
        unless the [status_protocol] argument overrides it
   *)



(** {2 Support for [response]} *)

(** Same as {!Webdav_client_methods.response_t} *)
class type response_t =
object
  method href : string list
  method paths : string list
  method status : webdav_status
  method status_code : int
  method status_text : string
  method status_protocol : string
  method propstat : propstat_t list
  method prop_creationdate : float option
  method prop_displayname : string option
  method prop_getcontentlanguage : string option
  method prop_getcontentlength : int64 option
  method prop_getcontenttype : string option
  method prop_getcontenttype_decoded : (string * (string * string) list) option
  method prop_getetag : string option
  method prop_getetag_decoded : Nethttp.etag option
  method prop_getlastmodified : float option
  method prop_resourcetype_is_collection : bool option
  method find_prop : string -> property * propstat_t
  method error : prepost_code list
  method responsedescription : string
  method location : string option
end


val create_status_response : 
       href:string list ->
       status:webdav_status ->
       ?status_code:int ->
       ?status_text:string ->
       ?status_protocol:string ->
       ?error:prepost_code list ->
       ?responsedescription:string ->
       ?location:string ->
       ?strip_prefix:string ->
       unit -> response_t
  (** Creates the kind of [response_t] that includes a [status] element,
      but no [propstat] elements. In the returned object, the [propstat]
      method returns the empty list.

      The [href] list must contain at least one element.

      [status], [status_code], [status_text], and [status_protocol] are
      handled as in {!Webdav_xml.create_propstat}.

      If [strip_prefix] is passed, this prefix is removed from all paths
      that are returned via the [paths] method.
   *)


val create_propstat_response :
       href:string ->
       propstat:propstat_t list ->
       ?error:prepost_code list ->
       ?responsedescription:string ->
       ?location:string ->
       ?strip_prefix:string ->
       unit -> response_t
  (** Create the kind of [response_t] that includes [propstat] elements but
      no [status] element. In the returned object, the [status] method
      returns [`Ok].

      The [propstat] list must contain at least one element.

      If [strip_prefix] is passed, this prefix is removed from the single path
      returned via the [paths] method.
   *)


(** {2 Support for [multistatus]} *)

class type multistatus_t =
object
  method responses : response_t list
  method responsedescription : string
end


val create_multistatus : 
       responses:response_t list ->
       ?responsedescription:string ->
       unit -> multistatus_t


val parse_multistatus_body :
      ?strip_prefix:string ->
      ?namespace_manager:Pxp_dtd.namespace_manager ->
      content_type:string ->
      Netchannels.in_obj_channel ->
        multistatus_t
  (** Parses the body of a [`Multi_status] response. It is required to
      pass the [content_type] from the HTTP header (for extracting the
      character encoding). Optionally, one can pass an initialized namespace
      manager. This is useful to enforce that certain XML prefixes are
      used for the expected namespaces. It is expected that the prefix
      "DAV" is bound to the namespace URI "DAV:". There is no guarantee
      that the display prefixes are preserved.

      [strip_prefix]: If passed, this path prefix is removed from the
      paths returned by the [paths] method. Also, it is considered an
      error if a path is found not within this prefix.
   *)

val write_multistatus_body :
      ?namespace_manager:Pxp_dtd.namespace_manager ->
      Netchannels.out_obj_channel ->
      multistatus_t ->
        unit
  (** Outputs this multistatus response object to the output channel.
      The character encoding is always UTF-8.
   *)


(** {2 Support for [PROPFIND]} *)

(** Same as {!Webdav_client_methods.propfind_request} *)
type propfind_request =
  [ `Prop of property list
  | `Propname
  | `Allprop of property list
  ]

val parse_propfind_request :
      ?namespace_manager:Pxp_dtd.namespace_manager ->
      content_type:string ->
      Netchannels.in_obj_channel ->
         propfind_request
  (** Parses the body of a [propfind] request body. See also 
      {!Webdav_xml.parse_multistatus_body} for the meaning of
      [namespace_manager] and [content_type].
   *)

val write_propfind_request :
      ?namespace_manager:Pxp_dtd.namespace_manager ->
      Netchannels.out_obj_channel ->
      propfind_request ->
        unit
  (** Writes the XML request for the PROPFIND method. The request will always
      be UTF-8-encoded.

      The passed properties (i.e. XML trees) can use any DTD and any
      namespace manager. In the generated XML text namespace prefixes are
      preserved (the prefix as returned by the [display_prefix] method of
      the property nodes).
   *)


(** {2 Support for [PROPPATCH]} *)

(** Same as {!Webdav_client_methods.proppatch_instruction} *)
type proppatch_instruction =
    [ `Remove of property list
    | `Set of property list
    ]

(** Same as {!Webdav_client_methods.proppatch_request} *)
type proppatch_request =
    proppatch_instruction list

val parse_proppatch_request :
      ?namespace_manager:Pxp_dtd.namespace_manager ->
      content_type:string ->
      Netchannels.in_obj_channel ->
         proppatch_request
  (** Parses the body of a [proppatch] request body. See also 
      {!Webdav_xml.parse_multistatus_body} for the meaning of
      [namespace_manager] and [content_type].
   *)

val write_proppatch_request :
      ?namespace_manager:Pxp_dtd.namespace_manager ->
      Netchannels.out_obj_channel ->
      proppatch_request ->
        unit
  (** Writes the XML request for the PROPPATCH method. The request will always
      be UTF-8-encoded.

      The passed properties (i.e. XML trees) can use any DTD and any
      namespace manager. In the generated XML text namespace prefixes are
      preserved (the prefix as returned by the [display_prefix] method of
      the property nodes).
   *)

This web site is published by Informatikbüro Gerd Stolpmann
Powered by Caml