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