universe@41: universe@41: universe@41: universe@41: c2html universe@41: universe@41: universe@41: universe@41: universe@41:
universe@63:   1 /*
universe@63:   2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
universe@63:   3  *
universe@63:   4  * Copyright 2015 Olaf Wintermann. All rights reserved.
universe@63:   5  *
universe@63:   6  * Redistribution and use in source and binary forms, with or without
universe@63:   7  * modification, are permitted provided that the following conditions are met:
universe@63:   8  *
universe@63:   9  *   1. Redistributions of source code must retain the above copyright
universe@63:  10  *      notice, this list of conditions and the following disclaimer.
universe@63:  11  *
universe@63:  12  *   2. Redistributions in binary form must reproduce the above copyright
universe@63:  13  *      notice, this list of conditions and the following disclaimer in the
universe@63:  14  *      documentation and/or other materials provided with the distribution.
universe@63:  15  *
universe@63:  16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
universe@63:  17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
universe@63:  18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
universe@63:  19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
universe@63:  20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
universe@63:  21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
universe@63:  22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
universe@63:  23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
universe@63:  24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
universe@63:  25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
universe@63:  26  * POSSIBILITY OF SUCH DAMAGE.
universe@63:  27  */
universe@63:  28 
universe@63:  29 #include <time.h>
universe@63:  30 #include <stdio.h>
universe@63:  31 #include <stdlib.h>
universe@63:  32 #include <string.h>
universe@63:  33 #include <ucx/string.h>
universe@63:  34 #include <ucx/buffer.h>
universe@63:  35 #include <ucx/utils.h>
universe@63:  36 #include <libxml/tree.h>
universe@63:  37 #include <curl/curl.h>
universe@63:  38 
universe@63:  39 #include <openssl/sha.h>
universe@63:  40 #include <openssl/hmac.h>
universe@63:  41 #include <openssl/evp.h>
universe@63:  42 #include <openssl/bio.h>
universe@63:  43 #include <openssl/buffer.h>
universe@63:  44 #include <openssl/rand.h>
universe@63:  45 
universe@63:  46 #include "utils.h"
universe@63:  47 #include "crypto.h"
universe@63:  48 #include "webdav.h"
universe@63:  49 
universe@63:  50 #define MACRO1337 1337L
universe@63:  51 
universe@63:  52 /* -------------------- This is a testing file. -------------------------- */
universe@63:  53 /*
universe@63:  54 time_t util_parse_creationdate(char *str) {
universe@63:  55     // example: 2012-11-29T21:35:35Z
universe@63:  56     if(!str) {
universe@63:  57         return 0;
universe@63:  58     }
universe@63:  59     // TODO
universe@63:  60     return 0;
universe@63:  61 }
universe@63:  62 */
universe@63:  63 time_t util_parse_lastmodified(char *str) {
universe@63:  64     // example: Thu, 29 Nov 2012 21:35:35 GMT
universe@63:  65     if(!str) {
universe@63:  66         return 0;
universe@63:  67     } else {
universe@63:  68         return curl_getdate(str, NULL);
universe@63:  69     }
universe@63:  70 }
universe@63:  71 
universe@63:  72 int util_getboolean(char *v) {
universe@63:  73     if(v[0] == 'T' || v[0] == 't') {
universe@63:  74         return 1;
universe@63:  75     }
universe@63:  76     return 0;
universe@63:  77 }
universe@63:  78 
universe@63:  79 int util_strtoint(char *str, int64_t *value) {
universe@63:  80     char *end;
universe@63:  81     int64_t val = strtoll(str, &end, 0);
universe@63:  82     if(strlen(end) == 0) {
universe@63:  83         *value = val;
universe@63:  84         return 1;
universe@63:  85     } else {
universe@63:  86         return 0;
universe@63:  87     }
universe@63:  88 }
universe@63:  89 
universe@63:  90 char* util_url_path(char *url) { 
universe@63:  91     char *path = NULL;
universe@63:  92     size_t len = strlen(url);
universe@63:  93     int slashcount = 0;
universe@63:  94     int slmax;
universe@63:  95     if(len > 7 && !strncasecmp(url, "http://", 7)) {
universe@63:  96         slmax = 3;
universe@63:  97     } else if(len > 8 && !strncasecmp(url, "https://", 8)) {
universe@63:  98         slmax = 3;
universe@63:  99     } else {
universe@63: 100         slmax = 1;
universe@63: 101     }
universe@63: 102     char c;
universe@63: 103     for(int i=0;i<len;i++) {
universe@63: 104         c = url[i];
universe@63: 105         if(c == '/') {
universe@63: 106             slashcount++;
universe@63: 107             if(slashcount == slmax) {
universe@63: 108                 path = url + i;
universe@63: 109                 break;
universe@63: 110             }
universe@63: 111         }
universe@63: 112     } 
universe@63: 113     return path;
universe@63: 114 }
universe@63: 115 
universe@63: 116 char* util_url_decode(DavSession *sn, char *url) {
universe@63: 117     char *unesc = curl_easy_unescape(sn->handle, url, strlen(url), NULL);
universe@63: 118     char *ret = strdup(unesc);
universe@63: 119     curl_free(unesc);
universe@63: 120     return ret;
universe@63: 121 }
universe@63: 122 
universe@63: 123 char* util_resource_name(char *url) {
universe@63: 124     int si = 0;
universe@63: 125     int osi = 0;
universe@63: 126     int i = 0;
universe@63: 127     int p = 0;
universe@63: 128     char c;
universe@63: 129     while((c = url[i]) != 0) {
universe@63: 130         if(c == '/') {
universe@63: 131             osi = si;
universe@63: 132             si = i;
universe@63: 133             p = 1;
universe@63: 134         }
universe@63: 135         i++;
universe@63: 136     }
universe@63: 137     
universe@63: 138     char *name = url + si + p;
universe@63: 139     if(name[0] == 0) {
universe@63: 140         name = url + osi + p;
universe@63: 141         if(name[0] == 0) {
universe@63: 142             return url;
universe@63: 143         }
universe@63: 144     }
universe@63: 145     
universe@63: 146     return name;
universe@63: 147 }
universe@63: 148 
universe@63: 149 int util_mkdir(char *path, mode_t mode) {
universe@63: 150 #ifdef _WIN32
universe@63: 151     return mkdir(path);
universe@63: 152 #else
universe@63: 153     return mkdir(path, mode);
universe@63: 154 #endif
universe@63: 155 }
universe@63: 156 
universe@63: 157 char* util_concat_path(char *url_base, char *p) {
universe@63: 158     sstr_t base = sstr(url_base);
universe@63: 159     sstr_t path;
universe@63: 160     if(p) {
universe@63: 161         path = sstr(p);
universe@63: 162     } else {
universe@63: 163         path = sstrn("", 0);
universe@63: 164     }
universe@63: 165     
universe@63: 166     int add_separator = 0;
universe@63: 167     if(base.ptr[base.length-1] == '/') {
universe@63: 168         if(path.ptr[0] == '/') {
universe@63: 169             base.length--;
universe@63: 170         }
universe@63: 171     } else {
universe@63: 172         if(path.length == 0 || path.ptr[0] != '/') {
universe@63: 173             add_separator = 1;
universe@63: 174         }
universe@63: 175     }
universe@63: 176     
universe@63: 177     sstr_t url;
universe@63: 178     if(add_separator) {
universe@63: 179         url = sstrcat(3, base, sstr("/"), path);
universe@63: 180     } else {
universe@63: 181         url = sstrcat(2, base, path);
universe@63: 182     }
universe@63: 183     
universe@63: 184     return url.ptr;
universe@63: 185 }
universe@63: 186 
universe@63: 187 void util_set_url(DavSession *sn, char *href) {
universe@63: 188     sstr_t base = sstr(sn->base_url);
universe@63: 189     sstr_t href_str = sstr(href);
universe@63: 190     
universe@63: 191     char *base_path = util_url_path(sn->base_url);
universe@63: 192     base.length -= strlen(base_path);
universe@63: 193     
universe@63: 194     sstr_t url = sstrcat(2, base, href_str);
universe@63: 195     
universe@63: 196     curl_easy_setopt(sn->handle, CURLOPT_URL, url.ptr);
universe@63: 197     free(url.ptr);
universe@63: 198 }
universe@63: 199 
universe@63: 200 char* util_path_to_url(DavSession *sn, char *path) {
universe@63: 201     char *space = malloc(256);
universe@63: 202     UcxBuffer *url = ucx_buffer_new(space, 256, UCX_BUFFER_AUTOEXTEND);
universe@63: 203     
universe@63: 204     // add base url
universe@63: 205     ucx_buffer_write(sn->base_url, 1, strlen(sn->base_url), url);
universe@63: 206     // remove trailing slash
universe@63: 207     ucx_buffer_seek(url, -1, SEEK_CUR);
universe@63: 208     
universe@63: 209     sstr_t p = sstr(path);
universe@63: 210     ssize_t ntk = 0;
universe@63: 211     sstr_t *tks = sstrsplit(p, S("/"), &ntk);
universe@63: 212     
universe@63: 213     for(int i=0;i<ntk;i++) {
universe@63: 214         sstr_t node = tks[i];
universe@63: 215         if(node.length > 0) {
universe@63: 216             char *esc = curl_easy_escape(sn->handle, node.ptr, node.length);
universe@63: 217             ucx_buffer_putc(url, '/');
universe@63: 218             ucx_buffer_write(esc, 1, strlen(esc), url);
universe@63: 219             curl_free(esc);
universe@63: 220         }
universe@63: 221         free(node.ptr);
universe@63: 222     }
universe@63: 223     free(tks);
universe@63: 224     if(path[p.length-1] == '/') {
universe@63: 225         ucx_buffer_putc(url, '/');
universe@63: 226     }
universe@63: 227     ucx_buffer_putc(url, 0);
universe@63: 228     
universe@63: 229     space = url->space;
universe@63: 230     ucx_buffer_free(url);
universe@63: 231     
universe@63: 232     return space;
universe@63: 233 }
universe@63: 234 
universe@63: 235 char* util_parent_path(char *path) {
universe@63: 236     char *name = util_resource_name(path);
universe@63: 237     size_t namelen = strlen(name);
universe@63: 238     size_t pathlen = strlen(path);
universe@63: 239     size_t parentlen = pathlen - namelen;
universe@63: 240     char *parent = malloc(parentlen + 1);
universe@63: 241     memcpy(parent, path, parentlen);
universe@63: 242     parent[parentlen] = '\0';
universe@63: 243     return parent;
universe@63: 244 }
universe@63: 245 
universe@63: 246 
universe@63: 247 char* util_xml_get_text(xmlNode *elm) {
universe@63: 248     xmlNode *node = elm->children;
universe@63: 249     while(node) {
universe@63: 250         if(node->type == XML_TEXT_NODE) {
universe@63: 251             return (char*)node->content;
universe@63: 252         }
universe@63: 253         node = node->next;
universe@63: 254     }
universe@63: 255     return NULL;
universe@63: 256 }
universe@63: 257 
universe@63: 258 
universe@63: 259 char* util_base64decode(char *in) {
universe@63: 260     int len = 0;
universe@63: 261     return util_base64decode_len(in, &len);
universe@63: 262 }
universe@63: 263 
universe@63: 264 char* util_base64decode_len(char* in, int *outlen) {
universe@63: 265     size_t len = strlen(in);
universe@63: 266     char *out = calloc(1, len);
universe@63: 267     
universe@63: 268     BIO* b = BIO_new_mem_buf(in, len);
universe@63: 269     BIO *d = BIO_new(BIO_f_base64());
universe@63: 270     BIO_set_flags(d, BIO_FLAGS_BASE64_NO_NL);
universe@63: 271     b = BIO_push(d, b);
universe@63: 272 
universe@63: 273     *outlen = BIO_read(b, out, len);
universe@63: 274     BIO_free_all(b);
universe@63: 275     
universe@63: 276     return out;
universe@63: 277 }
universe@63: 278 
universe@63: 279 char* util_base64encode(char *in, size_t len) { 
universe@63: 280     BIO *b;
universe@63: 281     BIO *e;
universe@63: 282     BUF_MEM *mem;
universe@63: 283 
universe@63: 284     e = BIO_new(BIO_f_base64());
universe@63: 285     b = BIO_new(BIO_s_mem());
universe@63: 286     
universe@63: 287     e = BIO_push(e, b);
universe@63: 288     BIO_write(e, in, len);
universe@63: 289     BIO_flush(e);
universe@63: 290     
universe@63: 291     BIO_get_mem_ptr(e, &mem);
universe@63: 292     char *out = malloc(mem->length);
universe@63: 293     memcpy(out, mem->data, mem->length -1);
universe@63: 294     out[mem->length - 1] = '\0';
universe@63: 295 
universe@63: 296     BIO_free_all(e);
universe@63: 297 
universe@63: 298     return out;
universe@63: 299 }
universe@63: 300 
universe@63: 301 char* util_encrypt_str(DavSession *sn, char *str, char *key) {
universe@63: 302     DavKey *k = dav_context_get_key(sn->context, key);
universe@63: 303     if(!k) {
universe@63: 304         // TODO: session error
universe@63: 305         return NULL;
universe@63: 306     }
universe@63: 307     
universe@63: 308     char *enc_str = aes_encrypt(str, k);
universe@63: 309     char *ret_str = dav_session_strdup(sn, enc_str);
universe@63: 310     free(enc_str);
universe@63: 311     return ret_str;
universe@63: 312 }
universe@63: 313 
universe@63: 314 /* commented out for testing reasons */
universe@63: 315 /*
universe@63: 316 char* util_decrypt_str(DavSession *sn, char *str, char *key) {
universe@63: 317     DavKey *k = dav_context_get_key(sn->context, key);
universe@63: 318     if(!k) {
universe@63: 319         // TODO: session error
universe@63: 320         return NULL;
universe@63: 321     }
universe@63: 322     
universe@63: 323     char *dec_str = aes_decrypt(str, k);
universe@63: 324     char *ret_str = dav_session_strdup(sn, dec_str);
universe@63: 325     free(dec_str);
universe@63: 326     return ret_str;
universe@63: 327 }
universe@63: 328 */
universe@63: 329 char* util_random_str() {
universe@63: 330     unsigned char *str = malloc(25);
universe@63: 331     str[24] = '\0';
universe@63: 332     
universe@63: 333     sstr_t t = S(
universe@63: 334             "01234567890"
universe@63: 335             "abcdefghijklmnopqrstuvwxyz"
universe@63: 336             "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
universe@63: 337     const unsigned char *table = (const unsigned char*)t.ptr;
universe@63: 338     
universe@63: 339     RAND_pseudo_bytes(str, 24);
universe@63: 340     for(int i=0;i<24;i++) {
universe@63: 341         int c = str[i] % t.length;
universe@63: 342         str[i] = table[c];
universe@63: 343     }
universe@63: 344     
universe@63: 345     return (char*)str;
universe@63: 346 }
universe@63: 347 
universe@63: 348 /*
universe@63: 349  * gets a substring from 0 to the appearance of the token
universe@63: 350  * tokens are separated by space
universe@63: 351  * sets sub to the substring and returns the remaining string
universe@63: 352  */
universe@63: 353 sstr_t util_getsubstr_until_token(sstr_t str, sstr_t token, sstr_t *sub) {  
universe@63: 354     int i;
universe@63: 355     int token_start = -1;
universe@63: 356     int token_end = -1;
universe@63: 357     for(i=0;i<=str.length;i++) {
universe@63: 358         int c;
universe@63: 359         if(i == str.length) {
universe@63: 360             c = ' ';
universe@63: 361         } else {
universe@63: 362             c = str.ptr[i];
universe@63: 363         }
universe@63: 364         if(c < 33) {
universe@63: 365             if(token_start != -1) {
universe@63: 366                 token_end = i;
universe@63: 367                 size_t len = token_end - token_start;
universe@63: 368                 sstr_t tk = sstrsubsl(str, token_start, len);
universe@63: 369                 //printf("token: {%.*s}\n", token.length, token.ptr);
universe@63: 370                 if(!sstrcmp(tk, token)) {
universe@63: 371                     *sub = sstrtrim(sstrsubsl(str, 0, token_start));
universe@63: 372                     break;
universe@63: 373                 }
universe@63: 374                 token_start = -1;
universe@63: 375                 token_end = -1;
universe@63: 376             }
universe@63: 377         } else {
universe@63: 378             if(token_start == -1) {
universe@63: 379                 token_start = i;
universe@63: 380             }
universe@63: 381         }
universe@63: 382     }
universe@63: 383     
universe@63: 384     if(i < str.length) {
universe@63: 385         return sstrtrim(sstrsubs(str, i));
universe@63: 386     } else {
universe@63: 387         str.ptr = NULL;
universe@63: 388         str.length = 0;
universe@63: 389         return str;
universe@63: 390     }
universe@63: 391 }
universe@41: 
universe@41: universe@41: universe@41: