see ChangeLog
Showing
13 changed files
with
337 additions
and
26 deletions
... | @@ -79,7 +79,13 @@ imap4d_copy0 (char *arg, int isuid, char *resp, size_t resplen) | ... | @@ -79,7 +79,13 @@ imap4d_copy0 (char *arg, int isuid, char *resp, size_t resplen) |
79 | mailbox_name = strdup ((pw) ? pw->pw_name : ""); | 79 | mailbox_name = strdup ((pw) ? pw->pw_name : ""); |
80 | } | 80 | } |
81 | else | 81 | else |
82 | mailbox_name = util_getfullpath (name, delim); | 82 | mailbox_name = namespace_getfullpath (name, delim); |
83 | |||
84 | if (!mailbox_name) | ||
85 | { | ||
86 | snprintf (resp, resplen, "NO Create failed."); | ||
87 | return RESP_NO; | ||
88 | } | ||
83 | 89 | ||
84 | /* If the destination mailbox does not exist, a server should return | 90 | /* If the destination mailbox does not exist, a server should return |
85 | an error. */ | 91 | an error. */ | ... | ... |
... | @@ -52,7 +52,10 @@ imap4d_create (struct imap4d_command *command, char *arg) | ... | @@ -52,7 +52,10 @@ imap4d_create (struct imap4d_command *command, char *arg) |
52 | return util_finish (command, RESP_BAD, "Already exist"); | 52 | return util_finish (command, RESP_BAD, "Already exist"); |
53 | 53 | ||
54 | /* Allocates memory. */ | 54 | /* Allocates memory. */ |
55 | name = util_getfullpath (name, delim); | 55 | name = namespace_getfullpath (name, delim); |
56 | |||
57 | if (!name) | ||
58 | return util_finish (command, RESP_NO, "Can not create mailbox"); | ||
56 | 59 | ||
57 | /* It will fail if the mailbox already exists. */ | 60 | /* It will fail if the mailbox already exists. */ |
58 | if (access (name, F_OK) != 0) | 61 | if (access (name, F_OK) != 0) | ... | ... |
... | @@ -44,7 +44,9 @@ imap4d_delete (struct imap4d_command *command, char *arg) | ... | @@ -44,7 +44,9 @@ imap4d_delete (struct imap4d_command *command, char *arg) |
44 | return util_finish (command, RESP_NO, "Already exist"); | 44 | return util_finish (command, RESP_NO, "Already exist"); |
45 | 45 | ||
46 | /* Allocates memory. */ | 46 | /* Allocates memory. */ |
47 | name = util_getfullpath (name, delim); | 47 | name = namespace_getfullpath (name, delim); |
48 | if (!name) | ||
49 | return util_finish (command, RESP_NO, "Can not remove"); | ||
48 | 50 | ||
49 | if (remove (name) != 0) | 51 | if (remove (name) != 0) |
50 | { | 52 | { | ... | ... |
... | @@ -32,12 +32,14 @@ static struct option long_options[] = | ... | @@ -32,12 +32,14 @@ static struct option long_options[] = |
32 | {"help", no_argument, 0, 'h'}, | 32 | {"help", no_argument, 0, 'h'}, |
33 | {"inetd", no_argument, 0, 'i'}, | 33 | {"inetd", no_argument, 0, 'i'}, |
34 | {"port", required_argument, 0, 'p'}, | 34 | {"port", required_argument, 0, 'p'}, |
35 | {"other-namespace", required_argument, 0, 'O'}, | ||
36 | {"shared-namespace", required_argument, 0, 'S'}, | ||
35 | {"timeout", required_argument, 0, 't'}, | 37 | {"timeout", required_argument, 0, 't'}, |
36 | {"version", no_argument, 0, 'v'}, | 38 | {"version", no_argument, 0, 'v'}, |
37 | {0, 0, 0, 0} | 39 | {0, 0, 0, 0} |
38 | }; | 40 | }; |
39 | 41 | ||
40 | const char *short_options ="d::hip:t:v"; | 42 | const char *short_options ="d::hip:t:vO:P:S:"; |
41 | 43 | ||
42 | static int syslog_error_printer __P ((const char *fmt, va_list ap)); | 44 | static int syslog_error_printer __P ((const char *fmt, va_list ap)); |
43 | static int imap4d_mainloop __P ((int, int)); | 45 | static int imap4d_mainloop __P ((int, int)); |
... | @@ -90,6 +92,14 @@ main (int argc, char **argv) | ... | @@ -90,6 +92,14 @@ main (int argc, char **argv) |
90 | port = strtoul (optarg, NULL, 10); | 92 | port = strtoul (optarg, NULL, 10); |
91 | break; | 93 | break; |
92 | 94 | ||
95 | case 'O': | ||
96 | set_namespace (NS_OTHER, optarg); | ||
97 | break; | ||
98 | |||
99 | case 'S': | ||
100 | set_namespace (NS_SHARED, optarg); | ||
101 | break; | ||
102 | |||
93 | case 't': | 103 | case 't': |
94 | timeout = strtoul (optarg, NULL, 10); | 104 | timeout = strtoul (optarg, NULL, 10); |
95 | break; | 105 | break; | ... | ... |
... | @@ -132,11 +132,18 @@ struct imap4d_command | ... | @@ -132,11 +132,18 @@ struct imap4d_command |
132 | #define ERR_TIMEOUT 3 | 132 | #define ERR_TIMEOUT 3 |
133 | #define ERR_SIGNAL 4 | 133 | #define ERR_SIGNAL 4 |
134 | 134 | ||
135 | /* Namespace numbers */ | ||
136 | #define NS_PRIVATE 0 | ||
137 | #define NS_OTHER 1 | ||
138 | #define NS_SHARED 2 | ||
139 | #define NS_MAX 3 | ||
140 | |||
135 | extern struct imap4d_command imap4d_command_table[]; | 141 | extern struct imap4d_command imap4d_command_table[]; |
136 | extern FILE *ofile; | 142 | extern FILE *ofile; |
137 | extern unsigned int timeout; | 143 | extern unsigned int timeout; |
138 | extern mailbox_t mbox; | 144 | extern mailbox_t mbox; |
139 | extern char *homedir; | 145 | extern char *homedir; |
146 | extern char *rootdir; | ||
140 | extern int state; | 147 | extern int state; |
141 | extern volatile size_t children; | 148 | extern volatile size_t children; |
142 | 149 | ||
... | @@ -169,6 +176,7 @@ extern int imap4d_store0 __P ((char *, int, char *, size_t)); | ... | @@ -169,6 +176,7 @@ extern int imap4d_store0 __P ((char *, int, char *, size_t)); |
169 | extern int imap4d_subscribe __P ((struct imap4d_command *, char *)); | 176 | extern int imap4d_subscribe __P ((struct imap4d_command *, char *)); |
170 | extern int imap4d_uid __P ((struct imap4d_command *, char *)); | 177 | extern int imap4d_uid __P ((struct imap4d_command *, char *)); |
171 | extern int imap4d_unsubscribe __P ((struct imap4d_command *, char *)); | 178 | extern int imap4d_unsubscribe __P ((struct imap4d_command *, char *)); |
179 | extern int imap4d_namespace __P ((struct imap4d_command *, char *)); | ||
172 | 180 | ||
173 | /* Synchronisation on simultenous access. */ | 181 | /* Synchronisation on simultenous access. */ |
174 | extern int imap4d_sync __P ((void)); | 182 | extern int imap4d_sync __P ((void)); | ... | ... |
... | @@ -141,7 +141,13 @@ imap4d_list (struct imap4d_command *command, char *arg) | ... | @@ -141,7 +141,13 @@ imap4d_list (struct imap4d_command *command, char *arg) |
141 | } | 141 | } |
142 | 142 | ||
143 | /* Allocates. */ | 143 | /* Allocates. */ |
144 | cwd = util_getfullpath (ref, delim); | 144 | cwd = namespace_checkfullpath (ref, wcard, delim); |
145 | if (!cwd) | ||
146 | { | ||
147 | free (ref); | ||
148 | return util_finish (command, RESP_NO, | ||
149 | "The requested item could not be found."); | ||
150 | } | ||
145 | 151 | ||
146 | /* If wcard match inbox return it too, part of the list. */ | 152 | /* If wcard match inbox return it too, part of the list. */ |
147 | if (!*ref && (match ("INBOX", wcard, delim) | 153 | if (!*ref && (match ("INBOX", wcard, delim) |
... | @@ -156,6 +162,7 @@ imap4d_list (struct imap4d_command *command, char *arg) | ... | @@ -156,6 +162,7 @@ imap4d_list (struct imap4d_command *command, char *arg) |
156 | free (cwd); | 162 | free (cwd); |
157 | free (ref); | 163 | free (ref); |
158 | } | 164 | } |
165 | |||
159 | return util_finish (command, RESP_OK, "Completed"); | 166 | return util_finish (command, RESP_OK, "Completed"); |
160 | } | 167 | } |
161 | 168 | ... | ... |
... | @@ -136,9 +136,10 @@ imap4d_login (struct imap4d_command *command, char *arg) | ... | @@ -136,9 +136,10 @@ imap4d_login (struct imap4d_command *command, char *arg) |
136 | if (pw->pw_uid > 1) | 136 | if (pw->pw_uid > 1) |
137 | setuid (pw->pw_uid); | 137 | setuid (pw->pw_uid); |
138 | 138 | ||
139 | homedir = strdup (pw->pw_dir); | 139 | homedir = util_normalize_path (strdup (pw->pw_dir), "/"); |
140 | /* FIXME: Check for errors. */ | 140 | /* FIXME: Check for errors. */ |
141 | chdir (homedir); | 141 | chdir (homedir); |
142 | namespace_init(pw->pw_dir); | ||
142 | syslog (LOG_INFO, "User '%s' logged in", username); | 143 | syslog (LOG_INFO, "User '%s' logged in", username); |
143 | return util_finish (command, RESP_OK, "Completed"); | 144 | return util_finish (command, RESP_OK, "Completed"); |
144 | } | 145 | } | ... | ... |
... | @@ -26,5 +26,6 @@ imap4d_noop (struct imap4d_command *command, char *arg) | ... | @@ -26,5 +26,6 @@ imap4d_noop (struct imap4d_command *command, char *arg) |
26 | return util_finish (command, RESP_BAD, "Wrong state"); | 26 | return util_finish (command, RESP_BAD, "Wrong state"); |
27 | if (util_getword (arg, &sp)) | 27 | if (util_getword (arg, &sp)) |
28 | return util_finish (command, RESP_BAD, "Too many args"); | 28 | return util_finish (command, RESP_BAD, "Too many args"); |
29 | imap4d_select_status(); | ||
29 | return util_finish (command, RESP_OK, "Completed"); | 30 | return util_finish (command, RESP_OK, "Completed"); |
30 | } | 31 | } | ... | ... |
... | @@ -50,7 +50,9 @@ imap4d_rename (struct imap4d_command *command, char *arg) | ... | @@ -50,7 +50,9 @@ imap4d_rename (struct imap4d_command *command, char *arg) |
50 | return util_finish (command, RESP_NO, "Name Inbox is reservered"); | 50 | return util_finish (command, RESP_NO, "Name Inbox is reservered"); |
51 | 51 | ||
52 | /* Allocates memory. */ | 52 | /* Allocates memory. */ |
53 | newname = util_getfullpath (newname, delim); | 53 | newname = namespace_getfullpath (newname, delim); |
54 | if (!newname) | ||
55 | return util_finish (command, RESP_NO, "Permission denied"); | ||
54 | 56 | ||
55 | /* It is an error to attempt to rename from a mailbox name that already | 57 | /* It is an error to attempt to rename from a mailbox name that already |
56 | exist. */ | 58 | exist. */ |
... | @@ -118,14 +120,15 @@ imap4d_rename (struct imap4d_command *command, char *arg) | ... | @@ -118,14 +120,15 @@ imap4d_rename (struct imap4d_command *command, char *arg) |
118 | return util_finish (command, RESP_OK, "Already exist"); | 120 | return util_finish (command, RESP_OK, "Already exist"); |
119 | } | 121 | } |
120 | 122 | ||
121 | oldname = util_getfullpath (oldname, delim); | 123 | oldname = namespace_getfullpath (oldname, delim); |
122 | 124 | ||
123 | /* It must exist. */ | 125 | /* It must exist. */ |
124 | if (rename (oldname, newname) != 0) | 126 | if (!oldname || rename (oldname, newname) != 0) |
125 | { | 127 | { |
126 | rc = RESP_NO; | 128 | rc = RESP_NO; |
127 | msg = "Failed"; | 129 | msg = "Failed"; |
128 | } | 130 | } |
131 | if (oldname) | ||
129 | free (oldname); | 132 | free (oldname); |
130 | free (newname); | 133 | free (newname); |
131 | return util_finish (command, rc, msg); | 134 | return util_finish (command, rc, msg); | ... | ... |
... | @@ -17,6 +17,8 @@ | ... | @@ -17,6 +17,8 @@ |
17 | 17 | ||
18 | #include "imap4d.h" | 18 | #include "imap4d.h" |
19 | 19 | ||
20 | static int select_flags; | ||
21 | |||
20 | /* select ::= "SELECT" SPACE mailbox */ | 22 | /* select ::= "SELECT" SPACE mailbox */ |
21 | 23 | ||
22 | int | 24 | int |
... | @@ -67,17 +69,39 @@ imap4d_select0 (struct imap4d_command *command, char *arg, int flags) | ... | @@ -67,17 +69,39 @@ imap4d_select0 (struct imap4d_command *command, char *arg, int flags) |
67 | mailbox_name = strdup ("/dev/null"); | 69 | mailbox_name = strdup ("/dev/null"); |
68 | } | 70 | } |
69 | else | 71 | else |
70 | mailbox_name = util_getfullpath (mailbox_name, "/"); | 72 | mailbox_name = namespace_getfullpath (mailbox_name, "/"); |
73 | |||
74 | if (!mailbox_name) | ||
75 | return util_finish (command, RESP_NO, "Couldn't open mailbox"); | ||
71 | 76 | ||
72 | if (mailbox_create (&mbox, mailbox_name) == 0 | 77 | if (mailbox_create (&mbox, mailbox_name) == 0 |
73 | && mailbox_open (mbox, flags) == 0) | 78 | && mailbox_open (mbox, flags) == 0) |
74 | { | 79 | { |
80 | free (mailbox_name); | ||
81 | select_flags = flags; | ||
82 | state = STATE_SEL; | ||
83 | imap4d_select_status(); | ||
84 | /* Need to set the state explicitely for select. */ | ||
85 | return util_send ("%s OK [%s] %s Completed\r\n", command->tag, | ||
86 | (MU_STREAM_READ == flags) ? | ||
87 | "READ-ONLY" : "READ-WRITE", command->name); | ||
88 | } | ||
89 | status = util_finish (command, RESP_NO, "Couldn't open %s", mailbox_name); | ||
90 | free (mailbox_name); | ||
91 | return status; | ||
92 | } | ||
93 | |||
94 | /* The code is shared between select and noop */ | ||
95 | void | ||
96 | imap4d_select_status() | ||
97 | { | ||
75 | const char *mflags = "\\Answered \\Flagged \\Deleted \\Seen \\Draft"; | 98 | const char *mflags = "\\Answered \\Flagged \\Deleted \\Seen \\Draft"; |
76 | const char *pflags = "\\Answered \\Deleted \\Seen"; | 99 | const char *pflags = "\\Answered \\Deleted \\Seen"; |
77 | unsigned long uidvalidity = 0; | 100 | unsigned long uidvalidity = 0; |
78 | size_t count = 0, recent = 0, unseen = 0, uidnext = 0; | 101 | size_t count = 0, recent = 0, unseen = 0, uidnext = 0; |
79 | 102 | ||
80 | free (mailbox_name); | 103 | if (state != STATE_SEL) |
104 | return; | ||
81 | 105 | ||
82 | mailbox_uidvalidity (mbox, &uidvalidity); | 106 | mailbox_uidvalidity (mbox, &uidvalidity); |
83 | mailbox_uidnext (mbox, &uidnext); | 107 | mailbox_uidnext (mbox, &uidnext); |
... | @@ -95,17 +119,8 @@ imap4d_select0 (struct imap4d_command *command, char *arg, int flags) | ... | @@ -95,17 +119,8 @@ imap4d_select0 (struct imap4d_command *command, char *arg, int flags) |
95 | /* FIXME: | 119 | /* FIXME: |
96 | - '\*' can be supported if we use the attribute_set userflag() | 120 | - '\*' can be supported if we use the attribute_set userflag() |
97 | - Answered is still not set in the mailbox code. */ | 121 | - Answered is still not set in the mailbox code. */ |
98 | if (flags == MU_STREAM_READ) | 122 | if (select_flags & MU_STREAM_READ) |
99 | util_out (RESP_OK, "[PERMANENTFLAGS ()] No Permanent flags"); | 123 | util_out (RESP_OK, "[PERMANENTFLAGS ()] No Permanent flags"); |
100 | else | 124 | else |
101 | util_out (RESP_OK, "[PERMANENTFLAGS (%s)] Permanent flags", pflags); | 125 | util_out (RESP_OK, "[PERMANENTFLAGS (%s)] Permanent flags", pflags); |
102 | /* Need to set the state explicitely for select. */ | ||
103 | state = STATE_SEL; | ||
104 | return util_send ("%s OK [%s] %s Completed\r\n", command->tag, | ||
105 | (MU_STREAM_READ == flags) ? | ||
106 | "READ-ONLY" : "READ-WRITE", command->name); | ||
107 | } | ||
108 | status = util_finish (command, RESP_NO, "Couldn't open %s", mailbox_name); | ||
109 | free (mailbox_name); | ||
110 | return status; | ||
111 | } | 126 | } | ... | ... |
... | @@ -51,7 +51,10 @@ imap4d_status (struct imap4d_command *command, char *arg) | ... | @@ -51,7 +51,10 @@ imap4d_status (struct imap4d_command *command, char *arg) |
51 | mailbox_name = strdup ((pw) ? pw->pw_name : ""); | 51 | mailbox_name = strdup ((pw) ? pw->pw_name : ""); |
52 | } | 52 | } |
53 | else | 53 | else |
54 | mailbox_name = util_getfullpath (name, delim); | 54 | mailbox_name = namespace_getfullpath (name, delim); |
55 | |||
56 | if (!mailbox_name) | ||
57 | return util_finish (command, RESP_NO, "Error opening mailbox"); | ||
55 | 58 | ||
56 | status = mailbox_create_default (&smbox, mailbox_name); | 59 | status = mailbox_create_default (&smbox, mailbox_name); |
57 | if (status == 0) | 60 | if (status == 0) | ... | ... |
... | @@ -138,6 +138,7 @@ imap4d_store0 (char *arg, int isuid, char *resp, size_t resplen) | ... | @@ -138,6 +138,7 @@ imap4d_store0 (char *arg, int isuid, char *resp, size_t resplen) |
138 | } | 138 | } |
139 | attribute_set_flags (attr, type); | 139 | attribute_set_flags (attr, type); |
140 | } | 140 | } |
141 | attribute_set_flags (attr, MU_ATTRIBUTE_MODIFIED); | ||
141 | flags = realloc (flags, strlen (flags) + strlen (item) + 2); | 142 | flags = realloc (flags, strlen (flags) + strlen (item) + 2); |
142 | if (*flags) | 143 | if (*flags) |
143 | strcat (flags, " "); | 144 | strcat (flags, " "); | ... | ... |
... | @@ -152,6 +152,71 @@ util_tilde_expansion (const char *ref, const char *delim) | ... | @@ -152,6 +152,71 @@ util_tilde_expansion (const char *ref, const char *delim) |
152 | return p; | 152 | return p; |
153 | } | 153 | } |
154 | 154 | ||
155 | /* util_normalize_path: convert pathname containig relative paths specs (../) | ||
156 | into an equivalent absolute path. Strip trailing delimiter if present, | ||
157 | unless it is the only character left. E.g.: | ||
158 | |||
159 | /home/user/../smith --> /home/smith | ||
160 | /home/user/../.. --> / | ||
161 | |||
162 | FIXME: delim is superfluous. The function deals with unix filesystem | ||
163 | paths, so delim should be always "/" */ | ||
164 | char * | ||
165 | util_normalize_path (char *path, const char *delim) | ||
166 | { | ||
167 | int len; | ||
168 | char *p; | ||
169 | |||
170 | if (!path) | ||
171 | return path; | ||
172 | |||
173 | len = strlen (path); | ||
174 | |||
175 | /* Empty string is returned as is */ | ||
176 | if (len == 0) | ||
177 | return path; | ||
178 | |||
179 | /* delete trailing delimiter if any */ | ||
180 | if (len && path[len-1] == delim[0]) | ||
181 | path[len-1] = 0; | ||
182 | |||
183 | /* Eliminate any /../ */ | ||
184 | for (p = strchr (path, '.'); p; p = strchr (p, '.')) | ||
185 | { | ||
186 | if (p > path && p[-1] == delim[0]) | ||
187 | { | ||
188 | if (p[1] == '.' && (p[2] == 0 || p[2] == delim[0])) | ||
189 | /* found */ | ||
190 | { | ||
191 | char *q, *s; | ||
192 | |||
193 | /* Find previous delimiter */ | ||
194 | for (q = p-2; *q != delim[0] && q >= path; q--) | ||
195 | ; | ||
196 | |||
197 | if (q < path) | ||
198 | break; | ||
199 | /* Copy stuff */ | ||
200 | s = p + 2; | ||
201 | p = q; | ||
202 | while (*q++ = *s++) | ||
203 | ; | ||
204 | continue; | ||
205 | } | ||
206 | } | ||
207 | |||
208 | p++; | ||
209 | } | ||
210 | |||
211 | if (path[0] == 0) | ||
212 | { | ||
213 | path[0] = delim[0]; | ||
214 | path[1] = 0; | ||
215 | } | ||
216 | |||
217 | return path; | ||
218 | } | ||
219 | |||
155 | /* Get the absolute path. */ | 220 | /* Get the absolute path. */ |
156 | /* NOTE: Path is allocated and must be free()d by the caller. */ | 221 | /* NOTE: Path is allocated and must be free()d by the caller. */ |
157 | char * | 222 | char * |
... | @@ -165,7 +230,7 @@ util_getfullpath (char *name, const char *delim) | ... | @@ -165,7 +230,7 @@ util_getfullpath (char *name, const char *delim) |
165 | free (p); | 230 | free (p); |
166 | p = s; | 231 | p = s; |
167 | } | 232 | } |
168 | return p; | 233 | return util_normalize_path (p, delim); |
169 | } | 234 | } |
170 | 235 | ||
171 | /* Return in set an allocated array contain (n) numbers, for imap messsage set | 236 | /* Return in set an allocated array contain (n) numbers, for imap messsage set |
... | @@ -226,7 +291,7 @@ util_msgset (char *s, size_t **set, int *n, int isuid) | ... | @@ -226,7 +291,7 @@ util_msgset (char *s, size_t **set, int *n, int isuid) |
226 | { | 291 | { |
227 | long tmp = low; | 292 | long tmp = low; |
228 | tmp -= 2; | 293 | tmp -= 2; |
229 | if (tmp <= 0 || val == 0) | 294 | if (tmp < 0 || val == 0) |
230 | { | 295 | { |
231 | free (*set); | 296 | free (*set); |
232 | *n = 0; | 297 | *n = 0; |
... | @@ -245,7 +310,7 @@ util_msgset (char *s, size_t **set, int *n, int isuid) | ... | @@ -245,7 +310,7 @@ util_msgset (char *s, size_t **set, int *n, int isuid) |
245 | } | 310 | } |
246 | else | 311 | else |
247 | { | 312 | { |
248 | status = add2set(set, n, val); | 313 | status = add2set (set, n, val); |
249 | if (status != 0) | 314 | if (status != 0) |
250 | return status; | 315 | return status; |
251 | } | 316 | } |
... | @@ -397,7 +462,7 @@ util_finish (struct imap4d_command *command, int rc, const char *format, ...) | ... | @@ -397,7 +462,7 @@ util_finish (struct imap4d_command *command, int rc, const char *format, ...) |
397 | 462 | ||
398 | va_start (ap, format); | 463 | va_start (ap, format); |
399 | status = vfprintf (ofile, buf, ap); | 464 | status = vfprintf (ofile, buf, ap); |
400 | va_end(ap); | 465 | va_end (ap); |
401 | free (buf); | 466 | free (buf); |
402 | /* Reset the state. */ | 467 | /* Reset the state. */ |
403 | new_state = (rc == RESP_OK) ? command->success : command->failure; | 468 | new_state = (rc == RESP_OK) ? command->success : command->failure; |
... | @@ -610,3 +675,189 @@ add2set (size_t **set, int *n, unsigned long val) | ... | @@ -610,3 +675,189 @@ add2set (size_t **set, int *n, unsigned long val) |
610 | (*n)++; | 675 | (*n)++; |
611 | return 0; | 676 | return 0; |
612 | } | 677 | } |
678 | |||
679 | static const char *months[] = | ||
680 | { | ||
681 | "Jan", "Feb", "Mar", "Apr", "May", "Jun", | ||
682 | "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" | ||
683 | }; | ||
684 | |||
685 | #define c2d(c) (c-'0') | ||
686 | |||
687 | int | ||
688 | util_parse_internal_date (char *date, time_t *timep) | ||
689 | { | ||
690 | struct tm tm; | ||
691 | char *save; | ||
692 | int n, i; | ||
693 | int year, day, hour, min, sec; | ||
694 | char mon[4]; | ||
695 | char sign[2]; | ||
696 | char tzs[6]; | ||
697 | time_t time; | ||
698 | |||
699 | memset (&tm, 0, sizeof (tm)); | ||
700 | n = sscanf (date, "%2d-%3s-%4d %2d:%2d:%2d %5s\n", | ||
701 | &day, mon, &year, | ||
702 | &hour, &min, &sec, &tzs); | ||
703 | |||
704 | switch (n) | ||
705 | { | ||
706 | case 3: | ||
707 | case 6: | ||
708 | case 7: break; | ||
709 | default: return 1; | ||
710 | } | ||
711 | |||
712 | tm.tm_mday = day; | ||
713 | for (i = 0; i < 11; i++) | ||
714 | if (strncmp (months[i], mon, 3) == 0) | ||
715 | break; | ||
716 | if (i == 12) | ||
717 | return 1; | ||
718 | tm.tm_mon = i; | ||
719 | tm.tm_year = (year < 1900) ? year : year - 1900; | ||
720 | |||
721 | if (n >= 6) | ||
722 | { | ||
723 | tm.tm_hour = hour; | ||
724 | tm.tm_min = min; | ||
725 | tm.tm_sec = sec; | ||
726 | } | ||
727 | |||
728 | tm.tm_isdst = -1; /* unknown. */ | ||
729 | |||
730 | time = mktime (&tm); | ||
731 | if (time == (time_t) -1) | ||
732 | return 2; | ||
733 | |||
734 | if (n == 7) | ||
735 | { | ||
736 | int sign; | ||
737 | int tz; | ||
738 | |||
739 | if (strlen (tzs) != 5) | ||
740 | return 3; | ||
741 | |||
742 | for (i = 1; i <= 4; i++) | ||
743 | if (!isdigit (tzs[i])) | ||
744 | return 3; | ||
745 | |||
746 | tz = (c2d (tzs[1])*10 + c2d (tzs[2]))*60 + | ||
747 | c2d (tzs[3])*10 + c2d (tzs[4]); | ||
748 | if (tzs[0] == '-') | ||
749 | tz = -tz; | ||
750 | else if (tzs[0] != '+') | ||
751 | return 4; | ||
752 | time -= tz*60; | ||
753 | } | ||
754 | *timep = time; | ||
755 | return 0; | ||
756 | } | ||
757 | |||
758 | int | ||
759 | util_parse_header_date (char *date, time_t *timep) | ||
760 | { | ||
761 | struct tm tm; | ||
762 | char *save; | ||
763 | int n, i; | ||
764 | int year, day, hour, min, sec; | ||
765 | char wday[5]; | ||
766 | char mon[4]; | ||
767 | char sign[2]; | ||
768 | char tzs[6]; | ||
769 | time_t time; | ||
770 | |||
771 | memset (&tm, 0, sizeof (tm)); | ||
772 | n = sscanf (date, "%3s, %2d %3s %4d %2d:%2d:%2d %5s", | ||
773 | wday, &day, mon, &year, | ||
774 | &hour, &min, &sec, &tzs); | ||
775 | |||
776 | if (n < 7) | ||
777 | return 1; | ||
778 | |||
779 | tm.tm_mday = day; | ||
780 | for (i = 0; i < 11; i++) | ||
781 | if (strncmp (months[i], mon, 3) == 0) | ||
782 | break; | ||
783 | if (i == 12) | ||
784 | return 1; | ||
785 | tm.tm_mon = i; | ||
786 | tm.tm_year = (year < 1900) ? year : year - 1900; | ||
787 | |||
788 | if (n >= 6) | ||
789 | { | ||
790 | tm.tm_hour = hour; | ||
791 | tm.tm_min = min; | ||
792 | tm.tm_sec = sec; | ||
793 | } | ||
794 | |||
795 | tm.tm_isdst = -1; /* unknown. */ | ||
796 | |||
797 | time = mktime (&tm); | ||
798 | if (time == (time_t) -1) | ||
799 | return 2; | ||
800 | |||
801 | if (n == 8) | ||
802 | { | ||
803 | int sign; | ||
804 | int tz; | ||
805 | |||
806 | if (strlen (tzs) != 5) | ||
807 | return 3; | ||
808 | |||
809 | for (i = 1; i <= 4; i++) | ||
810 | if (!isdigit (tzs[i])) | ||
811 | return 3; | ||
812 | |||
813 | tz = (c2d (tzs[1])*10 + c2d (tzs[2]))*60 + | ||
814 | c2d (tzs[3])*10 + c2d (tzs[4]); | ||
815 | if (tzs[0] == '-') | ||
816 | tz = -tz; | ||
817 | else if (tzs[0] != '+') | ||
818 | return 4; | ||
819 | time -= tz*60; | ||
820 | } | ||
821 | *timep = time; | ||
822 | return 0; | ||
823 | } | ||
824 | |||
825 | int | ||
826 | util_parse_rfc822_date (char *date, time_t *timep) | ||
827 | { | ||
828 | int year, mon, day, hour, min, sec; | ||
829 | int offt; | ||
830 | int i; | ||
831 | struct tm tm; | ||
832 | char month[5]; | ||
833 | char wday[5]; | ||
834 | |||
835 | month[0] = '\0'; | ||
836 | wday[0] = '\0'; | ||
837 | day = mon = year = hour = min = sec = offt = 0; | ||
838 | |||
839 | /* RFC822 Date: format. */ | ||
840 | if (sscanf (date, "%3s %3s %2d %2d:%2d:%2d %d\n", wday, month, &day, | ||
841 | &hour, &min, &sec, &year) != 7) | ||
842 | return 1; | ||
843 | tm.tm_sec = sec; | ||
844 | tm.tm_min = min; | ||
845 | tm.tm_hour = hour; | ||
846 | for (i = 0; i < 12; i++) | ||
847 | { | ||
848 | if (strncasecmp (month, months[i], 3) == 0) | ||
849 | { | ||
850 | mon = i; | ||
851 | break; | ||
852 | } | ||
853 | } | ||
854 | tm.tm_mday = day; | ||
855 | tm.tm_mon = mon; | ||
856 | tm.tm_year = (year > 1900) ? year - 1900 : year; | ||
857 | tm.tm_yday = 0; /* unknown. */ | ||
858 | tm.tm_wday = 0; /* unknown. */ | ||
859 | tm.tm_isdst = -1; /* unknown. */ | ||
860 | /* What to do the timezone? */ | ||
861 | *timep = mktime (&tm); | ||
862 | return 0; | ||
863 | } | ... | ... |
-
Please register or sign in to post a comment