1 /* $Id$ */
2 /* Copyright (c) 2012-2013 Pierre Pronchery <khorben@defora.org> */
3 /* This file is part of DeforaOS Desktop Mailer */
4 /* This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, version 3 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>. */
15
16
17
18 #include <ctype.h>
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <time.h>
23 #include "../include/Mailer/helper.h"
24
25
26 /* public */
27 /* functions */
28 /* mailer_helper_get_date */
29 static int _date_do(char const * date, char const * format, struct tm * tm);
30
mailer_helper_get_date(char const * date,struct tm * tm)31 time_t mailer_helper_get_date(char const * date, struct tm * tm)
32 {
33 time_t t;
34
35 if(date != NULL)
36 /* FIXME check the standard(s) again */
37 if(_date_do(date, "%a, %d %b %Y %T %z (%z)", tm) == 0
38 || _date_do(date, "%a, %d %b %Y %T %z", tm) == 0
39 || _date_do(date, "%d %b %Y %T %z", tm) == 0
40 || _date_do(date, "%d/%m/%Y %T %z", tm) == 0
41 || _date_do(date, "%d/%m/%Y %T", tm) == 0
42 || _date_do(date, "%FT%TZ", tm) == 0)
43 {
44 /* fix the date if missing the century */
45 if(tm->tm_year >= -1830 && tm->tm_year < -1800)
46 tm->tm_year += 1900;
47 else if(tm->tm_year >= -1900 && tm->tm_year < -1830)
48 tm->tm_year += 2000;
49 return mktime(tm);
50 }
51 /* XXX fallback to the current time and date */
52 #ifdef DEBUG
53 fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, date);
54 #endif
55 t = time(NULL);
56 gmtime_r(&t, tm);
57 return t;
58 }
59
_date_do(char const * date,char const * format,struct tm * tm)60 static int _date_do(char const * date, char const * format, struct tm * tm)
61 {
62 char const * p;
63
64 memset(tm, 0, sizeof(*tm));
65 if((p = strptime(date, format, tm)) != NULL && *p == '\0')
66 return 0;
67 /* check if we obtained enough information */
68 if(p != NULL && tm->tm_year != 0 && tm->tm_mday != 0)
69 /* XXX _apparently_ yes */
70 return 0;
71 return -1;
72 }
73
74
75 /* mailer_helper_get_email */
mailer_helper_get_email(char const * header)76 char * mailer_helper_get_email(char const * header)
77 {
78 char * ret;
79 size_t len;
80 char * buf = NULL;
81
82 if(header == NULL)
83 return NULL;
84 len = strlen(header);
85 if((ret = malloc(len + 1)) == NULL || (buf = malloc(len + 1)) == NULL)
86 {
87 free(buf);
88 free(ret);
89 return NULL;
90 }
91 if(mailer_helper_is_email(header))
92 {
93 strcpy(ret, header);
94 free(buf);
95 return ret;
96 }
97 if(sscanf(header, "%[^(](%[^)])", ret, buf) == 2
98 || sscanf(header, "<%[^>]>", ret) == 1
99 || sscanf(header, "%[^<]<%[^>]>", buf, ret) == 2)
100 {
101 for(len = strlen(ret); len > 0
102 && isblank((unsigned char)ret[len - 1]); len--)
103 ret[len - 1] = '\0';
104 if(mailer_helper_is_email(ret))
105 {
106 free(buf);
107 return ret;
108 }
109 }
110 free(buf);
111 free(ret);
112 return NULL;
113 }
114
115
116 /* mailer_helper_get_name */
mailer_helper_get_name(char const * header)117 char * mailer_helper_get_name(char const * header)
118 {
119 char * ret;
120 size_t len;
121 char * buf = NULL;
122 int c;
123
124 if(header == NULL)
125 return NULL;
126 len = strlen(header);
127 if((ret = malloc(len + 1)) == NULL || (buf = malloc(len + 1)) == NULL)
128 {
129 free(buf);
130 free(ret);
131 return NULL;
132 }
133 if(mailer_helper_is_email(header))
134 {
135 strcpy(ret, header);
136 free(buf);
137 return ret;
138 }
139 if(sscanf(header, "%[^(](%[^)])", buf, ret) != 2
140 && sscanf(header, "<%[^>]>", ret) != 1
141 && sscanf(header, "%[^<]<%[^>]>", ret, buf) != 2)
142 {
143 free(buf);
144 free(ret);
145 return NULL;
146 }
147 free(buf);
148 /* right-trim spaces */
149 for(len = strlen(ret); --len > 0
150 && isspace((unsigned char)ret[len]); ret[len] = '\0');
151 /* remove surrounding quotes */
152 if((len = strlen(ret)) >= 2 && ((c = ret[0]) == '"' || c == '\'')
153 && ret[len - 1] == c)
154 {
155 memmove(ret, &ret[1], len - 2);
156 ret[len - 2] = '\0';
157 }
158 return ret;
159 }
160
161
162 /* mailer_helper_is_email */
mailer_helper_is_email(char const * header)163 int mailer_helper_is_email(char const * header)
164 {
165 size_t i = 0;
166 int c;
167
168 /* FIXME this is neither strict nor standard at the moment */
169 for(i = 0; (c = (unsigned char)header[i]) != '@'; i++)
170 if(c == '\0')
171 return 0;
172 else if(!isalnum(c) && c != '.' && c != '_')
173 return 0;
174 for(i++; (c = (unsigned char)header[i]) != '\0'; i++)
175 if(!isalnum(c) && c != '.' && c != '_')
176 return 0;
177 return 1;
178 }
179