Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals

utils.c

00001 /*
00002  * Copyright (c) 2005, 2006 by KoanLogic s.r.l. <http://www.koanlogic.com>
00003  * All rights reserved.
00004  *
00005  * This file is part of KLone, and as such it is subject to the license stated
00006  * in the LICENSE file which you have received as part of this distribution.
00007  *
00008  * $Id: utils.c,v 1.49 2007/10/26 11:21:51 tho Exp $
00009  */
00010 
00011 #include "klone_conf.h"
00012 #include <stdlib.h>
00013 #include <stdio.h>
00014 #include <signal.h>
00015 #include <time.h>
00016 #include <string.h>
00017 #include <ctype.h>
00018 #include <fcntl.h>
00019 #include <unistd.h>
00020 #include <dirent.h>
00021 #include <sys/stat.h>
00022 #include <u/libu.h>
00023 #include <klone/os.h>
00024 #include <klone/io.h>
00025 #include <klone/codecs.h>
00026 #include <klone/emb.h>
00027 #include <klone/mime_map.h>
00028 #include <klone/version.h>
00029 #include <klone/utils.h>
00030 #ifdef HAVE_STRINGS
00031 #include <strings.h>
00032 #endif
00033 
00034 enum { LF = 0xA, CR = 0xD };
00035 
00036 static struct html_entities_s
00037 {
00038     int s_char;
00039     const char *entity; 
00040 } entities[] = {
00041     { '&',  "&amp;"  },
00042     { '"',  "&quot;" },
00043     { '\'', "&#39;"  }, 
00044     { '<',  "&lt;"   },
00045     { '>',  "&gt;"   },
00046     { 0, NULL     }
00047 };
00048 
00049 #ifdef OS_UNIX
00050 inline int u_sig_block(int sig)
00051 {
00052     sigset_t sset;
00053 
00054     sigemptyset(&sset);
00055     sigaddset(&sset, sig);
00056     dbg_err_if(sigprocmask(SIG_BLOCK, &sset, NULL));
00057 
00058     return 0;
00059 err:
00060     return ~0;
00061 }
00062 
00063 inline int u_sig_unblock(int sig)
00064 {
00065     sigset_t sset;
00066 
00067     sigemptyset(&sset);
00068     sigaddset(&sset, sig);
00069     dbg_err_if(sigprocmask(SIG_UNBLOCK, &sset, NULL));
00070 
00071     return 0;
00072 err:
00073     return ~0;
00074 }
00075 #endif /* OS_UNIX */
00076 
00077 
00093 char *u_strnstr(const char *buf, const char *sub, size_t buflen)
00094 {
00095     ssize_t len = strlen(sub);
00096     ssize_t plen;
00097     char *p;
00098 
00099     if (*sub == 0)
00100         return (char *)buf;
00101 
00102     plen = buflen;
00103     for (p = (char *)buf; p != NULL; p = memchr(p + 1, *sub, plen - 1))
00104     {
00105         plen = buflen - (p - buf);
00106 
00107         if (plen < len)
00108             return NULL;
00109 
00110         if (strncmp(p, sub, len) == 0)
00111             return (p);
00112     }
00113 
00114     return NULL;
00115 }
00116 
00133 int u_foreach_dir_item(const char *path, unsigned int mask,
00134     int (*cb)(struct dirent*, const char *, void*), void* arg)
00135 {
00136     struct dirent *de;
00137     struct stat st;
00138     DIR *dir = NULL;
00139     char buf[U_FILENAME_MAX];
00140     int rc;
00141 
00142     dbg_return_if (path == NULL, ~0);
00143     dbg_return_if (cb == NULL, ~0);
00144     
00145     /* open the given directory */
00146     dir = opendir(path);
00147     dbg_err_if(dir == NULL);
00148 
00149     while((de = readdir(dir)) != NULL)
00150     {
00151         /* skip . and .. dirs */
00152         if(!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
00153             continue;
00154 
00155         /* build fully qualified name of this item */
00156         dbg_err_if(u_snprintf(buf, U_FILENAME_MAX, "%s/%s", path, de->d_name));
00157 
00158         dbg_err_if( (rc = stat(buf, &st)) == -1);
00159 
00160         /* skip if its type is not in the requested mask */
00161         if(((st.st_mode & S_IFMT) & mask) != 0 && cb(de, path, arg))
00162             break;
00163     }
00164 
00165     closedir(dir);
00166 
00167     return 0;
00168 err:
00169     return ~0;
00170 }
00171 
00186 int u_match_ext(const char *filename, const char *extension)
00187 {
00188     const char *fn, *ext;
00189     size_t flen, elen;
00190 
00191     if(filename == NULL || extension == NULL)
00192         return 0;
00193 
00194     flen = strlen(filename);
00195     elen = strlen(extension);
00196     if(elen > flen)
00197         return 0;
00198 
00199     fn = filename + flen - 1;
00200     ext = extension + elen - 1;
00201     for( ; elen; --fn, --ext, --elen)
00202     {
00203         if(tolower(*fn) != tolower(*ext))
00204             return 0;
00205     }
00206     return 1;
00207 }
00208 
00209 /* hex char to int */
00210 static short htoi(unsigned char c)
00211 {
00212     c = tolower(c);
00213 
00214     if(c >= '0' && c <= '9')
00215         return c - '0';
00216     else if(c >= 'a' && c <= 'z')
00217         return c - 'a' + 10;
00218     else
00219         return 0;
00220 }
00221 
00222 
00223 static ssize_t u_sqlncpy_encode(char *d, const char *s, size_t slen)
00224 {
00225     ssize_t wr = 0;
00226     unsigned char c;
00227 
00228     dbg_return_if (d == NULL, -1);
00229     dbg_return_if (s == NULL, -1);
00230 
00231     for(; slen; --slen)
00232     {
00233         c = *d++ = *s++;
00234         wr++;
00235         if(c == '\'') 
00236         {
00237             dbg_err_if(slen < 2);
00238             *d++ = '\'';
00239             wr++;
00240             --slen;
00241         } 
00242     }
00243     *d = 0;
00244 
00245     return wr;
00246 err:
00247     return -1;
00248 }
00249 
00250 static ssize_t u_sqlncpy_decode(char *d, const char *s, size_t slen)
00251 {
00252     unsigned char c, last = 0;
00253     ssize_t wr = 0;
00254     
00255     dbg_return_if (d == NULL, -1);
00256     dbg_return_if (s == NULL, -1);
00257 
00258     for(; slen; --slen)
00259     {
00260         c = *s++;
00261         if(c == '\'' && last == c) 
00262         {
00263             last = 0; 
00264             ; /* skip */
00265         } else {
00266             *d++ = c;
00267             last = c;
00268             wr++;
00269         }
00270     }
00271     *d = 0;
00272 
00273     return wr;
00274 }
00275 
00292 ssize_t u_sqlncpy(char *d, const char *s, size_t slen, int flags)
00293 {
00294     dbg_return_if (d == NULL, -1);
00295     dbg_return_if (s == NULL, -1);
00296 
00297     switch(flags)
00298     {
00299     case SQLCPY_ENCODE:
00300         return u_sqlncpy_encode(d, s, slen);
00301     case SQLCPY_DECODE:
00302         return u_sqlncpy_decode(d, s, slen);
00303     default:
00304         strncpy(d, s, slen);
00305         d[slen] = 0;
00306         return slen;
00307     }
00308 
00309     return -1;
00310 }
00311 
00312 static ssize_t u_urlncpy_encode(char *d, const char *s, size_t slen)
00313 {
00314     const char hexc[] = "0123456789ABCDEF";
00315     ssize_t wr = 0;
00316     unsigned char c;
00317 
00318     dbg_return_if (d == NULL, -1);
00319     dbg_return_if (s == NULL, -1);
00320 
00321     for(; slen; --slen)
00322     {
00323         c = *s++;
00324         if(c == ' ') {
00325             *d++ = '+';
00326             wr++;
00327         } else if(isalnum(c) || c == '_' || c == '-' || c == '.') {
00328             *d++ = c;
00329             wr++;
00330         } else {
00331             *d++ = '%';                                        
00332             *d++ = hexc[(c >> 4) & 0xF];             
00333             *d++ = hexc[c & 0xF];  
00334             wr += 3;
00335         }
00336     }
00337     *d = 0;
00338 
00339     return wr;
00340 }
00341 
00342 static ssize_t u_urlncpy_decode(char *d, const char *s, size_t slen)
00343 {
00344     unsigned char c;
00345     ssize_t wr = 0;
00346 
00347     dbg_return_if (d == NULL, -1);
00348     dbg_return_if (s == NULL, -1);
00349 
00350     for(; slen; --slen, ++wr)
00351     {
00352         c = *s++;
00353         if(c == '%')
00354         {
00355             dbg_err_if(slen < 2 || !isxdigit(s[0]) || !isxdigit(s[1]));
00356             c = htoi(s[0]) << 4 | htoi(s[1]);
00357             //dbg_err_if(c == 0);
00358             *d++ = (char)c;
00359             s += 2;
00360             slen -= 2;
00361         } else if(c == '+') {
00362             *d++ = ' ';
00363         } else {
00364             *d++ = c;
00365         }
00366     }
00367     *d = 0;
00368 
00369     return wr;
00370 err:
00371     return -1;
00372 
00373 }
00374 
00391 ssize_t u_urlncpy(char *d, const char *s, size_t slen, int flags)
00392 {
00393     dbg_return_if (d == NULL, -1);
00394     dbg_return_if (s == NULL, -1);
00395 
00396     switch(flags)
00397     {
00398     case URLCPY_ENCODE:
00399         return u_urlncpy_encode(d, s, slen);
00400     case URLCPY_DECODE:
00401         return u_urlncpy_decode(d, s, slen);
00402     default:
00403         strncpy(d, s, slen);
00404         d[slen] = 0; /* zero-term the string */
00405         return slen;
00406     }
00407 
00408     return -1;
00409 }
00410 
00411 inline char u_tochex(int n)
00412 {
00413         if(n > 15)
00414                 return '?';
00415         return ( n < 10 ? n + '0' : n-10 + 'a');
00416 }
00417 
00418 static int u_hex2ch(char c)
00419 {
00420     if(c >= 'a' && c <= 'z') 
00421         return c - 'a' + 10;
00422     else if(c >= 'A' && c <= 'Z')
00423         return c - 'A' + 10;
00424     else if(c >= '0' && c <= '9') 
00425         return c - '0';
00426     else
00427         return -1; /* error */
00428 }
00429 
00430 void u_print_version_and_exit(void)
00431 {
00432     static const char *vv = 
00433     "KLone %s - Copyright (c) 2005, 2006, 2007 KoanLogic s.r.l. - "
00434     "All rights reserved. \n\n";
00435 
00436     fprintf(stderr, vv, klone_version());
00437 
00438     exit(EXIT_FAILURE);
00439 }
00440 
00441 static ssize_t u_hexncpy_decode(char *d, const char *s, size_t slen)
00442 {
00443         size_t i, t;
00444 
00445     dbg_return_if (d == NULL, -1);
00446     dbg_return_if (s == NULL, -1);
00447 
00448     /* slen must be multiple of 2 */
00449     dbg_err_if((slen % 2) != 0);
00450 
00451         for(i = 0, t = 0; i < slen; ++t, i += 2)
00452         d[t] = (u_hex2ch(s[i]) << 4) | u_hex2ch(s[i+1]); 
00453 
00454     d[t] = 0; /* zero-term */
00455 
00456     return t;
00457 err:
00458     return -1;
00459 }
00460 
00461 static ssize_t u_hexncpy_encode(char *d, const char *s, size_t slen)
00462 {
00463         size_t c, i, t;
00464 
00465     dbg_return_if (d == NULL, -1);
00466     dbg_return_if (s == NULL, -1);
00467 
00468         for(i = 0, t = 0; i < slen; ++i, t += 2)
00469         {
00470                 c = s[i];
00471         d[t]   = u_tochex((c >> 4) & 0x0F);
00472         d[t+1] = u_tochex(c & 0x0F);
00473         }
00474     d[t] = 0; /* zero-term */
00475 
00476     return t;
00477 }
00478 
00495 ssize_t u_hexncpy(char *d, const char *s, size_t slen, int flags)
00496 {
00497     dbg_err_if (d == NULL);
00498     dbg_err_if (s == NULL);
00499 
00500     switch(flags)
00501     {
00502     case HEXCPY_ENCODE:
00503         return u_hexncpy_encode(d, s, slen);
00504     case HEXCPY_DECODE:
00505         return u_hexncpy_decode(d, s, slen);
00506     default:
00507         strncpy(d, s, slen);
00508         d[slen] = 0; /* zero-term the string */
00509         return slen;
00510     }
00511 
00512 err:
00513     return -1;
00514 }
00515 
00516 static ssize_t u_htmlncpy_encode(char *d, const char *s, size_t slen)
00517 {
00518     struct html_entities_s *p;
00519     const char *map[256];
00520     size_t elen;
00521     unsigned char c;
00522     ssize_t wr = 0;
00523 
00524     dbg_return_if (d == NULL, -1);
00525     dbg_return_if (s == NULL, -1);
00526 
00527     /* build the map table (could be static but it wouldn't be thread-safe) */
00528     memset(map, 0, sizeof(map));
00529     for(p = entities; p->s_char; ++p)
00530         map[p->s_char] = p->entity;
00531 
00532     while(slen)
00533     {
00534         c = *s++;
00535         if(map[c] == NULL)
00536         {
00537             *d++ = c;   /* this char doesn't need encoding */
00538             wr++;
00539             --slen;
00540         } else {
00541             elen = strlen(map[c]);
00542             strcpy(d, map[c]); /* append the entity */
00543             --slen;
00544             d += elen;
00545             wr += elen;
00546         }
00547     }
00548     *d = 0;
00549 
00550     return wr;
00551 }
00552 
00553 static ssize_t u_htmlncpy_decode(char *d, const char *s, size_t slen)
00554 {
00555     struct html_entities_s *p;
00556     char *found, *after;
00557 
00558     dbg_return_if (d == NULL, -1);
00559     dbg_return_if (s == NULL, -1);
00560 
00561     strncpy(d, s, slen);
00562     d[slen] = 0;
00563 
00564     for(p = entities; p->s_char; ++p)
00565     {
00566         while((found = u_stristr(d, p->entity)) != NULL)
00567         {
00568             *found = p->s_char;
00569             after = found + strlen(p->entity);
00570             memmove(++found, after, 1 + strlen(after));
00571         }
00572     }
00573 
00574     return strlen(d);
00575 }
00576 
00593 ssize_t u_htmlncpy(char *d, const char *s, size_t slen, int flags)
00594 {
00595     dbg_err_if (d == NULL);
00596     dbg_err_if (s == NULL);
00597 
00598     switch(flags)
00599     {
00600     case HTMLCPY_ENCODE:
00601         return u_htmlncpy_encode(d, s, slen);
00602     case HTMLCPY_DECODE:
00603         return u_htmlncpy_decode(d, s, slen);
00604     default:
00605         strncpy(d, s, slen);
00606         d[slen] = 0; /* zero-term */
00607         return slen;
00608     }
00609 err:
00610     return -1;
00611 }
00612 
00626 char *u_stristr(const char *string, const char *sub)
00627 {
00628     const char *p;
00629     size_t len;
00630 
00631     dbg_err_if (sub == NULL);
00632     dbg_err_if (string == NULL);
00633 
00634     len = strlen(sub);
00635     for(p = string; *p; ++p)
00636     {
00637         if(strncasecmp(p, sub, len) == 0)
00638             return (char*)p;
00639     }
00640 
00641 err: /* fall through */
00642     return NULL;
00643 }
00644 
00658 char* u_strnrchr(const char *s, char c, size_t len)
00659 {
00660     register int i = len - 1;
00661 
00662     dbg_err_if (s == NULL);
00663     
00664     for(; i >= 0; --i)
00665         if(s[i] == c)
00666             return (char*)s + i; /* found */
00667 err:
00668     return NULL;
00669 }
00670 
00683 int u_tmpfile_open(io_t **pio)
00684 {
00685     char tmp[U_FILENAME_MAX];
00686     io_t *io = NULL;
00687 
00688     dbg_return_if (pio == NULL, ~0);
00689     
00690     if(tmpnam(tmp) != NULL)
00691     {
00692         dbg_err_if(u_file_open(tmp, O_CREAT | O_EXCL | O_RDWR, &io));
00693 
00694         dbg_err_if(io_name_set(io, tmp));
00695 
00696         *pio = io;
00697 
00698         return 0;
00699     }
00700 
00701 err:
00702     if(io)
00703         io_free(io);
00704     return ~0;
00705 }
00706 
00722 int u_file_open(const char *file, int flags, io_t **pio)
00723 {
00724     int fmod = 0; /* flags modifier */
00725     int fd;
00726 
00727 #ifdef OS_WIN
00728     fmod = _O_BINARY;
00729 #endif
00730     
00731     dbg_return_if (file == NULL, ~0);
00732     dbg_return_if (pio == NULL, ~0);
00733     
00734     fd = open(file, fmod | flags, 0600);
00735     dbg_err_if(fd < 0);
00736 
00737     dbg_err_if(io_fd_create(fd, IO_FD_CLOSE, pio));
00738 
00739     /* name the stream */
00740     dbg_err_if(io_name_set(*pio, file));
00741 
00742     return 0;
00743 err:
00744     if(fd < 0)
00745         dbg_strerror(errno);
00746     else
00747         close(fd);
00748     return ~0;
00749 }
00750 
00764 int u_getline(io_t *io, u_string_t *ln)
00765 {
00766     enum { BUFSZ = 1024 };
00767     char buf[BUFSZ];
00768     ssize_t len, rc;
00769 
00770     dbg_return_if (io == NULL, ~0);
00771     dbg_return_if (ln == NULL, ~0);
00772     
00773     u_string_clear(ln);
00774 
00775     while((rc = len = io_gets(io, buf, BUFSZ)) > 0)
00776     {
00777         dbg_err_if(u_string_append(ln, buf, --len));
00778         if(!u_isnl(buf[len]))
00779             continue; /* line's longer the bufsz (or eof);get next line chunk */
00780         else
00781             break;
00782     }
00783 
00784     dbg_if(rc < 0); /* io_gets error */
00785 
00786 err:
00787     return (rc <= 0 ? ~0 : 0);
00788 }
00789 
00803 int u_fgetline(FILE *in, u_string_t *ln)
00804 {
00805     enum { BUFSZ = 256 };
00806     char buf[BUFSZ];
00807     size_t len;
00808 
00809     dbg_return_if (in == NULL, ~0);
00810     dbg_return_if (ln == NULL, ~0);
00811     
00812     u_string_clear(ln);
00813 
00814     while(!ferror(in) && !feof(in) && fgets(buf, BUFSZ, in))
00815     {
00816         len = strlen(buf);
00817         dbg_err_if(u_string_append(ln, buf, len));
00818         if(!u_isnl(buf[len-1]))
00819             continue; /* line's longer the bufsz, get next line chunk */
00820         else
00821             break;
00822     }
00823 
00824     if(ferror(in))
00825         dbg_strerror(errno);
00826 err:
00827     return (u_string_len(ln) ? 0 : ~0);
00828 }
00829 
00830 int u_printf_ccstr(io_t *o, const char *buf, size_t sz)
00831 {
00832     char prev, c = 0;
00833     int pos = 0;
00834     size_t i;
00835 
00836     dbg_return_if (o == NULL, ~0);
00837     dbg_return_if (buf == NULL, ~0);
00838     
00839     for(i = 0; i < sz; ++i)
00840     {
00841         prev = c;
00842         c = buf[i];
00843         if(pos++ == 0) // first line char
00844             io_putc(o, '"');
00845         switch(c)
00846         {
00847         case CR:
00848             if(prev != LF) 
00849             io_printf(o, "\\n\"\n");
00850             pos = 0;
00851             break;
00852         case LF:
00853             if(prev != CR) 
00854             io_printf(o, "\\n\"\n");
00855             pos = 0;
00856             break;
00857         case '"':
00858             io_printf(o, "\\\"");
00859             break;
00860         case '\\':
00861             io_printf(o, "\\\\");
00862             break;
00863         default:
00864             if(isprint(c))
00865                 io_putc(o, c);
00866             else {
00867                 io_printf(o, "\\x%c%c", u_tochex((c >> 4) & 0x0F),
00868                 u_tochex(c & 0x0F));
00869             }
00870         }
00871     }
00872     if(pos)
00873         io_putc(o, '"');
00874 
00875     return 0;
00876 }
00877 
00888 int u_file_exists(const char *fqn)
00889 {
00890     struct stat st;
00891 
00892     dbg_return_if (fqn == NULL, 0);
00893     
00894     return stat(fqn, &st) == 0 && S_ISREG(st.st_mode);
00895 }
00896 
00911 void u_tohex(char *hex, const char *src, size_t sz)
00912 {
00913     size_t c, i, t;
00914 
00915     dbg_ifb (hex == NULL) return;
00916     dbg_ifb (src == NULL) return;
00917     
00918     for(i = 0, t = 0; i < sz; ++i, t += 2)
00919     {
00920         c = src[i];
00921         hex[t]   = u_tochex((c >> 4) & 0x0F);
00922         hex[t+1] = u_tochex(c & 0x0F);
00923     }
00924 
00925     hex[t] = 0; /* zero-term */
00926 }
00927 
00942 int u_md5(char *buf, size_t sz, char out[MD5_DIGEST_BUFSZ])
00943 {
00944     md5_state_t md5ctx;
00945     md5_byte_t md5_digest[16]; /* binary digest */
00946 
00947     dbg_return_if (buf == NULL, ~0);
00948     dbg_return_if (out == NULL, ~0);
00949     
00950     md5_init(&md5ctx);
00951     md5_append(&md5ctx, (md5_byte_t*)buf, sz);
00952     md5_finish(&md5ctx, md5_digest);
00953 
00954     u_tohex(out, (const char*)md5_digest, 16);
00955 
00956     out[MD5_DIGEST_LEN] = 0;
00957 
00958     return 0;
00959 }
00960 
00975 int u_md5io(io_t *io, char out[MD5_DIGEST_BUFSZ])
00976 {
00977     enum { page_sz = 4096 };
00978     md5_state_t md5ctx;
00979     md5_byte_t md5_digest[16]; /* binary digest */
00980     char buf[page_sz];
00981     size_t cnt;
00982 
00983     dbg_err_if (io == NULL);
00984     dbg_err_if (out == NULL);
00985 
00986     md5_init(&md5ctx);
00987 
00988     while((cnt = io_read(io, buf, page_sz)) > 0)
00989         md5_append(&md5ctx, (md5_byte_t*)buf, cnt);
00990 
00991     md5_finish(&md5ctx, md5_digest);
00992 
00993     u_tohex(out, (const char*)md5_digest, 16);
00994 
00995     out[MD5_DIGEST_LEN] = 0;
00996 
00997     return 0;
00998 err:
00999     return ~0;
01000 }
01001 
01002 int u_signal(int sig, u_sig_t handler)
01003 {
01004 #ifdef OS_WIN
01005     dbg_err_if(signal(sig, handler) == SIG_ERR);
01006 #else
01007     struct sigaction action;
01008     sigset_t all;
01009 
01010     sigfillset(&all); 
01011     action.sa_mask = all;
01012     action.sa_handler = handler;
01013 
01014     /* disable child shell jobs notification */
01015     action.sa_flags = SA_RESTART | (sig == SIGCHLD ? SA_NOCLDSTOP : 0);
01016     dbg_err_if(sigaction(sig, &action, (struct sigaction *) 0));
01017 #endif
01018 
01019     return 0;
01020 err:
01021     return ~0;
01022 }                                                             
01023 
01034 const mime_map_t *u_get_mime_map(const char *file_name)
01035 {
01036     char *ext;
01037     mime_map_t *mm;
01038 
01039     dbg_goto_if (file_name == NULL, notfound);
01040 
01041     if((ext = strrchr(file_name, '.')) != NULL)
01042     {
01043         ++ext; /* skip '.' */
01044         /* FIXME binary search here */
01045         for(mm = mime_map; mm->ext && mm->mime_type; ++mm)
01046         {
01047             if(strcasecmp(mm->ext, ext) == 0)
01048                 return mm;
01049         }
01050     }
01051 
01052 notfound:
01053     return mime_map; /* the first item is the default */
01054 }
01055 
01067 const char *u_guess_mime_type(const char *file_name)
01068 {
01069     char *ext;
01070     mime_map_t *mm;
01071 
01072     dbg_goto_if (file_name == NULL, notfound);
01073     
01074     if((ext = strrchr(file_name, '.')) != NULL)
01075     {
01076         ++ext; /* skip '.' */
01077         for(mm = mime_map; mm->ext && mm->mime_type; ++mm)
01078             if(strcmp(mm->ext, ext) == 0)
01079                 return mm->mime_type;
01080     }
01081 
01082 notfound:
01083     return "application/octet-stream";
01084 }
01085 
01086 #ifdef HAVE_LIBZ
01087 
01102 int u_io_unzip_copy(io_t *out, const char *data, size_t sz)
01103 {
01104     codec_t *zip = NULL;
01105     io_t *ios = NULL;
01106 
01107     dbg_return_if (out == NULL, ~0);
01108     dbg_return_if (data == NULL, ~0);
01109     
01110     /* create an io_t around the HTML block */
01111     dbg_err_if(io_mem_create((char*)data, sz, 0, &ios));
01112 
01113     /* apply a gzip codec */
01114     dbg_err_if(codec_gzip_create(GZIP_UNCOMPRESS, &zip));
01115     dbg_err_if(io_codec_add_tail(ios, zip));
01116     zip = NULL; /* io_free() will free the codec */
01117 
01118     /* pipe ios to out */
01119     dbg_err_if(io_pipe(out, ios) < 0);
01120 
01121     io_free(ios);
01122 
01123     return 0;
01124 err:
01125     if(zip)
01126         codec_free(zip);
01127     if(ios)
01128         io_free(ios);
01129     return ~0;
01130 }
01131 #endif
01132 
01133 #ifdef HAVE_LIBOPENSSL
01134 
01156 int u_cipher_encrypt(const EVP_CIPHER *cipher, unsigned char *key, 
01157     unsigned char *iv, char *dst, size_t *dcount, const char *src, size_t ssz)
01158 {
01159     EVP_CIPHER_CTX ctx;
01160     ssize_t dlen = 0;  /* dst buffer length */
01161     int wr;
01162 
01163     dbg_return_if (cipher == NULL, ~0);
01164     dbg_return_if (key == NULL, ~0);
01165     dbg_return_if (iv == NULL, ~0);
01166     dbg_return_if (dcount == NULL, ~0);
01167     dbg_return_if (src == NULL, ~0);
01168     dbg_return_if (dst == NULL, ~0);
01169     
01170     /* init the context */
01171     EVP_CIPHER_CTX_init(&ctx);
01172 
01173     /* be sure that the cipher has been loaded */
01174     EVP_add_cipher(cipher);
01175     
01176     dbg_err_if(!EVP_EncryptInit_ex(&ctx, cipher, NULL, key, iv));
01177 
01178     dbg_err_if(!EVP_EncryptUpdate(&ctx, dst, &wr, src, ssz));
01179     dlen += wr;
01180     dst += wr;
01181 
01182     dbg_err_if(!EVP_EncryptFinal_ex(&ctx, dst, &wr));
01183     dlen += wr;
01184 
01185     *dcount = dlen; /* # of bytes written to dst */
01186 
01187     EVP_CIPHER_CTX_cleanup(&ctx);
01188 
01189     return 0;
01190 err:
01191     EVP_CIPHER_CTX_cleanup(&ctx);
01192     return ~0;
01193 }
01194 
01215 int u_cipher_decrypt(const EVP_CIPHER *cipher, unsigned char *key, 
01216     unsigned char *iv, char *dst, size_t *dcount, const char *src, size_t ssz)
01217 {
01218     EVP_CIPHER_CTX ctx;
01219     ssize_t dlen = 0;  /* dst buffer length */
01220     int wr;
01221 
01222     dbg_return_if (cipher == NULL, ~0);
01223     dbg_return_if (key == NULL, ~0);
01224     dbg_return_if (iv == NULL, ~0);
01225     dbg_return_if (dcount == NULL, ~0);
01226     dbg_return_if (src == NULL, ~0);
01227     dbg_return_if (dst == NULL, ~0);
01228 
01229     /* init the context */
01230     EVP_CIPHER_CTX_init(&ctx);
01231 
01232     /* be sure that the cipher has been loaded */
01233     EVP_add_cipher(cipher);
01234     
01235     dbg_err_if(!EVP_DecryptInit_ex(&ctx, cipher, NULL, key, iv));
01236 
01237     dbg_err_if(!EVP_DecryptUpdate(&ctx, dst, &wr, src, ssz));
01238     dlen += wr;
01239     dst += wr;
01240 
01241     dbg_err_if(!EVP_DecryptFinal_ex(&ctx, dst, &wr));
01242     dlen += wr;
01243 
01244     *dcount = dlen; /* # of bytes written to dst */
01245 
01246     EVP_CIPHER_CTX_cleanup(&ctx);
01247 
01248     return 0;
01249 err:
01250     EVP_CIPHER_CTX_cleanup(&ctx);
01251     return ~0;
01252 }
01253 
01254 #endif