Back to index

avfs  1.0.1
Classes | Defines | Functions | Variables
dav_props.c File Reference
#include "config.h"
#include "ne_alloc.h"
#include "dav_props.h"
#include "dav_basic.h"
#include "hip_xml.h"

Go to the source code of this file.

Classes

struct  dav_propfind_handler_s
struct  prop
struct  propstat
struct  dav_prop_result_set_s

Defines

#define ELM_namedprop   (DAV_ELM_207_UNUSED)

Functions

hip_xml_parser * dav_propfind_get_parser (dav_propfind_handler *handler)
static int propfind (dav_propfind_handler *handler, dav_props_result results, void *userdata)
static void set_body (dav_propfind_handler *hdl, const dav_propname *names)
int dav_propfind_allprop (dav_propfind_handler *handler, dav_props_result results, void *userdata)
int dav_propfind_named (dav_propfind_handler *handler, dav_props_result results, void *userdata)
int dav_proppatch (http_session *sess, const char *uri, const dav_proppatch_operation *items)
static int pnamecmp (const dav_propname *pn1, const dav_propname *pn2)
static int findprop (const dav_prop_result_set *set, const dav_propname *pname, struct propstat **pstat_ret, struct prop **prop_ret)
const char * dav_propset_value (const dav_prop_result_set *set, const dav_propname *pname)
void * dav_propfind_current_private (dav_propfind_handler *handler)
void * dav_propset_private (const dav_prop_result_set *set)
int dav_propset_iterate (const dav_prop_result_set *set, dav_propset_iterator iterator, void *userdata)
const http_statusdav_propset_status (const dav_prop_result_set *set, const dav_propname *pname)
static int check_context (hip_xml_elmid parent, hip_xml_elmid child)
static void * start_response (void *userdata, const char *href)
static void * start_propstat (void *userdata, void *response)
static int startelm (void *userdata, const struct hip_xml_elm *elm, const char **atts)
static int endelm (void *userdata, const struct hip_xml_elm *elm, const char *cdata)
static void end_propstat (void *userdata, void *pstat_v, const char *status_line, const http_status *status, const char *description)
static void free_propset (dav_prop_result_set *set)
static void end_response (void *userdata, void *resource, const char *status_line, const http_status *status, const char *description)
dav_propfind_handler * dav_propfind_create (http_session *sess, const char *uri, int depth)
static struct hip_xml_elmmake_elms (const dav_propname *props)
static void free_elms (struct hip_xml_elm *elms)
void dav_propfind_destroy (dav_propfind_handler *handler)
int dav_simple_propfind (http_session *sess, const char *href, int depth, const dav_propname *props, dav_props_result results, void *userdata)
void dav_propfind_set_flat (dav_propfind_handler *hdl, const dav_propname *props)
void dav_propfind_set_complex (dav_propfind_handler *hdl, const dav_propname *props, dav_props_create_complex creator, void *userdata)

Variables

struct propstat propstat

Class Documentation

struct dav_propfind_handler_s

Definition at line 36 of file dav_props.c.

Collaboration diagram for dav_propfind_handler_s:
Class Members
sbuffer body
dav_props_result callback
dav_prop_result_set * current
int depth
struct hip_xml_elm * elms
int has_props
hip_xml_parser * parser
dav_207_parser * parser207
dav_props_create_complex private_creator
void * private_userdata
http_session * sess
const char * uri
void * userdata
struct prop

Definition at line 63 of file dav_props.c.

Collaboration diagram for prop:
Class Members
char * name
char * nspace
dav_propname pname
char * value
struct propstat

Definition at line 70 of file dav_props.c.

Collaboration diagram for propstat:
Class Members
int numprops
struct prop * props
http_status status
struct dav_prop_result_set_s

Definition at line 77 of file dav_props.c.

Collaboration diagram for dav_prop_result_set_s:
Class Members
char * href
int numpstats
void * private
struct propstat * pstats

Define Documentation

Definition at line 60 of file dav_props.c.


Function Documentation

static int check_context ( hip_xml_elmid  parent,
hip_xml_elmid  child 
) [static]

Definition at line 314 of file dav_props.c.

{
    if (child == ELM_namedprop && parent == DAV_ELM_prop)
       return HIP_XML_VALID;

    if (child == HIP_ELM_unknown && parent == DAV_ELM_prop)
       return HIP_XML_VALID;

    return HIP_XML_DECLINE;
}

Here is the caller graph for this function:

int dav_propfind_allprop ( dav_propfind_handler *  handler,
dav_props_result  results,
void *  userdata 
)

Definition at line 160 of file dav_props.c.

{
    sbuffer_zappend(handler->body, "<allprop/></propfind>" EOL);
    return propfind(handler, results, userdata);
}

Here is the call graph for this function:

dav_propfind_handler* dav_propfind_create ( http_session *  sess,
const char *  uri,
int  depth 
)

Definition at line 483 of file dav_props.c.

{
    dav_propfind_handler *ret = ne_calloc(sizeof(dav_propfind_handler));

    ret->parser = hip_xml_create();
    ret->parser207 = dav_207_create(ret->parser, ret);
    ret->uri = uri;
    ret->depth = depth;
    ret->sess = sess;
    ret->body = sbuffer_create();

    dav_207_set_response_handlers(ret->parser207, 
                              start_response, end_response);

    dav_207_set_propstat_handlers(ret->parser207, start_propstat,
                              end_propstat);

    /* The start of the request body is fixed: */
    sbuffer_concat(ret->body, 
                  "<?xml version=\"1.0\" encoding=\"utf-8\"?>" EOL 
                  "<propfind xmlns=\"DAV:\">", NULL);

    return ret;
}

Here is the call graph for this function:

void* dav_propfind_current_private ( dav_propfind_handler *  handler)

Definition at line 269 of file dav_props.c.

{
    return handler->current->private;
}
void dav_propfind_destroy ( dav_propfind_handler *  handler)

Definition at line 553 of file dav_props.c.

{
    dav_207_destroy(handler->parser207);
    hip_xml_destroy(handler->parser);
    if (handler->elms != NULL)
       free_elms(handler->elms);
    sbuffer_destroy(handler->body);
    free(handler);    
}

Here is the call graph for this function:

hip_xml_parser* dav_propfind_get_parser ( dav_propfind_handler *  handler)

Definition at line 84 of file dav_props.c.

{
    return handler->parser;
}
int dav_propfind_named ( dav_propfind_handler *  handler,
dav_props_result  results,
void *  userdata 
)

Definition at line 167 of file dav_props.c.

{
    sbuffer_zappend(handler->body, "</prop></propfind>" EOL);
    return propfind(handler, results, userdata);
}

Here is the call graph for this function:

void dav_propfind_set_complex ( dav_propfind_handler *  hdl,
const dav_propname props,
dav_props_create_complex  creator,
void *  userdata 
)

Definition at line 602 of file dav_props.c.

{
    set_body(hdl, props);
    hdl->private_creator = creator;
    hdl->private_userdata = userdata;
}

Here is the call graph for this function:

void dav_propfind_set_flat ( dav_propfind_handler *  hdl,
const dav_propname props 
)

Definition at line 588 of file dav_props.c.

{
    set_body(hdl, props);

    /* Register our special flat-property handler, which
     * is used for every flat property that they just passed.
     */
    
    hdl->elms = make_elms(props);
    hip_xml_push_handler(hdl->parser, hdl->elms, 
                      check_context, startelm, endelm, hdl);
}

Here is the call graph for this function:

int dav_proppatch ( http_session *  sess,
const char *  uri,
const dav_proppatch_operation items 
)

Definition at line 176 of file dav_props.c.

{
    http_req *req = http_request_create(sess, "PROPPATCH", uri);
    sbuffer body = sbuffer_create();
    char *utf8body;
    int n, ret;
    
    /* Create the request body */
    sbuffer_zappend(body, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" EOL
                   "<propertyupdate xmlns=\"DAV:\">");

    for (n = 0; items[n].name != NULL; n++) {
       switch (items[n].type) {
       case dav_propset:
           /* <set><prop><prop-name>value</prop-name></prop></set> */
           sbuffer_concat(body, "<set><prop>"
                        "<", items[n].name->name, " xmlns=\"",
                        items[n].name->nspace, "\">", items[n].value,
                        "</", items[n].name->name, "></prop></set>" EOL, 
                        NULL);
           break;

       case dav_propremove:
           /* <remove><prop><prop-name/></prop></remove> */
           sbuffer_concat(body, 
                        "<remove><prop><", items[n].name->name, " xmlns=\"",
                        items[n].name->nspace, "\"/></prop></remove>" EOL, 
                        NULL);
           break;
       }
    }  

    sbuffer_zappend(body, "</propertyupdate>" EOL);
    
    utf8body = ne_utf8_encode(sbuffer_data(body));

    http_set_request_body_buffer(req, utf8body);
    http_add_request_header(req, "Content-Type", "text/xml"); /* TODO: UTF-8? */
    
    ret = dav_simple_request(sess, req);
    
    sbuffer_destroy(body);
    free(utf8body);

    return ret;
}
int dav_propset_iterate ( const dav_prop_result_set *  set,
dav_propset_iterator  iterator,
void *  userdata 
)

Definition at line 279 of file dav_props.c.

{
    int ps, p;

    for (ps = 0; ps < set->numpstats; ps++) {
       for (p = 0; p < set->pstats[ps].numprops; p++) {
           struct prop *prop = &set->pstats[ps].props[p];
           int ret = iterator(userdata, &prop->pname, prop->value, 
                            &set->pstats[ps].status);
           if (ret)
              return ret;

       }
    }

    return 0;
}
void* dav_propset_private ( const dav_prop_result_set *  set)

Definition at line 274 of file dav_props.c.

{
    return set->private;
}
const http_status* dav_propset_status ( const dav_prop_result_set *  set,
const dav_propname pname 
)

Definition at line 298 of file dav_props.c.

{
    struct propstat *pstat;
    
    if (findprop(set, pname, &pstat, NULL)) {
       /* TODO: it is tempting to return a dummy status object here
        * rather than NULL, which says "Property result was not given
        * by server."  but I'm not sure if this is best left to the
        * client.  */
       return NULL;
    } else {
       return &pstat->status;
    }
}

Here is the call graph for this function:

const char* dav_propset_value ( const dav_prop_result_set *  set,
const dav_propname pname 
)

Definition at line 257 of file dav_props.c.

{
    struct prop *prop;
    
    if (findprop(set, pname, NULL, &prop)) {
       return NULL;
    } else {
       return prop->value;
    }
}

Here is the call graph for this function:

int dav_simple_propfind ( http_session *  sess,
const char *  href,
int  depth,
const dav_propname props,
dav_props_result  results,
void *  userdata 
)

Definition at line 563 of file dav_props.c.

{
    dav_propfind_handler *hdl;
    int ret;

    hdl = dav_propfind_create(sess, href, depth);
    if (props != NULL) {
       /* Named. */
       dav_propfind_set_flat(hdl, props);
       ret = dav_propfind_named(hdl, results, userdata);
    } else {
       /* Allprop: register the catch-all-props handler. */
       hdl->elms = make_elms(NULL);
       hip_xml_push_handler(hdl->parser, hdl->elms, 
                          check_context, startelm, endelm, hdl);
       ret = dav_propfind_allprop(hdl, results, userdata);
    }
       
    dav_propfind_destroy(hdl);
    
    return ret;
}

Here is the call graph for this function:

static void end_propstat ( void *  userdata,
void *  pstat_v,
const char *  status_line,
const http_status status,
const char *  description 
) [static]

Definition at line 413 of file dav_props.c.

{
    struct propstat *pstat = pstat_v;

    /* If we get a non-2xx response back here, we wipe the value for
     * each of the properties in this propstat, so the caller knows to
     * look at the status instead. It's annoying, since for each prop
     * we will have done an unnecessary strdup("") above, but there is
     * no easy way round that given the fact that we don't know
     * whether we've got an error or not till after we get the
     * property element. */
    if (status->klass != 2) {
       int n;
       
       for (n = 0; n < pstat->numprops; n++) {
           free(pstat->props[n].value);
           pstat->props[n].value = NULL;
       }
    }

    pstat->status = *status;
}

Here is the caller graph for this function:

static void end_response ( void *  userdata,
void *  resource,
const char *  status_line,
const http_status status,
const char *  description 
) [static]

Definition at line 460 of file dav_props.c.

{
    dav_propfind_handler *handler = userdata;
    dav_prop_result_set *set = resource;
    
    /* TODO: Handle status here too? The status element is mandatory
     * inside each propstat, so, not much point probably. */

    /* Pass back the results for this resource. */
    if (handler->callback != NULL) {
       handler->callback(handler->userdata, set->href, set);
    }

    free(set->href);

    /* Clean up the propset tree we've just built. */
    free_propset(set);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int endelm ( void *  userdata,
const struct hip_xml_elm elm,
const char *  cdata 
) [static]

Definition at line 393 of file dav_props.c.

{
    dav_propfind_handler *hdl = userdata;
    struct propstat *pstat = dav_207_get_current_propstat(hdl->parser207);
    int n;

    if (pstat == NULL) {
       DEBUG(DEBUG_XML, "gp_endelm: No propstat found, or not my element.");
       return -1;
    }

    n = pstat->numprops - 1;

    DEBUG(DEBUG_XML, "Value of property #%d is %s\n", n, cdata);
    
    pstat->props[n].value = ne_strdup(cdata);

    return 0;
}

Here is the caller graph for this function:

static int findprop ( const dav_prop_result_set *  set,
const dav_propname pname,
struct propstat **  pstat_ret,
struct prop **  prop_ret 
) [static]

Definition at line 234 of file dav_props.c.

{
    
    int ps, p;

    for (ps = 0; ps < set->numpstats; ps++) {
       for (p = 0; p < set->pstats[ps].numprops; p++) {
           struct prop *prop = &set->pstats[ps].props[p];

           if (pnamecmp(&prop->pname, pname) == 0) {
              if (pstat_ret != NULL)
                  *pstat_ret = &set->pstats[ps];
              if (prop_ret != NULL)
                  *prop_ret = prop;
              return 0;
           }
       }
    }

    return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void free_elms ( struct hip_xml_elm elms) [static]

Definition at line 547 of file dav_props.c.

{
    free(elms);
}

Here is the caller graph for this function:

static void free_propset ( dav_prop_result_set *  set) [static]

Definition at line 439 of file dav_props.c.

{
    int n;
    
    for (n = 0; n < set->numpstats; n++) {
       int m;
       struct propstat *p = &set->pstats[n];

       for (m = 0; m < p->numprops; m++) {
           free(p->props[m].nspace);
           free(p->props[m].name);
           HTTP_FREE(p->props[m].value);
       }

       free(set->pstats[n].props);
    }

    free(set->pstats);
    free(set);        
}

Here is the caller graph for this function:

static struct hip_xml_elm* make_elms ( const dav_propname props) [static, read]

Definition at line 508 of file dav_props.c.

{
    int n;
    struct hip_xml_elm *elms;

    if (props == NULL) {
       /* Just collect unknown.  Note this is a collect, so they get
        * a noddy text representation of the XML back, which is
        * probably never actually useful. */

       DEBUG(DEBUG_XML, "using UNKNOWN element handler.\n");
       elms = ne_calloc(sizeof(*elms) * 2);
       
       elms[0].id = HIP_ELM_unknown;
       elms[0].flags = HIP_XML_COLLECT | HIP_XML_UTF8DECODE;

       return elms;

    } else {
       /* Count the properties */
       for (n = 0; props[n].name != NULL; n++) /* noop */;
       
       /* Allocate the array, enough for each */
       elms = ne_calloc(sizeof(*elms) * (n+1));
       
       /* Fill it in. Note that the elements all have the SAME
        * element ID, and we COLLECT inside them, since these
        * are flat properties. */
       for (n = 0; props[n].name != NULL; n++) {
           elms[n].nspace = props[n].nspace;
           elms[n].name = props[n].name;
           elms[n].id = ELM_namedprop;
           elms[n].flags = HIP_XML_COLLECT | HIP_XML_UTF8DECODE;
       }
    }
    
    return elms;
}

Here is the caller graph for this function:

static int pnamecmp ( const dav_propname pn1,
const dav_propname pn2 
) [static]

Definition at line 225 of file dav_props.c.

{
    return (strcasecmp(pn1->nspace, pn2->nspace) ||
           strcasecmp(pn1->name, pn2->name));
}

Here is the caller graph for this function:

static int propfind ( dav_propfind_handler *  handler,
dav_props_result  results,
void *  userdata 
) [static]

Definition at line 89 of file dav_props.c.

{
    int ret;
    http_req *req;

    /* Register the catch-all handler to ignore any cruft the
     * server returns. */
    dav_207_ignore_unknown(handler->parser207);
    
    req = http_request_create(handler->sess, "PROPFIND", handler->uri);

    handler->callback = results;
    handler->userdata = userdata;

    http_set_request_body_buffer(req, sbuffer_data(handler->body));

    http_add_request_header(req, "Content-Type", "text/xml"); /* TODO: UTF-8? */
    dav_add_depth_header(req, handler->depth);
    
    http_add_response_body_reader(req, dav_accept_207, hip_xml_parse_v, 
                              handler->parser);

    ret = http_request_dispatch(req);

    if (ret == HTTP_OK && http_get_status(req)->klass != 2) {
       ret = HTTP_ERROR;
    } else if (!hip_xml_valid(handler->parser)) {
       http_set_error(handler->sess, hip_xml_get_error(handler->parser));
       ret = HTTP_ERROR;
    }

    http_request_destroy(req);

    return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void set_body ( dav_propfind_handler *  hdl,
const dav_propname names 
) [static]

Definition at line 126 of file dav_props.c.

{
    sbuffer body = hdl->body;
    int n;
    
    if (!hdl->has_props) {
       sbuffer_zappend(body, "<prop>" EOL);
       hdl->has_props = 1;
    }

    for (n = 0; names[n].name != NULL; n++) {
       char *name, *nspace;
       
       /* TODO:
        * In retrospect it is probably Wrong to do UTF-8 encoding
        * here.  More likely, it should be an API requirement that
        * property names/values are UTF-8 encoded strings.
        * 
        * I'm not up on the issues and problems that need to be
        * solved in this arena, so someone who is please shout
        * at me and tell me I'm stupid: neon@webdav.org */

       name = ne_utf8_encode(names[n].name);
       nspace = ne_utf8_encode(names[n].nspace);

       sbuffer_concat(body, "<", names[n].name, " xmlns=\"", 
                     names[n].nspace, "\"/>" EOL, NULL);

       free(name);
       free(nspace);
    }

}

Here is the caller graph for this function:

static void* start_propstat ( void *  userdata,
void *  response 
) [static]

Definition at line 341 of file dav_props.c.

{
    dav_prop_result_set *set = response;
    int n;
    struct propstat *pstat;

    n = set->numpstats;
    set->pstats = realloc(set->pstats, sizeof(struct propstat) * (n+1));
    set->numpstats = n+1;

    pstat = &set->pstats[n];
    memset(pstat, 0, sizeof(*pstat));
    
    /* And return this as the new pstat. */
    return &set->pstats[n];
}

Here is the caller graph for this function:

static void* start_response ( void *  userdata,
const char *  href 
) [static]

Definition at line 325 of file dav_props.c.

{
    dav_prop_result_set *set = ne_calloc(sizeof(*set));
    dav_propfind_handler *hdl = userdata;

    set->href = ne_strdup(href);

    if (hdl->private_creator != NULL) {
       set->private = hdl->private_creator(hdl->private_userdata, href);
    }

    hdl->current = set;

    return set;
}

Here is the caller graph for this function:

static int startelm ( void *  userdata,
const struct hip_xml_elm elm,
const char **  atts 
) [static]

Definition at line 359 of file dav_props.c.

{
    dav_propfind_handler *hdl = userdata;
    struct propstat *pstat = dav_207_get_current_propstat(hdl->parser207);
    struct prop *prop;
    int n;

    /* Paranoia */
    if (pstat == NULL) {
       DEBUG(DEBUG_XML, "gp_startelm: No propstat found, or not my element.");
       return -1;
    }

    /* Add a property to this propstat */
    n = pstat->numprops;

    pstat->props = realloc(pstat->props, sizeof(struct prop) * (n + 1));
    pstat->numprops = n+1;

    /* Fill in the new property. */
    prop = &pstat->props[n];

    prop->pname.name = prop->name = ne_strdup(elm->name);
    prop->pname.nspace = prop->nspace = ne_strdup(elm->nspace);
    prop->value = NULL;

    DEBUG(DEBUG_XML, "Got property #%d: %s@@%s.\n", n, 
         prop->nspace, prop->name);

    return 0;
}

Here is the caller graph for this function:


Variable Documentation