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