Back to index

avfs  1.0.1
Classes | Functions
dav_basic.c File Reference
#include "config.h"
#include "http_request.h"
#include "dav_basic.h"
#include "uri.h"
#include "http_basic.h"
#include "string_utils.h"
#include "dav_207.h"
#include "ne_alloc.h"

Go to the source code of this file.

Classes

struct  context

Functions

static void * start_response (void *userdata, const char *href)
static void handle_error (struct context *ctx, const char *status_line, const http_status *status, const char *description)
static void end_response (void *userdata, void *response, const char *status_line, const http_status *status, const char *description)
static void end_propstat (void *userdata, void *propstat, const char *status_line, const http_status *status, const char *description)
void dav_add_depth_header (http_req *req, int depth)
int dav_simple_request (http_session *sess, http_req *req)
static int copy_or_move (http_session *sess, int is_move, int overwrite, const char *src, const char *dest)
int dav_copy (http_session *sess, int overwrite, const char *src, const char *dest)
int dav_move (http_session *sess, int overwrite, const char *src, const char *dest)
int dav_delete (http_session *sess, const char *uri)
int dav_mkcol (http_session *sess, const char *uri)

Class Documentation

struct context

Definition at line 53 of file dav_basic.c.

Collaboration diagram for context:
Class Members
sbuffer buf
char * href
unsigned int is_error

Function Documentation

static int copy_or_move ( http_session *  sess,
int  is_move,
int  overwrite,
const char *  src,
const char *  dest 
) [static]

Definition at line 171 of file dav_basic.c.

{
    http_req *req = http_request_create( sess, is_move?"MOVE":"COPY", src );

#ifdef USE_DAV_LOCKS
    if (is_move) {
       dav_lock_using_resource(req, src, DAV_DEPTH_INFINITE);
    }
    dav_lock_using_resource(req, dest, DAV_DEPTH_INFINITE);
    /* And we need to be able to add members to the destination's parent */
    dav_lock_using_parent(req, dest);
#endif

    http_print_request_header(req, "Destination", "%s://%s%s", 
                           http_get_scheme(sess), 
                           http_get_server_hostport(sess), dest);
    
    http_add_request_header(req, "Overwrite", overwrite?"T":"F");

    return dav_simple_request(sess, req);
}

Here is the caller graph for this function:

void dav_add_depth_header ( http_req *  req,
int  depth 
)

Definition at line 100 of file dav_basic.c.

{
    const char *value;
    switch(depth) {
    case DAV_DEPTH_ZERO:
       value = "0";
       break;
    case DAV_DEPTH_ONE:
       value = "1";
       break;
    default:
       value = "infinity";
       break;
    }
    http_add_request_header(req, "Depth", value);
}
int dav_copy ( http_session *  sess,
int  overwrite,
const char *  src,
const char *  dest 
)

Definition at line 194 of file dav_basic.c.

{
    return copy_or_move(sess, 0, overwrite, src, dest);
}

Here is the call graph for this function:

int dav_delete ( http_session *  sess,
const char *  uri 
)

Definition at line 207 of file dav_basic.c.

{
    http_req *req = http_request_create(sess, "DELETE", uri);

#ifdef USE_DAV_LOCKS
    dav_lock_using_resource(req, uri, DAV_DEPTH_INFINITE);
    dav_lock_using_parent(req, uri);
#endif
    
    /* joe: I asked on the DAV WG list about whether we might get a
     * 207 error back from a DELETE... conclusion, you shouldn't if
     * you don't send the Depth header, since we might be an HTTP/1.1
     * client and a 2xx response indicates success to them.  But
     * it's all a bit unclear. In any case, DAV servers today do
     * return 207 to DELETE even if we don't send the Depth header.
     * So we handle 207 errors appropriately. */

    return dav_simple_request(sess, req);
}
int dav_mkcol ( http_session *  sess,
const char *  uri 
)

Definition at line 227 of file dav_basic.c.

{
    http_req *req;
    char *real_uri;
    int ret;

    if (uri_has_trailing_slash(uri)) {
       real_uri = ne_strdup(uri);
    } else {
       CONCAT2(real_uri, uri, "/");
    }

    req = http_request_create(sess, "MKCOL", real_uri);

#ifdef USE_DAV_LOCKS
    dav_lock_using_resource(req, real_uri, 0);
    dav_lock_using_parent(req, real_uri);
#endif
    
    ret = dav_simple_request(sess, req);

    free(real_uri);

    return ret;
}
int dav_move ( http_session *  sess,
int  overwrite,
const char *  src,
const char *  dest 
)

Definition at line 200 of file dav_basic.c.

{
    return copy_or_move(sess, 1, overwrite, src, dest);
}

Here is the call graph for this function:

int dav_simple_request ( http_session *  sess,
http_req *  req 
)

Definition at line 118 of file dav_basic.c.

{
    int ret;
    http_content_type ctype = {0};
    struct context ctx = {0};
    dav_207_parser *p207;
    hip_xml_parser *p;
    
    p = hip_xml_create();
    p207 = dav_207_create(p, &ctx);
    /* The error string is progressively written into the
     * sbuffer by the element callbacks */
    ctx.buf = sbuffer_create();

    dav_207_set_response_handlers(p207, start_response, end_response);
    dav_207_set_propstat_handlers(p207, NULL, end_propstat);
    
    http_add_response_body_reader(req, dav_accept_207, hip_xml_parse_v, p);
    http_add_response_header_handler(req, "Content-Type", 
                                  http_content_type_handler, &ctype);

    dav_207_ignore_unknown(p207);

    ret = http_request_dispatch(req);

    if (ret == HTTP_OK) {
       if (http_get_status(req)->code == 207) {
           if (!hip_xml_valid(p)) { 
              /* The parse was invalid */
              http_set_error(sess, hip_xml_get_error(p));
              ret = HTTP_ERROR;
           } else if (ctx.is_error) {
              /* If we've actually got any error information
               * from the 207, then set that as the error */
              http_set_error(sess, sbuffer_data(ctx.buf));
              ret = HTTP_ERROR;
           }
       } else if (http_get_status(req)->klass != 2) {
           ret = HTTP_ERROR;
       }
    }

    HTTP_FREE(ctype.value);
    dav_207_destroy(p207);
    hip_xml_destroy(p);
    sbuffer_destroy(ctx.buf);
    HTTP_FREE(ctx.href);

    http_request_destroy(req);

    return ret;
}

Here is the call graph for this function:

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

Definition at line 93 of file dav_basic.c.

{
    struct context *ctx = userdata;
    handle_error(ctx, status_line, status, description);
}

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 85 of file dav_basic.c.

{
    struct context *ctx = userdata;
    handle_error(ctx, status_line, status, description);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void handle_error ( struct context ctx,
const char *  status_line,
const http_status status,
const char *  description 
) [static]

Definition at line 67 of file dav_basic.c.

{
    if (status && status->klass != 2) {
       if (status->code != 424) {
           ctx->is_error = 1;
           sbuffer_concat(ctx->buf, ctx->href, ": ", status_line, "\n", NULL);
           if (description != NULL) {
              /* TODO: these can be multi-line. Would be good to
               * word-wrap this at col 80. */
              sbuffer_concat(ctx->buf, " -> ", description, "\n", NULL);
           }
       }
    }

}

Here is the caller graph for this function:

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

Definition at line 59 of file dav_basic.c.

{
    struct context *ctx = userdata;
    HTTP_FREE(ctx->href);
    ctx->href = ne_strdup(href);
    return NULL;
}

Here is the caller graph for this function: