mirror of
https://github.com/nextcloud/desktop.git
synced 2025-10-26 11:17:43 +00:00
module: Start with some webdav code based on libneon.
This commit is contained in:
parent
f0f36120ad
commit
141a095d45
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2008 by Andreas Schneider <mail@cynapses.org>
|
||||
* Copyright (c) 2011 by Andreas Schneider <asn@cryptomilk.org>
|
||||
*
|
||||
* This program is free software = NULL, you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -21,20 +21,26 @@
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <neon/ne_basic.h>
|
||||
#include <neon/ne_socket.h>
|
||||
#include <neon/ne_session.h>
|
||||
#include <neon/ne_request.h>
|
||||
|
||||
#include "c_lib.h"
|
||||
#include "vio/csync_vio_module.h"
|
||||
#include "vio/csync_vio_file_stat.h"
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define DEBUG_DUMMY(x)
|
||||
#define DEBUG_WEBDAV(x)
|
||||
#else
|
||||
#define DEBUG_DUMMY(x) printf x
|
||||
#define DEBUG_WEBDAV(x) printf x
|
||||
#endif
|
||||
|
||||
struct dav_session {
|
||||
struct dav_session_s {
|
||||
ne_session *ctx;
|
||||
char *base_uri;
|
||||
char *user;
|
||||
@ -46,7 +52,104 @@ int _connected;
|
||||
|
||||
csync_vio_file_stat_t fs;
|
||||
|
||||
static int _dav_connect(const char *base_url) {
|
||||
static int ne_session_error_errno(ne_session *session)
|
||||
{
|
||||
const char *p = ne_get_error(session);
|
||||
char *q;
|
||||
int err;
|
||||
|
||||
err = strtol(p, &q, 10);
|
||||
if (p == q) {
|
||||
return EIO;
|
||||
}
|
||||
|
||||
switch(err) {
|
||||
case 200: /* OK */
|
||||
case 201: /* Created */
|
||||
case 202: /* Accepted */
|
||||
case 203: /* Non-Authoritative Information */
|
||||
case 204: /* No Content */
|
||||
case 205: /* Reset Content */
|
||||
case 207: /* Multi-Status */
|
||||
case 304: /* Not Modified */
|
||||
return 0;
|
||||
case 401: /* Unauthorized */
|
||||
case 402: /* Payment Required */
|
||||
case 407: /* Proxy Authentication Required */
|
||||
return EPERM;
|
||||
case 301: /* Moved Permanently */
|
||||
case 303: /* See Other */
|
||||
case 404: /* Not Found */
|
||||
case 410: /* Gone */
|
||||
return ENOENT;
|
||||
case 408: /* Request Timeout */
|
||||
case 504: /* Gateway Timeout */
|
||||
return EAGAIN;
|
||||
case 423: /* Locked */
|
||||
return EACCES;
|
||||
case 400: /* Bad Request */
|
||||
case 403: /* Forbidden */
|
||||
case 405: /* Method Not Allowed */
|
||||
case 409: /* Conflict */
|
||||
case 411: /* Length Required */
|
||||
case 412: /* Precondition Failed */
|
||||
case 414: /* Request-URI Too Long */
|
||||
case 415: /* Unsupported Media Type */
|
||||
case 424: /* Failed Dependency */
|
||||
case 501: /* Not Implemented */
|
||||
return EINVAL;
|
||||
case 413: /* Request Entity Too Large */
|
||||
case 507: /* Insufficient Storage */
|
||||
return ENOSPC;
|
||||
case 206: /* Partial Content */
|
||||
case 300: /* Multiple Choices */
|
||||
case 302: /* Found */
|
||||
case 305: /* Use Proxy */
|
||||
case 306: /* (Unused) */
|
||||
case 307: /* Temporary Redirect */
|
||||
case 406: /* Not Acceptable */
|
||||
case 416: /* Requested Range Not Satisfiable */
|
||||
case 417: /* Expectation Failed */
|
||||
case 422: /* Unprocessable Entity */
|
||||
case 500: /* Internal Server Error */
|
||||
case 502: /* Bad Gateway */
|
||||
case 503: /* Service Unavailable */
|
||||
case 505: /* HTTP Version Not Supported */
|
||||
return EIO;
|
||||
default:
|
||||
return EIO;
|
||||
}
|
||||
|
||||
return EIO;
|
||||
}
|
||||
|
||||
static int ne_error_to_errno(int ne_err)
|
||||
{
|
||||
switch (ne_err) {
|
||||
case NE_OK:
|
||||
case NE_ERROR:
|
||||
return 0;
|
||||
case NE_AUTH:
|
||||
case NE_PROXYAUTH:
|
||||
return EACCES;
|
||||
case NE_CONNECT:
|
||||
case NE_TIMEOUT:
|
||||
case NE_RETRY:
|
||||
return EAGAIN;
|
||||
case NE_FAILED:
|
||||
return EINVAL;
|
||||
case NE_REDIRECT:
|
||||
return ENOENT;
|
||||
case NE_LOOKUP:
|
||||
return EIO;
|
||||
default:
|
||||
return EIO;
|
||||
}
|
||||
|
||||
return EIO;
|
||||
}
|
||||
|
||||
static int ne_dav_connect(const char *base_url) {
|
||||
char *scheme = NULL;
|
||||
char *user = NULL;
|
||||
char *passwd = NULL;
|
||||
@ -61,7 +164,7 @@ static int _dav_connect(const char *base_url) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = c_parse_uri(uri, &scheme, &user, &passwd, &host, &port, &path);
|
||||
rc = c_parse_uri(base_url, &scheme, &user, &passwd, &host, &port, &path);
|
||||
if (rc < 0) {
|
||||
goto out;
|
||||
}
|
||||
@ -72,7 +175,7 @@ static int _dav_connect(const char *base_url) {
|
||||
}
|
||||
|
||||
if (uri.scheme == NULL) {
|
||||
uri.scheme = "http";
|
||||
uri.scheme = c_strdup("http");
|
||||
}
|
||||
|
||||
if (uri.port == 0) {
|
||||
@ -85,13 +188,13 @@ static int _dav_connect(const char *base_url) {
|
||||
}
|
||||
|
||||
dav_session.ctx = ne_session_create(uri.scheme, uri.host, uri.port);
|
||||
if (dav_session == NULL) {
|
||||
if (dav_session.ctx == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ne_set_read_timeout(dav_session.ctx, timeout);
|
||||
|
||||
ne_set_server_auth();
|
||||
/* ne_set_server_auth(); */
|
||||
|
||||
_connected = 1;
|
||||
rc = 0;
|
||||
@ -101,7 +204,6 @@ out:
|
||||
SAFE_FREE(passwd);
|
||||
SAFE_FREE(host);
|
||||
SAFE_FREE(path);
|
||||
SAFE_FREE(hash);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -110,46 +212,101 @@ out:
|
||||
* file functions
|
||||
*/
|
||||
|
||||
static csync_vio_method_handle_t *_open(const char *durl, int flags, mode_t mode) {
|
||||
csync_vio_method_handle_t *mh = NULL;
|
||||
static csync_vio_method_handle_t *_open(const char *durl,
|
||||
int flags,
|
||||
mode_t mode) {
|
||||
char *uri;
|
||||
ne_request *req;
|
||||
int put = 0;
|
||||
|
||||
(void) durl;
|
||||
(void) flags;
|
||||
(void) mode;
|
||||
(void) mode; /* unused */
|
||||
|
||||
return mh;
|
||||
uri = ne_path_escape(durl);
|
||||
if (uri == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (flags & O_WRONLY) {
|
||||
put = 1;
|
||||
}
|
||||
if (flags & O_RDWR) {
|
||||
put = 1;
|
||||
}
|
||||
if (flags & O_CREAT) {
|
||||
put = 1;
|
||||
}
|
||||
|
||||
/* FIXME */
|
||||
if (put) {
|
||||
req = ne_request_create(dav_session.ctx, "PUT", uri);
|
||||
} else {
|
||||
req = ne_request_create(dav_session.ctx, "GET", uri);
|
||||
}
|
||||
|
||||
return (csync_vio_method_handle_t *) req;
|
||||
}
|
||||
|
||||
static csync_vio_method_handle_t *_creat(const char *durl, mode_t mode) {
|
||||
(void) durl;
|
||||
(void) mode;
|
||||
|
||||
return &mh;
|
||||
return _open(durl, O_CREAT|O_WRONLY|O_TRUNC, mode);
|
||||
}
|
||||
|
||||
static int _close(csync_vio_method_handle_t *fhandle) {
|
||||
(void) fhandle;
|
||||
ne_request *req;
|
||||
|
||||
if (fhandle == NULL) {
|
||||
return -1;
|
||||
}
|
||||
req = (ne_request *)fhandle;
|
||||
|
||||
ne_request_destroy(req);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t _read(csync_vio_method_handle_t *fhandle, void *buf, size_t count) {
|
||||
(void) fhandle;
|
||||
(void) buf;
|
||||
(void) count;
|
||||
ne_request *req = (ne_request *)fhandle;
|
||||
const ne_status *const st = ne_get_status(req);
|
||||
ssize_t len;
|
||||
int rc;
|
||||
|
||||
/* GET request */
|
||||
return 0;
|
||||
rc = ne_begin_request(req);
|
||||
if (rc != NE_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
do {
|
||||
if (st->klass == 2) {
|
||||
rc = NE_OK;
|
||||
len = ne_read_response_block(req, buf, count);
|
||||
if (len < 0) {
|
||||
rc = NE_ERROR;
|
||||
}
|
||||
} else {
|
||||
rc = ne_discard_response(req);
|
||||
len = -1;
|
||||
}
|
||||
} while(rc == NE_RETRY);
|
||||
|
||||
if (rc == NE_OK) {
|
||||
rc = ne_end_request(req);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t _write(csync_vio_method_handle_t *fhandle, const void *buf, size_t count) {
|
||||
(void) fhandle;
|
||||
(void) buf;
|
||||
(void) count;
|
||||
ne_request *req = (ne_request *)fhandle;
|
||||
ssize_t len = count;
|
||||
int rc;
|
||||
|
||||
/* put request */
|
||||
ne_set_request_body_buffer(req, buf, count);
|
||||
|
||||
return 0;
|
||||
rc = ne_request_dispatch(req);
|
||||
if (rc == NE_OK && ne_get_status(req)->klass != 2) {
|
||||
len = -1;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static off_t _lseek(csync_vio_method_handle_t *fhandle, off_t offset, int whence) {
|
||||
@ -157,7 +314,7 @@ static off_t _lseek(csync_vio_method_handle_t *fhandle, off_t offset, int whence
|
||||
(void) offset;
|
||||
(void) whence;
|
||||
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -167,7 +324,7 @@ static off_t _lseek(csync_vio_method_handle_t *fhandle, off_t offset, int whence
|
||||
static csync_vio_method_handle_t *_opendir(const char *name) {
|
||||
(void) name;
|
||||
|
||||
return &mh;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int _closedir(csync_vio_method_handle_t *dhandle) {
|
||||
@ -183,14 +340,51 @@ static csync_vio_file_stat_t *_readdir(csync_vio_method_handle_t *dhandle) {
|
||||
}
|
||||
|
||||
static int _mkdir(const char *uri, mode_t mode) {
|
||||
(void) uri;
|
||||
(void) mode;
|
||||
char *suri;
|
||||
int rc;
|
||||
|
||||
(void) mode; /* unused */
|
||||
|
||||
suri = ne_path_escape(uri);
|
||||
if (suri == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = ne_dav_connect(suri);
|
||||
if (rc < 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = ne_mkcol(dav_session.ctx, suri);
|
||||
if (rc != 0) {
|
||||
errno = ne_error_to_errno(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _rmdir(const char *uri) {
|
||||
(void) uri;
|
||||
char *suri;
|
||||
int rc;
|
||||
|
||||
suri = ne_path_escape(uri);
|
||||
if (suri == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = ne_dav_connect(suri);
|
||||
if (rc < 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = ne_delete(dav_session.ctx, uri);
|
||||
if (rc != 0) {
|
||||
errno = ne_error_to_errno(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -198,6 +392,12 @@ static int _rmdir(const char *uri) {
|
||||
static int _stat(const char *uri, csync_vio_file_stat_t *buf) {
|
||||
time_t now;
|
||||
|
||||
/* get props:
|
||||
* modtime
|
||||
* creattime
|
||||
* size
|
||||
*/
|
||||
|
||||
buf->name = c_basename(uri);
|
||||
if (buf->name == NULL) {
|
||||
csync_vio_file_stat_destroy(buf);
|
||||
@ -212,14 +412,55 @@ static int _stat(const char *uri, csync_vio_file_stat_t *buf) {
|
||||
}
|
||||
|
||||
static int _rename(const char *olduri, const char *newuri) {
|
||||
(void) olduri;
|
||||
(void) newuri;
|
||||
char *ouri;
|
||||
char *nuri;
|
||||
int rc;
|
||||
|
||||
ouri = ne_path_escape(olduri);
|
||||
if (ouri == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
nuri = ne_path_escape(newuri);
|
||||
if (nuri == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = ne_dav_connect(ouri);
|
||||
if (rc < 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = ne_move(dav_session.ctx, 1, ouri, nuri);
|
||||
if (rc != 0) {
|
||||
errno = ne_error_to_errno(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _unlink(const char *uri) {
|
||||
(void) uri;
|
||||
char *suri;
|
||||
int rc;
|
||||
|
||||
suri = ne_path_escape(uri);
|
||||
if (suri == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = ne_dav_connect(suri);
|
||||
if (rc < 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = ne_delete(dav_session.ctx, uri);
|
||||
if (rc != 0) {
|
||||
errno = ne_error_to_errno(rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -269,16 +510,14 @@ csync_vio_method_t _method = {
|
||||
|
||||
csync_vio_method_t *vio_module_init(const char *method_name, const char *args,
|
||||
csync_auth_callback cb, void *userdata) {
|
||||
DEBUG_DUMMY(("csync_dummy - method_name: %s\n", method_name));
|
||||
DEBUG_DUMMY(("csync_dummy - args: %s\n", args));
|
||||
DEBUG_WEBDAV(("csync_webdav - method_name: %s\n", method_name));
|
||||
DEBUG_WEBDAV(("csync_webdav - args: %s\n", args));
|
||||
|
||||
(void) method_name;
|
||||
(void) args;
|
||||
(void) cb;
|
||||
(void) userdata;
|
||||
|
||||
mh = (void *) method_name;
|
||||
fs.mtime = 42;
|
||||
|
||||
return &_method;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user