# HG changeset patch # User Olaf Wintermann # Date 1552477944 -3600 # Node ID da2b0cc44e4fc6fa4794fb711875c19aa58db787 # Parent ac5ac55b1b2ed7ec7bda2841947388823034bd42 adds xml attribute support and xattr property diff -r ac5ac55b1b2e -r da2b0cc44e4f dav/finfo.c --- a/dav/finfo.c Tue Mar 12 09:35:04 2019 +0100 +++ b/dav/finfo.c Wed Mar 13 12:52:24 2019 +0100 @@ -30,10 +30,15 @@ #include #include +#include #include #include #include +#include +#include + +#include "libxattr.h" uint32_t parse_finfo(const char *str) { scstr_t s = scstr(str); @@ -54,6 +59,8 @@ finfo |= FINFO_OWNER; } else if(!sstrcasecmp(f, SC("mode"))) { finfo |= FINFO_MODE; + } else if(!sstrcasecmp(f, SC("xattr"))) { + finfo |= FINFO_XATTR; } free(f.ptr); } @@ -114,3 +121,79 @@ return 0; } + +XAttributes* file_get_attributes(const char *path) { + ssize_t nelm = 0; + char **attributes = xattr_list(path, &nelm); + if(nelm <= 0) { + return NULL; + } + + XAttributes *xattr = malloc(sizeof(XAttributes)); + xattr->nattr = 0; + xattr->names = calloc(nelm, sizeof(char*)); + xattr->values = calloc(nelm, sizeof(sstr_t)); + + DAV_SHA_CTX *sha256 = dav_hash_init(); + + size_t nattr = 0; + for(int i=0;i= 0) { + dav_hash_update(sha256, attributes[i], strlen(attributes[i])); + dav_hash_update(sha256, value, valuelen); + // add name and value + xattr->names[nattr] = attributes[i]; + sstr_t v; + v.ptr = value; + v.length = valuelen; + xattr->values[nattr] = v; + nattr++; + } else { + // discard not readable attributes + free(attributes[i]); + } + } + + xattr->nattr = nattr; + + unsigned char hash[DAV_SHA256_DIGEST_LENGTH]; + dav_hash_final(sha256, hash); + xattr->hash = util_hexstr(hash, DAV_SHA256_DIGEST_LENGTH); + + free(attributes); + + return xattr; +} + +int resource_set_xattr(DavResource *res, XAttributes *xattr) { + if(!xattr || xattr->nattr == 0) { + return 0; + } + + DavXmlNode *content = dav_xml_createnode_with_text(DAV_NS, "hash", xattr->hash); + DavXmlNode *last = content; + + for(int i=0;inattr;i++) { + DavXmlNode *attr = dav_xml_createnode(DAV_NS, "xattr"); + dav_xml_add_attr(attr, "name", xattr->names[i]); + last->next = attr; + last = attr; + + sstr_t value = xattr->values[i]; + if(value.length > 0) { + char *encval = util_base64encode(value.ptr, value.length); + attr->children = dav_xml_createtextnode(encval); + free(encval); + } + } + + dav_set_property(res, "idav:xattributes", content); + + return 0; +} + +void xattributes_free(XAttributes *xattr) { + +} diff -r ac5ac55b1b2e -r da2b0cc44e4f dav/finfo.h --- a/dav/finfo.h Tue Mar 12 09:35:04 2019 +0100 +++ b/dav/finfo.h Wed Mar 13 12:52:24 2019 +0100 @@ -40,12 +40,23 @@ #define FINFO_DATE 1 #define FINFO_OWNER 2 #define FINFO_MODE 4 +#define FINFO_XATTR 8 + +typedef struct XAttributes { + size_t nattr; + char **names; + sstr_t *values; + char *hash; +} XAttributes; uint32_t parse_finfo(const char *str); int resource_set_finfo(const char *path, DavResource *res, uint32_t finfo); int resource_set_finfo_s(struct stat *s, DavResource *res, uint32_t finfo); +XAttributes* file_get_attributes(const char *path); +int resource_set_xattr(DavResource *res, XAttributes *xattr); +void xattributes_free(XAttributes *xattr); #ifdef __cplusplus } diff -r ac5ac55b1b2e -r da2b0cc44e4f dav/main.c --- a/dav/main.c Tue Mar 12 09:35:04 2019 +0100 +++ b/dav/main.c Wed Mar 13 12:52:24 2019 +0100 @@ -1524,6 +1524,12 @@ if(resource_set_finfo(fpath, res, finfo)) { fprintf(stderr, "Cannot set finfo: %s.\n", strerror(errno)); } + if(finfo & FINFO_XATTR == FINFO_XATTR) { + XAttributes *xattr = file_get_attributes(fpath); + if(xattr) { + resource_set_xattr(res, xattr); + } + } dav_set_content(res, in, (dav_read_func)fread, (dav_seek_func)file_seek); if(len > 0 && len < 0x7d000000) { diff -r ac5ac55b1b2e -r da2b0cc44e4f libidav/crypto.c --- a/libidav/crypto.c Tue Mar 12 09:35:04 2019 +0100 +++ b/libidav/crypto.c Wed Mar 13 12:52:24 2019 +0100 @@ -359,6 +359,21 @@ return util_hexstr(hash, DAV_SHA256_DIGEST_LENGTH); } +DAV_SHA_CTX* dav_hash_init(void) { + DAV_SHA_CTX *ctx = malloc(sizeof(DAV_SHA_CTX)); + SHA256_Init(ctx); + return ctx; +} + +void dav_hash_update(DAV_SHA_CTX *ctx, const char *data, size_t len) { + SHA256_Update(ctx, data, len); +} + +void dav_hash_final(DAV_SHA_CTX *ctx, unsigned char *buf) { + SHA256_Final(buf, ctx); + free(ctx); +} + DavKey* dav_pw2key(const char *password, const unsigned char *salt, int saltlen, int pwfunc, int enc) { if(!password) { return NULL; @@ -779,6 +794,21 @@ return util_hexstr(hash, DAV_SHA256_DIGEST_LENGTH); } +DAV_SHA_CTX* dav_hash_init(void) { + DAV_SHA_CTX *ctx = malloc(sizeof(DAV_SHA_CTX)); + CC_SHA256_Init(ctx); + return ctx; +} + +void dav_hash_update(DAV_SHA_CTX *ctx, const char *data, size_t len) { + CC_SHA256_Update(ctx, data, len); +} + +void dav_hash_final(DAV_SHA_CTX *ctx, unsigned char *buf) { + CC_SHA256_Final(buf, ctx); + free(ctx); +} + DavKey* dav_pw2key(const char *password, const unsigned char *salt, int saltlen, int pwfunc, int enc) { if(!password) { return NULL; diff -r ac5ac55b1b2e -r da2b0cc44e4f libidav/crypto.h --- a/libidav/crypto.h Tue Mar 12 09:35:04 2019 +0100 +++ b/libidav/crypto.h Wed Mar 13 12:52:24 2019 +0100 @@ -97,6 +97,8 @@ int end; } AESEncrypter; +typedef struct DavHashContext DavHashContext; + int dav_rand_bytes(unsigned char *buf, size_t len); AESDecrypter* aes_decrypter_new(DavKey *key, void *stream, dav_write_func write_func); @@ -116,6 +118,10 @@ char* dav_create_hash(const char *data, size_t len); +DAV_SHA_CTX* dav_hash_init(void); +void dav_hash_update(DAV_SHA_CTX *ctx, const char *data, size_t len); +void dav_hash_final(DAV_SHA_CTX *ctx, unsigned char *buf); + DavKey* dav_pw2key(const char *password, const unsigned char *salt, int saltlen, int pwfunc, int enc); UcxBuffer* aes_encrypt_buffer(UcxBuffer *buf, DavKey *key); diff -r ac5ac55b1b2e -r da2b0cc44e4f libidav/webdav.h --- a/libidav/webdav.h Tue Mar 12 09:35:04 2019 +0100 +++ b/libidav/webdav.h Wed Mar 13 12:52:24 2019 +0100 @@ -59,6 +59,7 @@ typedef struct DavPropName DavPropName; typedef struct DavKey DavKey; typedef struct DavXmlNode DavXmlNode; +typedef struct DavXmlAttr DavXmlAttr; typedef size_t(*dav_read_func)(void*, size_t, size_t, void*); typedef size_t(*dav_write_func)(const void*, size_t, size_t, void*); @@ -206,12 +207,18 @@ DavXmlNode *children; DavXmlNode *parent; - // TODO: attributes + DavXmlAttr *attributes; char *content; size_t contentlength; }; +struct DavXmlAttr { + char *name; + char *value; + DavXmlAttr *next; +}; + DavContext* dav_context_new(); void dav_context_destroy(DavContext *ctx); @@ -333,6 +340,7 @@ DavXmlNode* dav_xml_createnode_with_text(const char *ns, const char *name, const char *text); DavXmlNode* dav_xml_createtextnode(const char *text); void dav_xml_add_child(DavXmlNode *node, DavXmlNode *child); +void dav_xml_add_attr(DavXmlNode *node, const char *name, const char *value); DavXmlNode* dav_parse_xml(DavSession *sn, const char *str, size_t len); diff -r ac5ac55b1b2e -r da2b0cc44e4f libidav/xml.c --- a/libidav/xml.c Tue Mar 12 09:35:04 2019 +0100 +++ b/libidav/xml.c Wed Mar 13 12:52:24 2019 +0100 @@ -94,7 +94,25 @@ newxn->namespace = dav_session_strdup(sn, (char*)n->ns->href); } - // TODO: copy attributes + xmlAttr *attr = n->properties; + DavXmlAttr *newattr = NULL; + DavXmlAttr *newattr_last = NULL; + while(attr) { + DavXmlAttr *na = ucx_mempool_calloc(mp, 1, sizeof(DavXmlAttr)); + na->name = dav_session_strdup(sn, (char*)attr->name); + if(attr->children && attr->children->type == XML_TEXT_NODE) { + na->value = dav_session_strdup(sn, (char*)attr->children->content); + } + if(!newattr) { + newattr = na; + } else { + newattr_last->next = na; + } + newattr_last = na; + + attr = attr->next; + } + newxn->attributes = newattr; if(n->children) { ConvXmlElm *convc = malloc(sizeof(ConvXmlElm)); @@ -120,7 +138,13 @@ void dav_print_xml(DavXmlNode *node) { if(node->type == DAV_XML_ELEMENT) { - printf("<%s>", node->name); + printf("<%s", node->name); + DavXmlAttr *attr = node->attributes; + while(attr) { + printf(" %s=\"%s\"", attr->name, attr->value); + attr = attr->next; + } + putchar('>'); DavXmlNode *child = node->children; if(child) { @@ -140,7 +164,7 @@ void dav_print_node(void *stream, write_func writef, UcxMap *nsmap, DavXmlNode *node) { while(node) { if(node->type == DAV_XML_ELEMENT) { - char *tagend = node->children ? ">" : " />"; + char *tagend = node->children ? ">" : " />"; char *prefix = NULL; if(node->namespace) { prefix = ucx_map_cstr_get(nsmap, node->namespace); @@ -158,12 +182,19 @@ node->namespace, tagend); } else { - ucx_fprintf(stream, writef, "<%s:%s%s", prefix, node->name, tagend); + ucx_fprintf(stream, writef, "<%s:%s", prefix, node->name); } } else { - ucx_fprintf(stream, writef, "<%s%s", node->name, tagend); + ucx_fprintf(stream, writef, "<%s", node->name); } + DavXmlAttr *attr = node->attributes; + while(attr) { + ucx_fprintf(stream, writef, " %s=\"%s\"", attr->name, attr->value); + attr = attr->next; + } + writef(tagend, 1, strlen(tagend), stream); // end xml tag + if(node->children) { dav_print_node(stream, writef, nsmap, node->children); if(prefix) { @@ -296,6 +327,24 @@ } } +void dav_xml_add_attr(DavXmlNode *node, const char *name, const char *value) { + DavXmlAttr *attr = calloc(1, sizeof(DavXmlAttr)); + attr->name = strdup(name); + attr->value = strdup(value); + + if(node->attributes) { + DavXmlAttr *last; + DavXmlAttr *end = node->attributes; + while(end) { + last = end; + end = end->next; + } + last->next = attr; + } else { + node->attributes = attr; + } +} + DavXmlNode* dav_parse_xml(DavSession *sn, const char *str, size_t len) { xmlDoc *doc = xmlReadMemory(str, len, NULL, NULL, 0); if(!doc) {