Back to index

libcitadel  8.12
vnote.c
Go to the documentation of this file.
00001 /*
00002  * vNote implementation for Citadel
00003  *
00004  * Copyright (C) 1999-2007 by the citadel.org development team.
00005  *
00006  * This program is open source software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 3 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00019  */
00020 
00021 
00022 #include <stdlib.h>
00023 #include <unistd.h>
00024 #include <stdio.h>
00025 #include <fcntl.h>
00026 #include <signal.h>
00027 
00028 #if TIME_WITH_SYS_TIME
00029 # include <sys/time.h>
00030 # include <time.h>
00031 #else
00032 # if HAVE_SYS_TIME_H
00033 #  include <sys/time.h>
00034 # else
00035 #  include <time.h>
00036 # endif
00037 #endif
00038 
00039 #include <ctype.h>
00040 #include <string.h>
00041 #include <errno.h>
00042 #include <limits.h>
00043 #include <string.h>
00044 #include <libcitadel.h>
00045 
00046 
00047 struct vnote *vnote_new(void) {
00048        struct vnote *v;
00049 
00050        v = (struct vnote *) malloc(sizeof(struct vnote));
00051        if (v) {
00052               memset(v, 0, sizeof(struct vnote));
00053               v->magic = CTDL_VNOTE_MAGIC;
00054               v->pos_left = rand() % 256;
00055               v->pos_top = rand() % 256;
00056               v->pos_width = 200;
00057               v->pos_height = 150;
00058               v->color_red = 0xFF;
00059               v->color_green = 0xFF;
00060               v->color_blue = 0x00;
00061        }
00062        return v;
00063 }
00064 
00065 struct vnote *vnote_new_from_str(char *s) {
00066        struct vnote *v;
00067        char *ptr = s;
00068        char *nexteol;
00069        char *thisline;
00070        int thisline_len;
00071        char *encoded_value;
00072        char *decoded_value;
00073        int is_quoted_printable;
00074        int is_base64;
00075 
00076        v = vnote_new();
00077        if (!v) return NULL;
00078 
00079        while (*ptr) {              // keep going until we hit a null terminator
00080               thisline = NULL;
00081               nexteol = strchr(ptr, '\n');
00082               if (nexteol) {
00083                      thisline = malloc((nexteol - ptr) + 2);
00084                      strncpy(thisline, ptr, (nexteol-ptr));
00085                      thisline_len = (nexteol-ptr);
00086                      thisline[thisline_len] = 0;
00087                      ptr = nexteol + 1;
00088               }
00089               else {
00090                      thisline = strdup(ptr);
00091                      thisline_len = strlen(thisline);
00092                      ptr += thisline_len;
00093               }
00094 
00095               if (thisline) {
00096                      if (thisline_len > 1) {
00097                             if (thisline[thisline_len - 1] == '\r') {
00098                                    thisline[thisline_len - 1] = 0;
00099                                    --thisline_len;
00100                             }
00101                      }
00102 
00103                      /* locate the colon separator */
00104                      encoded_value = strchr(thisline, ':');
00105                      if (encoded_value) {
00106                             *encoded_value++ = 0;
00107 
00108                             /* any qualifiers?  (look for a semicolon) */
00109                             is_base64 = bmstrcasestr(thisline, "encoding=base64") ? 1 : 0;
00110                             is_quoted_printable = bmstrcasestr(thisline, "encoding=quoted-printable") ? 1 : 0;
00111 
00112                             char *semicolon_pos = strchr(thisline, ';');
00113                             if (semicolon_pos) {
00114                                    *semicolon_pos = 0;
00115                             }
00116 
00117                             decoded_value = malloc(thisline_len);
00118                             if (is_base64) {
00119                                    CtdlDecodeBase64(decoded_value,
00120                                                  encoded_value,
00121                                                  strlen(encoded_value));
00122                             }
00123                             else if (is_quoted_printable) {
00124                                    CtdlDecodeQuotedPrintable(decoded_value,
00125                                                  encoded_value,
00126                                                  strlen(encoded_value));
00127                             }
00128                             else {
00129                                    strcpy(decoded_value, encoded_value);
00130                             }
00131 
00132                             if (!strcasecmp(thisline, "UID")) {
00133                                    if (v->uid) free(v->uid);
00134                                    v->uid = decoded_value;
00135                             }
00136                             else if (!strcasecmp(thisline, "SUMMARY")) {
00137                                    if (v->summary) free(v->summary);
00138                                    v->summary = decoded_value;
00139                             }
00140                             else if ( (!strcasecmp(thisline, "NOTE"))
00141                                  || (!strcasecmp(thisline, "BODY")) ) {
00142                                    if (v->body) free(v->body);
00143                                    v->body = decoded_value;
00144                             }
00145                             else if (!strcasecmp(thisline, "X-OUTLOOK-WIDTH")) {
00146                                    v->pos_width = atoi(decoded_value);
00147                                    free(decoded_value);
00148                             }
00149                             else if (!strcasecmp(thisline, "X-OUTLOOK-HEIGHT")) {
00150                                    v->pos_height = atoi(decoded_value);
00151                                    free(decoded_value);
00152                             }
00153                             else if (!strcasecmp(thisline, "X-OUTLOOK-LEFT")) {
00154                                    v->pos_left = atoi(decoded_value);
00155                                    free(decoded_value);
00156                             }
00157                             else if (!strcasecmp(thisline, "X-OUTLOOK-TOP")) {
00158                                    v->pos_top = atoi(decoded_value);
00159                                    free(decoded_value);
00160                             }
00161                             else if ( (!strcasecmp(thisline, "X-OUTLOOK-COLOR"))
00162                                  && (strlen(decoded_value) == 7)
00163                                  && (decoded_value[0] == '#') ) {
00164                                    sscanf(&decoded_value[1], "%2x%2x%2x",
00165                                           &v->color_red,
00166                                           &v->color_green,
00167                                           &v->color_blue);
00168                                    free(decoded_value);
00169                             }
00170                             else {
00171                                    free(decoded_value); // throw it away
00172                             }
00173 
00174                             /* FIXME still need to handle these:
00175                              * X-OUTLOOK-CREATE-TIME:20070611T204615Z
00176                              * REV:20070611T204621Z
00177                              */
00178                      }
00179                      free(thisline);
00180               }
00181        }
00182 
00183        return(v);
00184 }
00185 
00186 void vnote_free(struct vnote *v) {
00187        if (!v) return;
00188        if (v->magic != CTDL_VNOTE_MAGIC) return;
00189 
00190        if (v->uid) free(v->uid);
00191        if (v->summary) free(v->summary);
00192        if (v->body) free(v->body);
00193        
00194        memset(v, 0, sizeof(struct vnote));
00195        free(v);
00196 }
00197 
00198 
00199 /* helper function for vnote_serialize() */
00200 void vnote_serialize_output_field(char *append_to, char *field, char *label) {
00201 
00202        char *mydup;
00203        int output_len = 0;
00204        int is_qp = 0;
00205        char *ptr = field;
00206        unsigned char ch;
00207        int pos = 0;
00208 
00209        if (!append_to) return;
00210        if (!field) return;
00211        if (!label) return;
00212 
00213        mydup = malloc((strlen(field) * 3) + 1);
00214        if (!mydup) return;
00215        strcpy(mydup, "");
00216 
00217        while (ptr[pos] != 0) {
00218               ch = (unsigned char)(ptr[pos++]);
00219 
00220               if (ch == 9) {
00221                      mydup[output_len++] = ch;
00222               }
00223               else if ( (ch >= 32) && (ch <= 60) ) {
00224                      mydup[output_len++] = ch;
00225               }
00226               else if ( (ch >= 62) && (ch <= 126) ) {
00227                      mydup[output_len++] = ch;
00228               }
00229               else {
00230                      sprintf((char *)&mydup[output_len], "=%02X", ch);
00231                      output_len += 3;
00232                      is_qp = 1;
00233               }
00234        }
00235        mydup[output_len] = 0;
00236 
00237        sprintf(&append_to[strlen(append_to)], "%s%s:%s\r\n",
00238               label,
00239               (is_qp ? ";ENCODING=QUOTED-PRINTABLE" : ""),
00240               mydup);
00241        free(mydup);
00242 }
00243 
00244 
00245 char *vnote_serialize(struct vnote *v) {
00246        char *s;
00247        int bytes_needed = 0;
00248 
00249        if (!v) return NULL;
00250        if (v->magic != CTDL_VNOTE_MAGIC) return NULL;
00251 
00252        bytes_needed = 1024;
00253        if (v->summary) bytes_needed += strlen(v->summary);
00254        if (v->body) bytes_needed += strlen(v->body);
00255        s = malloc(bytes_needed);
00256        if (!s) return NULL;
00257 
00258        strcpy(s, "");
00259        vnote_serialize_output_field(s, "vnote", "BEGIN");
00260        vnote_serialize_output_field(s, "//Citadel//vNote handler library//EN", "PRODID");
00261        vnote_serialize_output_field(s, "1.1", "VERSION");
00262        vnote_serialize_output_field(s, "PUBLIC", "CLASS");
00263        vnote_serialize_output_field(s, v->uid, "UID");
00264        vnote_serialize_output_field(s, v->summary, "SUMMARY");
00265        vnote_serialize_output_field(s, v->body, "BODY");
00266        vnote_serialize_output_field(s, v->body, "NOTE");
00267        sprintf(&s[strlen(s)], "X-OUTLOOK-COLOR:#%02X%02X%02X\r\n",
00268               v->color_red, v->color_green, v->color_blue);
00269        sprintf(&s[strlen(s)], "X-OUTLOOK-LEFT:%d\r\n", v->pos_left);
00270        sprintf(&s[strlen(s)], "X-OUTLOOK-TOP:%d\r\n", v->pos_top);
00271        sprintf(&s[strlen(s)], "X-OUTLOOK-WIDTH:%d\r\n", v->pos_width);
00272        sprintf(&s[strlen(s)], "X-OUTLOOK-HEIGHT:%d\r\n", v->pos_height);
00273        vnote_serialize_output_field(s, "vnote", "END");
00274        return(s);
00275 }