--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/ctest.c Mon Apr 24 21:01:41 2023 +0200 @@ -0,0 +1,391 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2015 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <time.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ucx/string.h> +#include <ucx/buffer.h> +#include <ucx/utils.h> +#include <libxml/tree.h> +#include <curl/curl.h> + +#include <openssl/sha.h> +#include <openssl/hmac.h> +#include <openssl/evp.h> +#include <openssl/bio.h> +#include <openssl/buffer.h> +#include <openssl/rand.h> + +#include "utils.h" +#include "crypto.h" +#include "webdav.h" + +#define MACRO1337 1337L + +/* -------------------- This is a testing file. -------------------------- */ +/* +time_t util_parse_creationdate(char *str) { + // example: 2012-11-29T21:35:35Z + if(!str) { + return 0; + } + // TODO + return 0; +} +*/ +time_t util_parse_lastmodified(char *str) { + // example: Thu, 29 Nov 2012 21:35:35 GMT + if(!str) { + return 0; + } else { + return curl_getdate(str, NULL); + } +} + +int util_getboolean(char *v) { + if(v[0] == 'T' || v[0] == 't') { + return 1; + } + return 0; +} + +int util_strtoint(char *str, int64_t *value) { + char *end; + int64_t val = strtoll(str, &end, 0); + if(strlen(end) == 0) { + *value = val; + return 1; + } else { + return 0; + } +} + +char* util_url_path(char *url) { + char *path = NULL; + size_t len = strlen(url); + int slashcount = 0; + int slmax; + if(len > 7 && !strncasecmp(url, "http://", 7)) { + slmax = 3; + } else if(len > 8 && !strncasecmp(url, "https://", 8)) { + slmax = 3; + } else { + slmax = 1; + } + char c; + for(int i=0;i<len;i++) { + c = url[i]; + if(c == '/') { + slashcount++; + if(slashcount == slmax) { + path = url + i; + break; + } + } + } + return path; +} + +char* util_url_decode(DavSession *sn, char *url) { + char *unesc = curl_easy_unescape(sn->handle, url, strlen(url), NULL); + char *ret = strdup(unesc); + curl_free(unesc); + return ret; +} + +char* util_resource_name(char *url) { + int si = 0; + int osi = 0; + int i = 0; + int p = 0; + char c; + while((c = url[i]) != 0) { + if(c == '/') { + osi = si; + si = i; + p = 1; + } + i++; + } + + char *name = url + si + p; + if(name[0] == 0) { + name = url + osi + p; + if(name[0] == 0) { + return url; + } + } + + return name; +} + +int util_mkdir(char *path, mode_t mode) { +#ifdef _WIN32 + return mkdir(path); +#else + return mkdir(path, mode); +#endif +} + +char* util_concat_path(char *url_base, char *p) { + sstr_t base = sstr(url_base); + sstr_t path; + if(p) { + path = sstr(p); + } else { + path = sstrn("", 0); + } + + int add_separator = 0; + if(base.ptr[base.length-1] == '/') { + if(path.ptr[0] == '/') { + base.length--; + } + } else { + if(path.length == 0 || path.ptr[0] != '/') { + add_separator = 1; + } + } + + sstr_t url; + if(add_separator) { + url = sstrcat(3, base, sstr("/"), path); + } else { + url = sstrcat(2, base, path); + } + + return url.ptr; +} + +void util_set_url(DavSession *sn, char *href) { + sstr_t base = sstr(sn->base_url); + sstr_t href_str = sstr(href); + + char *base_path = util_url_path(sn->base_url); + base.length -= strlen(base_path); + + sstr_t url = sstrcat(2, base, href_str); + + curl_easy_setopt(sn->handle, CURLOPT_URL, url.ptr); + free(url.ptr); +} + +char* util_path_to_url(DavSession *sn, char *path) { + char *space = malloc(256); + UcxBuffer *url = ucx_buffer_new(space, 256, CX_BUFFER_AUTO_EXTEND); + + // add base url + ucx_buffer_write(sn->base_url, 1, strlen(sn->base_url), url); + // remove trailing slash + ucx_buffer_seek(url, -1, SEEK_CUR); + + sstr_t p = sstr(path); + ssize_t ntk = 0; + sstr_t *tks = sstrsplit(p, S("/"), &ntk); + + for(int i=0;i<ntk;i++) { + sstr_t node = tks[i]; + if(node.length > 0) { + char *esc = curl_easy_escape(sn->handle, node.ptr, node.length); + ucx_buffer_putc(url, '/'); + ucx_buffer_write(esc, 1, strlen(esc), url); + curl_free(esc); + } + free(node.ptr); + } + free(tks); + if(path[p.length-1] == '/') { + ucx_buffer_putc(url, '/'); + } + ucx_buffer_putc(url, 0); + + space = url->space; + ucx_buffer_free(url); + + return space; +} + +char* util_parent_path(char *path) { + char *name = util_resource_name(path); + size_t namelen = strlen(name); + size_t pathlen = strlen(path); + size_t parentlen = pathlen - namelen; + char *parent = malloc(parentlen + 1); + memcpy(parent, path, parentlen); + parent[parentlen] = '\0'; + return parent; +} + + +char* util_xml_get_text(xmlNode *elm) { + xmlNode *node = elm->children; + while(node) { + if(node->type == XML_TEXT_NODE) { + return (char*)node->content; + } + node = node->next; + } + return NULL; +} + + +char* util_base64decode(char *in) { + int len = 0; + return util_base64decode_len(in, &len); +} + +char* util_base64decode_len(char* in, int *outlen) { + size_t len = strlen(in); + char *out = calloc(1, len); + + BIO* b = BIO_new_mem_buf(in, len); + BIO *d = BIO_new(BIO_f_base64()); + BIO_set_flags(d, BIO_FLAGS_BASE64_NO_NL); + b = BIO_push(d, b); + + *outlen = BIO_read(b, out, len); + BIO_free_all(b); + + return out; +} + +char* util_base64encode(char *in, size_t len) { + BIO *b; + BIO *e; + BUF_MEM *mem; + + e = BIO_new(BIO_f_base64()); + b = BIO_new(BIO_s_mem()); + + e = BIO_push(e, b); + BIO_write(e, in, len); + BIO_flush(e); + + BIO_get_mem_ptr(e, &mem); + char *out = malloc(mem->length); + memcpy(out, mem->data, mem->length -1); + out[mem->length - 1] = '\0'; + + BIO_free_all(e); + + return out; +} + +char* util_encrypt_str(DavSession *sn, char *str, char *key) { + DavKey *k = dav_context_get_key(sn->context, key); + if(!k) { + // TODO: session error + return NULL; + } + + char *enc_str = aes_encrypt(str, k); + char *ret_str = dav_session_strdup(sn, enc_str); + free(enc_str); + return ret_str; +} + +/* commented out for testing reasons */ +/* +char* util_decrypt_str(DavSession *sn, char *str, char *key) { + DavKey *k = dav_context_get_key(sn->context, key); + if(!k) { + // TODO: session error + return NULL; + } + + char *dec_str = aes_decrypt(str, k); + char *ret_str = dav_session_strdup(sn, dec_str); + free(dec_str); + return ret_str; +} +*/ +char* util_random_str() { + unsigned char *str = malloc(25); + str[24] = '\0'; + + sstr_t t = S( + "01234567890" + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + const unsigned char *table = (const unsigned char*)t.ptr; + + RAND_pseudo_bytes(str, 24); + for(int i=0;i<24;i++) { + int c = str[i] % t.length; + str[i] = table[c]; + } + + return (char*)str; +} + +/* + * gets a substring from 0 to the appearance of the token + * tokens are separated by space + * sets sub to the substring and returns the remaining string + */ +sstr_t util_getsubstr_until_token(sstr_t str, sstr_t token, sstr_t *sub) { + int i; + int token_start = -1; + int token_end = -1; + for(i=0;i<=str.length;i++) { + int c; + if(i == str.length) { + c = ' '; + } else { + c = str.ptr[i]; + } + if(c < 33) { + if(token_start != -1) { + token_end = i; + size_t len = token_end - token_start; + sstr_t tk = sstrsubsl(str, token_start, len); + //printf("token: {%.*s}\n", token.length, token.ptr); + if(!sstrcmp(tk, token)) { + *sub = sstrtrim(sstrsubsl(str, 0, token_start)); + break; + } + token_start = -1; + token_end = -1; + } + } else { + if(token_start == -1) { + token_start = i; + } + } + } + + if(i < str.length) { + return sstrtrim(sstrsubs(str, i)); + } else { + str.ptr = NULL; + str.length = 0; + return str; + } +}