1 // vNote implementation for Citadel
3 // Copyright (C) 1999-2023 by the citadel.org development team.
5 // This program is open source software. Use, duplication, or disclosure
6 // is subject to the terms of the GNU General Public License, version 3.
20 #include <libcitadel.h>
23 struct vnote *vnote_new(void) {
26 v = (struct vnote *) malloc(sizeof(struct vnote));
28 memset(v, 0, sizeof(struct vnote));
29 v->magic = CTDL_VNOTE_MAGIC;
30 v->pos_left = rand() % 256;
31 v->pos_top = rand() % 256;
35 v->color_green = 0xFF;
41 struct vnote *vnote_new_from_str(char *s) {
49 int is_quoted_printable;
55 while (*ptr) { // keep going until we hit a null terminator
57 nexteol = strchr(ptr, '\n');
59 thisline_len = (nexteol-ptr);
60 thisline = malloc(thisline_len + 2);
61 memcpy(thisline, ptr, thisline_len);
62 thisline[thisline_len] = '\0';
66 thisline = strdup(ptr);
67 thisline_len = strlen(thisline);
72 if (thisline_len > 1) {
73 if (thisline[thisline_len - 1] == '\r') {
74 thisline[thisline_len - 1] = 0;
79 /* locate the colon separator */
80 encoded_value = strchr(thisline, ':');
84 /* any qualifiers? (look for a semicolon) */
85 is_base64 = bmstrcasestr(thisline, "encoding=base64") ? 1 : 0;
86 is_quoted_printable = bmstrcasestr(thisline, "encoding=quoted-printable") ? 1 : 0;
88 char *semicolon_pos = strchr(thisline, ';');
93 decoded_value = malloc(thisline_len);
95 CtdlDecodeBase64(decoded_value,
97 strlen(encoded_value));
99 else if (is_quoted_printable) {
100 CtdlDecodeQuotedPrintable(decoded_value,
102 strlen(encoded_value));
105 strcpy(decoded_value, encoded_value);
108 if (!strcasecmp(thisline, "UID")) {
109 if (v->uid) free(v->uid);
110 v->uid = decoded_value;
112 else if (!strcasecmp(thisline, "SUMMARY")) {
113 if (v->summary) free(v->summary);
114 v->summary = decoded_value;
116 else if ( (!strcasecmp(thisline, "NOTE"))
117 || (!strcasecmp(thisline, "BODY")) ) {
118 if (v->body) free(v->body);
119 v->body = decoded_value;
121 else if (!strcasecmp(thisline, "X-OUTLOOK-WIDTH")) {
122 v->pos_width = atoi(decoded_value);
125 else if (!strcasecmp(thisline, "X-OUTLOOK-HEIGHT")) {
126 v->pos_height = atoi(decoded_value);
129 else if (!strcasecmp(thisline, "X-OUTLOOK-LEFT")) {
130 v->pos_left = atoi(decoded_value);
133 else if (!strcasecmp(thisline, "X-OUTLOOK-TOP")) {
134 v->pos_top = atoi(decoded_value);
137 else if ( (!strcasecmp(thisline, "X-OUTLOOK-COLOR"))
138 && (strlen(decoded_value) == 7)
139 && (decoded_value[0] == '#') ) {
140 sscanf(&decoded_value[1], "%2x%2x%2x",
147 free(decoded_value); // throw it away
150 // FIXME still need to handle these:
151 // X-OUTLOOK-CREATE-TIME:20070611T204615Z
152 // REV:20070611T204621Z
161 void vnote_free(struct vnote *v) {
163 if (v->magic != CTDL_VNOTE_MAGIC) return;
165 if (v->uid) free(v->uid);
166 if (v->summary) free(v->summary);
167 if (v->body) free(v->body);
169 memset(v, 0, sizeof(struct vnote));
174 // helper function for vnote_serialize()
175 void vnote_serialize_output_field(char *append_to, char *field, char *label) {
184 if (!append_to) return;
188 mydup = malloc((strlen(field) * 3) + 1);
192 while (ptr[pos] != 0) {
193 ch = (unsigned char)(ptr[pos++]);
196 mydup[output_len++] = ch;
198 else if ( (ch >= 32) && (ch <= 60) ) {
199 mydup[output_len++] = ch;
201 else if ( (ch >= 62) && (ch <= 126) ) {
202 mydup[output_len++] = ch;
205 sprintf((char *)&mydup[output_len], "=%02X", ch);
210 mydup[output_len] = 0;
212 sprintf(&append_to[strlen(append_to)], "%s%s:%s\r\n",
214 (is_qp ? ";ENCODING=QUOTED-PRINTABLE" : ""),
220 char *vnote_serialize(struct vnote *v) {
222 int bytes_needed = 0;
225 if (v->magic != CTDL_VNOTE_MAGIC) return NULL;
228 if (v->summary) bytes_needed += strlen(v->summary);
229 if (v->body) bytes_needed += strlen(v->body);
230 s = malloc(bytes_needed);
234 vnote_serialize_output_field(s, "vnote", "BEGIN");
235 vnote_serialize_output_field(s, "//Citadel//vNote handler library//EN", "PRODID");
236 vnote_serialize_output_field(s, "1.1", "VERSION");
237 vnote_serialize_output_field(s, "PUBLIC", "CLASS");
238 vnote_serialize_output_field(s, v->uid, "UID");
239 vnote_serialize_output_field(s, v->summary, "SUMMARY");
240 vnote_serialize_output_field(s, v->body, "BODY");
241 vnote_serialize_output_field(s, v->body, "NOTE");
242 sprintf(&s[strlen(s)], "X-OUTLOOK-COLOR:#%02X%02X%02X\r\n", v->color_red, v->color_green, v->color_blue);
243 sprintf(&s[strlen(s)], "X-OUTLOOK-LEFT:%d\r\n", v->pos_left);
244 sprintf(&s[strlen(s)], "X-OUTLOOK-TOP:%d\r\n", v->pos_top);
245 sprintf(&s[strlen(s)], "X-OUTLOOK-WIDTH:%d\r\n", v->pos_width);
246 sprintf(&s[strlen(s)], "X-OUTLOOK-HEIGHT:%d\r\n", v->pos_height);
247 vnote_serialize_output_field(s, "vnote", "END");