libetpan - fdik
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

7836 lines
158 KiB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
  1. /*
  2. * libEtPan! -- a mail stuff library
  3. *
  4. * Copyright (C) 2001, 2005 - DINH Viet Hoa
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the libEtPan! project nor the names of its
  16. * contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
  20. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
  23. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  25. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  26. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  27. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  28. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  29. * SUCH DAMAGE.
  30. */
  31. /*
  32. * $Id: mailimf.c,v 1.50 2011/06/20 23:25:26 hoa Exp $
  33. */
  34. #ifdef HAVE_CONFIG_H
  35. # include <config.h>
  36. #endif
  37. #include "mailimf.h"
  38. /*
  39. RFC 2822
  40. RFC 2821 ...
  41. A message-originating SMTP system SHOULD NOT send a message that
  42. already contains a Return-path header. SMTP servers performing a
  43. relay function MUST NOT inspect the message data, and especially not
  44. to the extent needed to determine if Return-path headers are present.
  45. SMTP servers making final delivery MAY remove Return-path headers
  46. before adding their own.
  47. */
  48. #include <ctype.h>
  49. #include "mmapstring.h"
  50. #include <stdlib.h>
  51. #include <string.h>
  52. #include "mailmime_decode.h"
  53. #ifndef TRUE
  54. #define TRUE 1
  55. #endif
  56. #ifndef FALSE
  57. #define FALSE 0
  58. #endif
  59. static inline int is_dtext(char ch);
  60. static int mailimf_quoted_pair_parse(const char * message, size_t length,
  61. size_t * indx, char * result);
  62. static int mailimf_ccontent_parse(const char * message, size_t length,
  63. size_t * indx);
  64. static int
  65. mailimf_comment_fws_ccontent_parse(const char * message, size_t length,
  66. size_t * indx);
  67. static inline int mailimf_comment_parse(const char * message, size_t length,
  68. size_t * indx);
  69. static int mailimf_qcontent_parse(const char * message, size_t length,
  70. size_t * indx, char * ch);
  71. static int mailimf_phrase_parse(const char * message, size_t length,
  72. size_t * indx, char ** result);
  73. static int mailimf_unstructured_parse(const char * message, size_t length,
  74. size_t * indx, char ** result);
  75. static int mailimf_ignore_unstructured_parse(const char * message, size_t length,
  76. size_t * indx);
  77. static int mailimf_day_of_week_parse(const char * message, size_t length,
  78. size_t * indx, int * result);
  79. static int mailimf_day_name_parse(const char * message, size_t length,
  80. size_t * indx, int * result);
  81. static int mailimf_date_parse(const char * message, size_t length,
  82. size_t * indx,
  83. int * pday, int * pmonth, int * pyear);
  84. static int mailimf_year_parse(const char * message, size_t length,
  85. size_t * indx, int * result);
  86. static int mailimf_month_parse(const char * message, size_t length,
  87. size_t * indx, int * result);
  88. static int mailimf_month_name_parse(const char * message, size_t length,
  89. size_t * indx, int * result);
  90. static int mailimf_day_parse(const char * message, size_t length,
  91. size_t * indx, int * result);
  92. static int mailimf_time_parse(const char * message, size_t length,
  93. size_t * indx,
  94. int * phour, int * pmin,
  95. int * psec,
  96. int * zone);
  97. static int mailimf_time_of_day_parse(const char * message, size_t length,
  98. size_t * indx,
  99. int * phour, int * pmin,
  100. int * psec);
  101. static int mailimf_hour_parse(const char * message, size_t length,
  102. size_t * indx, int * result);
  103. static int mailimf_minute_parse(const char * message, size_t length,
  104. size_t * indx, int * result);
  105. static int mailimf_second_parse(const char * message, size_t length,
  106. size_t * indx, int * result);
  107. static int mailimf_zone_parse(const char * message, size_t length,
  108. size_t * indx, int * result);
  109. static int mailimf_name_addr_parse(const char * message, size_t length,
  110. size_t * indx,
  111. char ** pdisplay_name,
  112. char ** pangle_addr);
  113. static int mailimf_angle_addr_parse(const char * message, size_t length,
  114. size_t * indx, char ** result);
  115. static int mailimf_group_parse(const char * message, size_t length,
  116. size_t * indx,
  117. struct mailimf_group ** result);
  118. static int mailimf_display_name_parse(const char * message, size_t length,
  119. size_t * indx, char ** result);
  120. static int mailimf_addr_spec_parse(const char * message, size_t length,
  121. size_t * indx,
  122. char ** address);
  123. static int
  124. mailimf_orig_date_parse(const char * message, size_t length,
  125. size_t * indx, struct mailimf_orig_date ** result);
  126. static int
  127. mailimf_from_parse(const char * message, size_t length,
  128. size_t * indx, struct mailimf_from ** result);
  129. static int
  130. mailimf_sender_parse(const char * message, size_t length,
  131. size_t * indx, struct mailimf_sender ** result);
  132. static int
  133. mailimf_reply_to_parse(const char * message, size_t length,
  134. size_t * indx, struct mailimf_reply_to ** result);
  135. static int
  136. mailimf_to_parse(const char * message, size_t length,
  137. size_t * indx, struct mailimf_to ** result);
  138. static int
  139. mailimf_cc_parse(const char * message, size_t length,
  140. size_t * indx, struct mailimf_cc ** result);
  141. static int
  142. mailimf_bcc_parse(const char * message, size_t length,
  143. size_t * indx, struct mailimf_bcc ** result);
  144. static int mailimf_message_id_parse(const char * message, size_t length,
  145. size_t * indx,
  146. struct mailimf_message_id ** result);
  147. static int
  148. mailimf_in_reply_to_parse(const char * message, size_t length,
  149. size_t * indx,
  150. struct mailimf_in_reply_to ** result);
  151. static int mailimf_unstrict_msg_id_parse(const char * message, size_t length,
  152. size_t * indx,
  153. char ** result);
  154. static int mailimf_subject_parse(const char * message, size_t length,
  155. size_t * indx,
  156. struct mailimf_subject ** result);
  157. static int mailimf_comments_parse(const char * message, size_t length,
  158. size_t * indx,
  159. struct mailimf_comments ** result);
  160. static int mailimf_keywords_parse(const char * message, size_t length,
  161. size_t * indx,
  162. struct mailimf_keywords ** result);
  163. static int
  164. mailimf_resent_date_parse(const char * message, size_t length,
  165. size_t * indx, struct mailimf_orig_date ** result);
  166. static int
  167. mailimf_resent_from_parse(const char * message, size_t length,
  168. size_t * indx, struct mailimf_from ** result);
  169. static int
  170. mailimf_resent_sender_parse(const char * message, size_t length,
  171. size_t * indx, struct mailimf_sender ** result);
  172. static int
  173. mailimf_resent_to_parse(const char * message, size_t length,
  174. size_t * indx, struct mailimf_to ** result);
  175. static int
  176. mailimf_resent_cc_parse(const char * message, size_t length,
  177. size_t * indx, struct mailimf_cc ** result);
  178. static int
  179. mailimf_resent_bcc_parse(const char * message, size_t length,
  180. size_t * indx, struct mailimf_bcc ** result);
  181. static int
  182. mailimf_resent_msg_id_parse(const char * message, size_t length,
  183. size_t * indx,
  184. struct mailimf_message_id ** result);
  185. static int mailimf_return_parse(const char * message, size_t length,
  186. size_t * indx,
  187. struct mailimf_return ** result);
  188. static int
  189. mailimf_path_parse(const char * message, size_t length,
  190. size_t * indx, struct mailimf_path ** result);
  191. static int
  192. mailimf_optional_field_parse(const char * message, size_t length,
  193. size_t * indx,
  194. struct mailimf_optional_field ** result);
  195. static int mailimf_field_name_parse(const char * message, size_t length,
  196. size_t * indx, char ** result);
  197. /* *************************************************************** */
  198. static inline int is_digit(char ch)
  199. {
  200. return (ch >= '0') && (ch <= '9');
  201. }
  202. static int mailimf_digit_parse(const char * message, size_t length,
  203. size_t * indx, int * result)
  204. {
  205. size_t cur_token;
  206. cur_token = * indx;
  207. if (cur_token >= length)
  208. return MAILIMF_ERROR_PARSE;
  209. if (is_digit(message[cur_token])) {
  210. * result = message[cur_token] - '0';
  211. cur_token ++;
  212. * indx = cur_token;
  213. return MAILIMF_NO_ERROR;
  214. }
  215. else
  216. return MAILIMF_ERROR_PARSE;
  217. }
  218. LIBETPAN_EXPORT
  219. int
  220. mailimf_number_parse(const char * message, size_t length,
  221. size_t * indx, uint32_t * result)
  222. {
  223. size_t cur_token;
  224. int digit;
  225. uint32_t number;
  226. int parsed;
  227. int r;
  228. cur_token = * indx;
  229. parsed = FALSE;
  230. number = 0;
  231. while (1) {
  232. r = mailimf_digit_parse(message, length, &cur_token, &digit);
  233. if (r != MAILIMF_NO_ERROR) {
  234. if (r == MAILIMF_ERROR_PARSE)
  235. break;
  236. else
  237. return r;
  238. }
  239. number *= 10;
  240. number += digit;
  241. parsed = TRUE;
  242. }
  243. if (!parsed)
  244. return MAILIMF_ERROR_PARSE;
  245. * result = number;
  246. * indx = cur_token;
  247. return MAILIMF_NO_ERROR;
  248. }
  249. LIBETPAN_EXPORT
  250. int mailimf_char_parse(const char * message, size_t length,
  251. size_t * indx, char token)
  252. {
  253. size_t cur_token;
  254. cur_token = * indx;
  255. if (cur_token >= length)
  256. return MAILIMF_ERROR_PARSE;
  257. if (message[cur_token] == token) {
  258. cur_token ++;
  259. * indx = cur_token;
  260. return MAILIMF_NO_ERROR;
  261. }
  262. else
  263. return MAILIMF_ERROR_PARSE;
  264. }
  265. LIBETPAN_EXPORT
  266. int mailimf_unstrict_char_parse(const char * message, size_t length,
  267. size_t * indx, char token)
  268. {
  269. size_t cur_token;
  270. int r;
  271. cur_token = * indx;
  272. r = mailimf_cfws_parse(message, length, &cur_token);
  273. if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
  274. return r;
  275. r = mailimf_char_parse(message, length, &cur_token, token);
  276. if (r != MAILIMF_NO_ERROR)
  277. return r;
  278. * indx = cur_token;
  279. return MAILIMF_NO_ERROR;
  280. }
  281. LIBETPAN_EXPORT
  282. int
  283. mailimf_token_case_insensitive_len_parse(const char * message, size_t length,
  284. size_t * indx, char * token,
  285. size_t token_length)
  286. {
  287. size_t cur_token;
  288. cur_token = * indx;
  289. if (cur_token + token_length - 1 >= length)
  290. return MAILIMF_ERROR_PARSE;
  291. if (strncasecmp(message + cur_token, token, token_length) == 0) {
  292. cur_token += token_length;
  293. * indx = cur_token;
  294. return MAILIMF_NO_ERROR;
  295. }
  296. else
  297. return MAILIMF_ERROR_PARSE;
  298. }
  299. static int mailimf_oparenth_parse(const char * message, size_t length,
  300. size_t * indx)
  301. {
  302. return mailimf_char_parse(message, length, indx, '(');
  303. }
  304. static int mailimf_cparenth_parse(const char * message, size_t length,
  305. size_t * indx)
  306. {
  307. return mailimf_char_parse(message, length, indx, ')');
  308. }
  309. static int mailimf_comma_parse(const char * message, size_t length,
  310. size_t * indx)
  311. {
  312. return mailimf_unstrict_char_parse(message, length, indx, ',');
  313. }
  314. static int mailimf_dquote_parse(const char * message, size_t length,
  315. size_t * indx)
  316. {
  317. return mailimf_char_parse(message, length, indx, '\"');
  318. }
  319. static int mailimf_colon_parse(const char * message, size_t length,
  320. size_t * indx)
  321. {
  322. return mailimf_unstrict_char_parse(message, length, indx, ':');
  323. }
  324. static int mailimf_semi_colon_parse(const char * message, size_t length,
  325. size_t * indx)
  326. {
  327. return mailimf_unstrict_char_parse(message, length, indx, ';');
  328. }
  329. static int mailimf_plus_parse(const char * message, size_t length,
  330. size_t * indx)
  331. {
  332. return mailimf_unstrict_char_parse(message, length, indx, '+');
  333. }
  334. static int mailimf_minus_parse(const char * message, size_t length,
  335. size_t * indx)
  336. {
  337. return mailimf_unstrict_char_parse(message, length, indx, '-');
  338. }
  339. static int mailimf_lower_parse(const char * message, size_t length,
  340. size_t * indx)
  341. {
  342. return mailimf_unstrict_char_parse(message, length, indx, '<');
  343. }
  344. static int mailimf_greater_parse(const char * message, size_t length,
  345. size_t * indx)
  346. {
  347. return mailimf_unstrict_char_parse(message, length, indx, '>');
  348. }
  349. static int mailimf_at_sign_parse(const char * message, size_t length,
  350. size_t * indx)
  351. {
  352. return mailimf_unstrict_char_parse(message, length, indx, '@');
  353. }
  354. static int mailimf_point_parse(const char * message, size_t length,
  355. size_t * indx)
  356. {
  357. return mailimf_unstrict_char_parse(message, length, indx, '.');
  358. }
  359. LIBETPAN_EXPORT
  360. int
  361. mailimf_custom_string_parse(const char * message, size_t length,
  362. size_t * indx, char ** result,
  363. int (* is_custom_char)(char))
  364. {
  365. size_t begin;
  366. size_t end;
  367. char * gstr;
  368. begin = * indx;
  369. end = begin;
  370. if (end >= length)
  371. return MAILIMF_ERROR_PARSE;
  372. while (is_custom_char(message[end])) {
  373. end ++;
  374. if (end >= length)
  375. break;
  376. }
  377. if (end != begin) {
  378. /*
  379. gstr = strndup(message + begin, end - begin);
  380. */
  381. gstr = malloc(end - begin + 1);
  382. if (gstr == NULL)
  383. return MAILIMF_ERROR_MEMORY;
  384. strncpy(gstr, message + begin, end - begin);
  385. gstr[end - begin] = '\0';
  386. * indx = end;
  387. * result = gstr;
  388. return MAILIMF_NO_ERROR;
  389. }
  390. else
  391. return MAILIMF_ERROR_PARSE;
  392. }
  393. typedef int mailimf_struct_parser(const char * message, size_t length,
  394. size_t * indx, void * result);
  395. typedef int mailimf_struct_destructor(void * result);
  396. static int
  397. mailimf_struct_multiple_parse(const char * message, size_t length,
  398. size_t * indx, clist ** result,
  399. mailimf_struct_parser * parser,
  400. mailimf_struct_destructor * destructor)
  401. {
  402. clist * struct_list;
  403. size_t cur_token;
  404. void * value;
  405. int r;
  406. int res;
  407. cur_token = * indx;
  408. r = parser(message, length, &cur_token, &value);
  409. if (r != MAILIMF_NO_ERROR) {
  410. res = r;
  411. goto err;
  412. }
  413. struct_list = clist_new();
  414. if (struct_list == NULL) {
  415. destructor(value);
  416. res = MAILIMF_ERROR_MEMORY;
  417. goto err;
  418. }
  419. r = clist_append(struct_list, value);
  420. if (r < 0) {
  421. destructor(value);
  422. res = MAILIMF_ERROR_MEMORY;
  423. goto free;
  424. }
  425. while (1) {
  426. r = parser(message, length, &cur_token, &value);
  427. if (r != MAILIMF_NO_ERROR) {
  428. if (r == MAILIMF_ERROR_PARSE)
  429. break;
  430. else {
  431. res = r;
  432. goto free;
  433. }
  434. }
  435. r = clist_append(struct_list, value);
  436. if (r < 0) {
  437. (*destructor)(value);
  438. res = MAILIMF_ERROR_MEMORY;
  439. goto free;
  440. }
  441. }
  442. * result = struct_list;
  443. * indx = cur_token;
  444. return MAILIMF_NO_ERROR;
  445. free:
  446. clist_foreach(struct_list, (clist_func) destructor, NULL);
  447. clist_free(struct_list);
  448. err:
  449. return res;
  450. }
  451. static int
  452. mailimf_struct_list_parse(const char * message, size_t length,
  453. size_t * indx, clist ** result,
  454. char symbol,
  455. mailimf_struct_parser * parser,
  456. mailimf_struct_destructor * destructor)
  457. {
  458. clist * struct_list;
  459. size_t cur_token;
  460. void * value;
  461. size_t final_token;
  462. int r;
  463. int res;
  464. cur_token = * indx;
  465. r = parser(message, length, &cur_token, &value);
  466. if (r != MAILIMF_NO_ERROR) {
  467. res = r;
  468. goto err;
  469. }
  470. struct_list = clist_new();
  471. if (struct_list == NULL) {
  472. destructor(value);
  473. res = MAILIMF_ERROR_MEMORY;
  474. goto err;
  475. }
  476. r = clist_append(struct_list, value);
  477. if (r < 0) {
  478. destructor(value);
  479. res = MAILIMF_ERROR_MEMORY;
  480. goto free;
  481. }
  482. final_token = cur_token;
  483. while (1) {
  484. r = mailimf_unstrict_char_parse(message, length, &cur_token, symbol);
  485. if (r != MAILIMF_NO_ERROR) {
  486. if (r == MAILIMF_ERROR_PARSE)
  487. break;
  488. else {
  489. res = r;
  490. goto free;
  491. }
  492. }
  493. r = parser(message, length, &cur_token, &value);
  494. if (r != MAILIMF_NO_ERROR) {
  495. if (r == MAILIMF_ERROR_PARSE)
  496. break;
  497. else {
  498. res = r;
  499. goto free;
  500. }
  501. }
  502. r = clist_append(struct_list, value);
  503. if (r < 0) {
  504. destructor(value);
  505. res = MAILIMF_ERROR_MEMORY;
  506. goto free;
  507. }
  508. final_token = cur_token;
  509. }
  510. * result = struct_list;
  511. * indx = final_token;
  512. return MAILIMF_NO_ERROR;
  513. free:
  514. clist_foreach(struct_list, (clist_func) destructor, NULL);
  515. clist_free(struct_list);
  516. err:
  517. return res;
  518. }
  519. static inline int mailimf_wsp_parse(const char * message, size_t length,
  520. size_t * indx)
  521. {
  522. size_t cur_token;
  523. cur_token = * indx;
  524. if (cur_token >= length)
  525. return MAILIMF_ERROR_PARSE;
  526. if ((message[cur_token] != ' ') && (message[cur_token] != '\t'))
  527. return MAILIMF_ERROR_PARSE;
  528. cur_token ++;
  529. * indx = cur_token;
  530. return MAILIMF_NO_ERROR;
  531. }
  532. LIBETPAN_EXPORT
  533. int mailimf_crlf_parse(const char * message, size_t length, size_t * indx)
  534. {
  535. size_t cur_token;
  536. int r;
  537. cur_token = * indx;
  538. r = mailimf_char_parse(message, length, &cur_token, '\r');
  539. if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
  540. return r;
  541. r = mailimf_char_parse(message, length, &cur_token, '\n');
  542. if (r != MAILIMF_NO_ERROR)
  543. return r;
  544. * indx = cur_token;
  545. return MAILIMF_NO_ERROR;
  546. }
  547. static int mailimf_unstrict_crlf_parse(const char * message,
  548. size_t length, size_t * indx)
  549. {
  550. size_t cur_token;
  551. int r;
  552. cur_token = * indx;
  553. mailimf_cfws_parse(message, length, &cur_token);
  554. r = mailimf_char_parse(message, length, &cur_token, '\r');
  555. if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
  556. return r;
  557. r = mailimf_char_parse(message, length, &cur_token, '\n');
  558. if (r != MAILIMF_NO_ERROR)
  559. return r;
  560. * indx = cur_token;
  561. return MAILIMF_NO_ERROR;
  562. }
  563. /* ************************************************************************ */
  564. /* RFC 2822 grammar */
  565. /*
  566. NO-WS-CTL = %d1-8 / ; US-ASCII control characters
  567. %d11 / ; that do not include the
  568. %d12 / ; carriage return, line feed,
  569. %d14-31 / ; and white space characters
  570. %d127
  571. */
  572. static inline int is_no_ws_ctl(char ch)
  573. {
  574. if ((ch == 9) || (ch == 10) || (ch == 13))
  575. return FALSE;
  576. if (ch == 127)
  577. return TRUE;
  578. return (ch >= 1) && (ch <= 31);
  579. }
  580. /*
  581. text = %d1-9 / ; Characters excluding CR and LF
  582. %d11 /
  583. %d12 /
  584. %d14-127 /
  585. obs-text
  586. */
  587. /*
  588. specials = "(" / ")" / ; Special characters used in
  589. "<" / ">" / ; other parts of the syntax
  590. "[" / "]" /
  591. ":" / ";" /
  592. "@" / "\" /
  593. "," / "." /
  594. DQUOTE
  595. */
  596. /*
  597. quoted-pair = ("\" text) / obs-qp
  598. */
  599. static inline int mailimf_quoted_pair_parse(const char * message, size_t length,
  600. size_t * indx, char * result)
  601. {
  602. size_t cur_token;
  603. cur_token = * indx;
  604. if (cur_token + 1 >= length)
  605. return MAILIMF_ERROR_PARSE;
  606. if (message[cur_token] != '\\')
  607. return MAILIMF_ERROR_PARSE;
  608. cur_token ++;
  609. * result = message[cur_token];
  610. cur_token ++;
  611. * indx = cur_token;
  612. return MAILIMF_NO_ERROR;
  613. }
  614. /*
  615. FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space
  616. obs-FWS
  617. */
  618. LIBETPAN_EXPORT
  619. int mailimf_fws_parse(const char * message, size_t length, size_t * indx)
  620. {
  621. size_t cur_token;
  622. size_t final_token;
  623. int fws_1;
  624. int fws_2;
  625. int fws_3;
  626. int r;
  627. cur_token = * indx;
  628. fws_1 = FALSE;
  629. while (1) {
  630. r = mailimf_wsp_parse(message, length, &cur_token);
  631. if (r != MAILIMF_NO_ERROR) {
  632. if (r == MAILIMF_ERROR_PARSE)
  633. break;
  634. else
  635. return r;
  636. }
  637. fws_1 = TRUE;
  638. }
  639. final_token = cur_token;
  640. r = mailimf_crlf_parse(message, length, &cur_token);
  641. switch (r) {
  642. case MAILIMF_NO_ERROR:
  643. fws_2 = TRUE;
  644. break;
  645. case MAILIMF_ERROR_PARSE:
  646. fws_2 = FALSE;
  647. break;
  648. default:
  649. return r;
  650. }
  651. fws_3 = FALSE;
  652. if (fws_2) {
  653. while (1) {
  654. r = mailimf_wsp_parse(message, length, &cur_token);
  655. if (r != MAILIMF_NO_ERROR) {
  656. if (r == MAILIMF_ERROR_PARSE)
  657. break;
  658. else
  659. return r;
  660. }
  661. fws_3 = TRUE;
  662. }
  663. }
  664. if ((!fws_1) && (!fws_3))
  665. return MAILIMF_ERROR_PARSE;
  666. if (!fws_3)
  667. cur_token = final_token;
  668. * indx = cur_token;
  669. return MAILIMF_NO_ERROR;
  670. }
  671. /*
  672. ctext = NO-WS-CTL / ; Non white space controls
  673. %d33-39 / ; The rest of the US-ASCII
  674. %d42-91 / ; characters not including "(",
  675. %d93-126 ; ")", or "\"
  676. */
  677. static inline int is_ctext(char ch)
  678. {
  679. unsigned char uch = (unsigned char) ch;
  680. if (is_no_ws_ctl(ch))
  681. return TRUE;
  682. if (uch < 33)
  683. return FALSE;
  684. if ((uch == 40) || (uch == 41))
  685. return FALSE;
  686. if (uch == 92)
  687. return FALSE;
  688. if (uch == 127)
  689. return FALSE;
  690. return TRUE;
  691. }
  692. /*
  693. ccontent = ctext / quoted-pair / comment
  694. */
  695. static inline int mailimf_ccontent_parse(const char * message, size_t length,
  696. size_t * indx)
  697. {
  698. size_t cur_token;
  699. char ch;
  700. int r;
  701. cur_token = * indx;
  702. if (cur_token >= length)
  703. return MAILIMF_ERROR_PARSE;
  704. if (is_ctext(message[cur_token])) {
  705. cur_token ++;
  706. }
  707. else {
  708. r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
  709. if (r == MAILIMF_ERROR_PARSE)
  710. r = mailimf_comment_parse(message, length, &cur_token);
  711. if (r == MAILIMF_ERROR_PARSE)
  712. return r;
  713. }
  714. * indx = cur_token;
  715. return MAILIMF_NO_ERROR;
  716. }
  717. /*
  718. [FWS] ccontent
  719. */
  720. static inline int
  721. mailimf_comment_fws_ccontent_parse(const char * message, size_t length,
  722. size_t * indx)
  723. {
  724. size_t cur_token;
  725. int r;
  726. cur_token = * indx;
  727. r = mailimf_fws_parse(message, length, &cur_token);
  728. if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
  729. return r;
  730. r = mailimf_ccontent_parse(message, length, &cur_token);
  731. if (r != MAILIMF_NO_ERROR)
  732. return r;
  733. * indx = cur_token;
  734. return MAILIMF_NO_ERROR;
  735. }
  736. /*
  737. comment = "(" *([FWS] ccontent) [FWS] ")"
  738. */
  739. static inline int mailimf_comment_parse(const char * message, size_t length,
  740. size_t * indx)
  741. {
  742. size_t cur_token;
  743. int r;
  744. cur_token = * indx;
  745. r = mailimf_oparenth_parse(message, length, &cur_token);
  746. if (r != MAILIMF_NO_ERROR)
  747. return r;
  748. while (1) {
  749. r = mailimf_comment_fws_ccontent_parse(message, length, &cur_token);
  750. if (r != MAILIMF_NO_ERROR) {
  751. if (r == MAILIMF_ERROR_PARSE)
  752. break;
  753. else
  754. return r;
  755. }
  756. }
  757. r = mailimf_fws_parse(message, length, &cur_token);
  758. if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
  759. return r;
  760. r = mailimf_cparenth_parse(message, length, &cur_token);
  761. if (r != MAILIMF_NO_ERROR)
  762. return r;
  763. * indx = cur_token;
  764. return MAILIMF_NO_ERROR;
  765. }
  766. /*
  767. [FWS] comment
  768. */
  769. static inline int mailimf_cfws_fws_comment_parse(const char * message, size_t length,
  770. size_t * indx)
  771. {
  772. size_t cur_token;
  773. int r;
  774. cur_token = * indx;
  775. r = mailimf_fws_parse(message, length, &cur_token);
  776. if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE))
  777. return r;
  778. r = mailimf_comment_parse(message, length, &cur_token);
  779. if (r != MAILIMF_NO_ERROR)
  780. return r;
  781. * indx = cur_token;
  782. return MAILIMF_NO_ERROR;
  783. }
  784. /*
  785. CFWS = *([FWS] comment) (([FWS] comment) / FWS)
  786. */
  787. LIBETPAN_EXPORT
  788. int mailimf_cfws_parse(const char * message, size_t length,
  789. size_t * indx)
  790. {
  791. size_t cur_token;
  792. int has_comment;
  793. int r;
  794. cur_token = * indx;
  795. has_comment = FALSE;
  796. while (1) {
  797. r = mailimf_cfws_fws_comment_parse(message, length, &cur_token);
  798. if (r != MAILIMF_NO_ERROR) {
  799. if (r == MAILIMF_ERROR_PARSE)
  800. break;
  801. else
  802. return r;
  803. }
  804. has_comment = TRUE;
  805. }
  806. if (!has_comment) {
  807. r = mailimf_fws_parse(message, length, &cur_token);
  808. if (r != MAILIMF_NO_ERROR)
  809. return r;
  810. }
  811. * indx = cur_token;
  812. return MAILIMF_NO_ERROR;
  813. }
  814. /*
  815. atext = ALPHA / DIGIT / ; Any character except controls,
  816. "!" / "#" / ; SP, and specials.
  817. "$" / "%" / ; Used for atoms
  818. "&" / "'" /
  819. "*" / "+" /
  820. "-" / "/" /
  821. "=" / "?" /
  822. "^" / "_" /
  823. "`" / "{" /
  824. "|" / "}" /
  825. "~"
  826. */
  827. static inline int is_atext(char ch)
  828. {
  829. switch (ch) {
  830. case ' ':
  831. case '\t':
  832. case '\n':
  833. case '\r':
  834. #if 0
  835. case '(':
  836. case ')':
  837. #endif
  838. case '<':
  839. case '>':
  840. #if 0
  841. case '@':
  842. #endif
  843. case ',':
  844. case '"':
  845. case ':':
  846. case ';':
  847. return FALSE;
  848. default:
  849. return TRUE;
  850. }
  851. }
  852. /*
  853. atom = [CFWS] 1*atext [CFWS]
  854. */
  855. LIBETPAN_EXPORT
  856. int mailimf_atom_parse(const char * message, size_t length,
  857. size_t * indx, char ** result)
  858. {
  859. size_t cur_token;
  860. int r;
  861. int res;
  862. char * atom;
  863. size_t end;
  864. cur_token = * indx;
  865. r = mailimf_cfws_parse(message, length, &cur_token);
  866. if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
  867. res = r;
  868. goto err;
  869. }
  870. end = cur_token;
  871. if (end >= length) {
  872. res = MAILIMF_ERROR_PARSE;
  873. goto err;
  874. }
  875. while (is_atext(message[end])) {
  876. end ++;
  877. if (end >= length)
  878. break;
  879. }
  880. if (end == cur_token) {
  881. res = MAILIMF_ERROR_PARSE;
  882. goto err;
  883. }
  884. atom = malloc(end - cur_token + 1);
  885. if (atom == NULL) {
  886. res = MAILIMF_ERROR_MEMORY;
  887. goto err;
  888. }
  889. strncpy(atom, message + cur_token, end - cur_token);
  890. atom[end - cur_token] = '\0';
  891. cur_token = end;
  892. * indx = cur_token;
  893. * result = atom;
  894. return MAILIMF_NO_ERROR;
  895. err:
  896. return res;
  897. }
  898. LIBETPAN_EXPORT
  899. int mailimf_fws_atom_for_word_parse(const char * message, size_t length,
  900. size_t * indx, char ** result, int * p_missing_closing_quote)
  901. {
  902. size_t end;
  903. size_t cur_token;
  904. int r;
  905. int res;
  906. struct mailmime_encoded_word * word;
  907. int has_fwd;
  908. int missing_closing_quote;
  909. char * atom;
  910. cur_token = * indx;
  911. missing_closing_quote = 0;
  912. r = mailimf_fws_parse(message, length, &cur_token);
  913. if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
  914. res = r;
  915. goto err;
  916. }
  917. end = cur_token;
  918. r = mailmime_encoded_word_parse(message, length, &cur_token, &word, &has_fwd, &missing_closing_quote);
  919. if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
  920. res = r;
  921. goto err;
  922. }
  923. if (r == MAILIMF_ERROR_PARSE) {
  924. return mailimf_fws_atom_parse(message, length, indx, result);
  925. }
  926. mailmime_encoded_word_free(word);
  927. atom = malloc(cur_token - end + 1);
  928. if (atom == NULL) {
  929. res = MAILIMF_ERROR_MEMORY;
  930. goto err;
  931. }
  932. strncpy(atom, message + end, cur_token - end);
  933. atom[cur_token - end] = '\0';
  934. * result = atom;
  935. * indx = cur_token;
  936. * p_missing_closing_quote = missing_closing_quote;
  937. return MAILIMF_NO_ERROR;
  938. err:
  939. return res;
  940. }
  941. LIBETPAN_EXPORT
  942. int mailimf_fws_atom_parse(const char * message, size_t length,
  943. size_t * indx, char ** result)
  944. {
  945. size_t cur_token;
  946. int r;
  947. int res;
  948. char * atom;
  949. size_t end;
  950. cur_token = * indx;
  951. r = mailimf_fws_parse(message, length, &cur_token);
  952. if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
  953. res = r;
  954. goto err;
  955. }
  956. end = cur_token;
  957. if (end >= length) {
  958. res = MAILIMF_ERROR_PARSE;
  959. goto err;
  960. }
  961. while (is_atext(message[end])) {
  962. end ++;
  963. if (end >= length)
  964. break;
  965. }
  966. if (end == cur_token) {
  967. res = MAILIMF_ERROR_PARSE;
  968. goto err;
  969. }
  970. atom = malloc(end - cur_token + 1);
  971. if (atom == NULL) {
  972. res = MAILIMF_ERROR_MEMORY;
  973. goto err;
  974. }
  975. strncpy(atom, message + cur_token, end - cur_token);
  976. atom[end - cur_token] = '\0';
  977. cur_token = end;
  978. * indx = cur_token;
  979. * result = atom;
  980. return MAILIMF_NO_ERROR;
  981. err:
  982. return res;
  983. }
  984. /*
  985. dot-atom = [CFWS] dot-atom-text [CFWS]
  986. */
  987. #if 0
  988. static int mailimf_dot_atom_parse(const char * message, size_t length,
  989. size_t * indx, char ** result)
  990. {
  991. return mailimf_atom_parse(message, length, indx, result);
  992. }
  993. #endif
  994. /*
  995. dot-atom-text = 1*atext *("." 1*atext)
  996. */
  997. #if 0
  998. static int
  999. mailimf_dot_atom_text_parse(const char * message, size_t length,
  1000. size_t * indx, char ** result)
  1001. {
  1002. return mailimf_atom_parse(message, length, indx, result);
  1003. }
  1004. #endif
  1005. /*
  1006. qtext = NO-WS-CTL / ; Non white space controls
  1007. %d33 / ; The rest of the US-ASCII
  1008. %d35-91 / ; characters not including "\"
  1009. %d93-126 ; or the quote character
  1010. */
  1011. static inline int is_qtext(char ch)
  1012. {
  1013. unsigned char uch = (unsigned char) ch;
  1014. if (is_no_ws_ctl(ch))
  1015. return TRUE;
  1016. if (uch < 33)
  1017. return FALSE;
  1018. if (uch == 34)
  1019. return FALSE;
  1020. if (uch == 92)
  1021. return FALSE;
  1022. if (uch == 127)
  1023. return FALSE;
  1024. return TRUE;
  1025. }
  1026. /*
  1027. qcontent = qtext / quoted-pair
  1028. */
  1029. static int mailimf_qcontent_parse(const char * message, size_t length,
  1030. size_t * indx, char * result)
  1031. {
  1032. size_t cur_token;
  1033. char ch;
  1034. int r;
  1035. cur_token = * indx;
  1036. if (cur_token >= length)
  1037. return MAILIMF_ERROR_PARSE;
  1038. if (is_qtext(message[cur_token])) {
  1039. ch = message[cur_token];
  1040. cur_token ++;
  1041. }
  1042. else {
  1043. r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch);
  1044. if (r != MAILIMF_NO_ERROR)
  1045. return r;
  1046. }
  1047. * result = ch;
  1048. * indx = cur_token;
  1049. return MAILIMF_NO_ERROR;
  1050. }
  1051. /*
  1052. quoted-string = [CFWS]
  1053. DQUOTE *([FWS] qcontent) [FWS] DQUOTE
  1054. [CFWS]
  1055. */
  1056. LIBETPAN_EXPORT
  1057. int mailimf_quoted_string_parse(const char * message, size_t length,
  1058. size_t * indx, char ** result)
  1059. {
  1060. size_t cur_token;
  1061. MMAPString * gstr;
  1062. char ch;
  1063. char * str;
  1064. int r;
  1065. int res;
  1066. cur_token = * indx;
  1067. r = mailimf_cfws_parse(message, length, &cur_token);
  1068. if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
  1069. res = r;
  1070. goto err;
  1071. }
  1072. r = mailimf_dquote_parse(message, length, &cur_token);
  1073. if (r != MAILIMF_NO_ERROR) {
  1074. res = r;
  1075. goto err;
  1076. }
  1077. gstr = mmap_string_new("");
  1078. if (gstr == NULL) {
  1079. res = MAILIMF_ERROR_MEMORY;
  1080. goto err;
  1081. }
  1082. #if 0
  1083. if (mmap_string_append_c(gstr, '\"') == NULL) {
  1084. res = MAILIMF_ERROR_MEMORY;
  1085. goto free_gstr;
  1086. }
  1087. #endif
  1088. while (1) {
  1089. r = mailimf_fws_parse(message, length, &cur_token);
  1090. if (r == MAILIMF_NO_ERROR) {
  1091. if (mmap_string_append_c(gstr, ' ') == NULL) {
  1092. res = MAILIMF_ERROR_MEMORY;
  1093. goto free_gstr;
  1094. }
  1095. }
  1096. else if (r != MAILIMF_ERROR_PARSE) {
  1097. res = r;
  1098. goto free_gstr;
  1099. }
  1100. r = mailimf_qcontent_parse(message, length, &cur_token, &ch);
  1101. if (r == MAILIMF_NO_ERROR) {
  1102. if (mmap_string_append_c(gstr, ch) == NULL) {
  1103. res = MAILIMF_ERROR_MEMORY;
  1104. goto free_gstr;
  1105. }
  1106. }
  1107. else if (r == MAILIMF_ERROR_PARSE)
  1108. break;
  1109. else {
  1110. res = r;
  1111. goto free_gstr;
  1112. }
  1113. }
  1114. r = mailimf_dquote_parse(message, length, &cur_token);
  1115. if (r != MAILIMF_NO_ERROR) {
  1116. res = r;
  1117. goto free_gstr;
  1118. }
  1119. #if 0
  1120. if (mmap_string_append_c(gstr, '\"') == NULL) {
  1121. res = MAILIMF_ERROR_MEMORY;
  1122. goto free_gstr;
  1123. }
  1124. #endif
  1125. str = strdup(gstr->str);
  1126. if (str == NULL) {
  1127. res = MAILIMF_ERROR_MEMORY;
  1128. goto free_gstr;
  1129. }
  1130. mmap_string_free(gstr);
  1131. * indx = cur_token;
  1132. * result = str;
  1133. return MAILIMF_NO_ERROR;
  1134. free_gstr:
  1135. mmap_string_free(gstr);
  1136. err:
  1137. return res;
  1138. }
  1139. LIBETPAN_EXPORT
  1140. int mailimf_fws_quoted_string_parse(const char * message, size_t length,
  1141. size_t * indx, char ** result)
  1142. {
  1143. size_t cur_token;
  1144. MMAPString * gstr;
  1145. char ch;
  1146. char * str;
  1147. int r;
  1148. int res;
  1149. cur_token = * indx;
  1150. r = mailimf_fws_parse(message, length, &cur_token);
  1151. if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
  1152. res = r;
  1153. goto err;
  1154. }
  1155. r = mailimf_dquote_parse(message, length, &cur_token);
  1156. if (r != MAILIMF_NO_ERROR) {
  1157. res = r;
  1158. goto err;
  1159. }
  1160. gstr = mmap_string_new("");
  1161. if (gstr == NULL) {
  1162. res = MAILIMF_ERROR_MEMORY;
  1163. goto err;
  1164. }
  1165. #if 0
  1166. if (mmap_string_append_c(gstr, '\"') == NULL) {
  1167. res = MAILIMF_ERROR_MEMORY;
  1168. goto free_gstr;
  1169. }
  1170. #endif
  1171. while (1) {
  1172. r = mailimf_fws_parse(message, length, &cur_token);
  1173. if (r == MAILIMF_NO_ERROR) {
  1174. if (mmap_string_append_c(gstr, ' ') == NULL) {
  1175. res = MAILIMF_ERROR_MEMORY;
  1176. goto free_gstr;
  1177. }
  1178. }
  1179. else if (r != MAILIMF_ERROR_PARSE) {
  1180. res = r;
  1181. goto free_gstr;
  1182. }
  1183. r = mailimf_qcontent_parse(message, length, &cur_token, &ch);
  1184. if (r == MAILIMF_NO_ERROR) {
  1185. if (mmap_string_append_c(gstr, ch) == NULL) {
  1186. res = MAILIMF_ERROR_MEMORY;
  1187. goto free_gstr;
  1188. }
  1189. }
  1190. else if (r == MAILIMF_ERROR_PARSE)
  1191. break;
  1192. else {
  1193. res = r;
  1194. goto free_gstr;
  1195. }
  1196. }
  1197. r = mailimf_dquote_parse(message, length, &cur_token);
  1198. if (r != MAILIMF_NO_ERROR) {
  1199. res = r;
  1200. goto free_gstr;
  1201. }
  1202. #if 0
  1203. if (mmap_string_append_c(gstr, '\"') == NULL) {
  1204. res = MAILIMF_ERROR_MEMORY;
  1205. goto free_gstr;
  1206. }
  1207. #endif
  1208. str = strdup(gstr->str);
  1209. if (str == NULL) {
  1210. res = MAILIMF_ERROR_MEMORY;
  1211. goto free_gstr;
  1212. }
  1213. mmap_string_free(gstr);
  1214. * indx = cur_token;
  1215. * result = str;
  1216. return MAILIMF_NO_ERROR;
  1217. free_gstr:
  1218. mmap_string_free(gstr);
  1219. err:
  1220. return res;
  1221. }
  1222. /*
  1223. word = atom / quoted-string
  1224. */
  1225. LIBETPAN_EXPORT
  1226. int mailimf_word_parse(const char * message, size_t length,
  1227. size_t * indx, char ** result)
  1228. {
  1229. size_t cur_token;
  1230. char * word;
  1231. int r;
  1232. cur_token = * indx;
  1233. r = mailimf_atom_parse(message, length, &cur_token, &word);
  1234. if (r == MAILIMF_ERROR_PARSE)
  1235. r = mailimf_quoted_string_parse(message, length, &cur_token, &word);
  1236. if (r != MAILIMF_NO_ERROR)
  1237. return r;
  1238. * result = word;
  1239. * indx = cur_token;
  1240. return MAILIMF_NO_ERROR;
  1241. }
  1242. LIBETPAN_EXPORT
  1243. int mailimf_fws_word_parse(const char * message, size_t length,
  1244. size_t * indx, char ** result, int * p_missing_closing_quote)
  1245. {
  1246. size_t cur_token;
  1247. char * word;
  1248. int r;
  1249. int missing_closing_quote;
  1250. cur_token = * indx;
  1251. missing_closing_quote = 0;
  1252. r = mailimf_fws_atom_for_word_parse(message, length, &cur_token, &word, &missing_closing_quote);
  1253. if (r == MAILIMF_ERROR_PARSE)
  1254. r = mailimf_fws_quoted_string_parse(message, length, &cur_token, &word);
  1255. if (r != MAILIMF_NO_ERROR)
  1256. return r;
  1257. * result = word;
  1258. * indx = cur_token;
  1259. * p_missing_closing_quote = missing_closing_quote;
  1260. return MAILIMF_NO_ERROR;
  1261. }
  1262. /*
  1263. phrase = 1*word / obs-phrase
  1264. */
  1265. static int mailimf_phrase_parse(const char * message, size_t length,
  1266. size_t * indx, char ** result)
  1267. {
  1268. MMAPString * gphrase;
  1269. char * word;
  1270. int first;
  1271. size_t cur_token;
  1272. int r;
  1273. int res;
  1274. char * str;
  1275. int has_missing_closing_quote;
  1276. cur_token = * indx;
  1277. has_missing_closing_quote = 0;
  1278. gphrase = mmap_string_new("");
  1279. if (gphrase == NULL) {
  1280. res = MAILIMF_ERROR_MEMORY;
  1281. goto err;
  1282. }
  1283. first = TRUE;
  1284. while (1) {
  1285. int missing_quote = 0;
  1286. r = mailimf_fws_word_parse(message, length, &cur_token, &word, &missing_quote);
  1287. if (missing_quote) {
  1288. has_missing_closing_quote = 1;
  1289. }
  1290. if (r == MAILIMF_NO_ERROR) {
  1291. if (!first) {
  1292. if (mmap_string_append_c(gphrase, ' ') == NULL) {
  1293. mailimf_word_free(word);
  1294. res = MAILIMF_ERROR_MEMORY;
  1295. goto free;
  1296. }
  1297. }
  1298. if (mmap_string_append(gphrase, word) == NULL) {
  1299. mailimf_word_free(word);
  1300. res = MAILIMF_ERROR_MEMORY;
  1301. goto free;
  1302. }
  1303. mailimf_word_free(word);
  1304. first = FALSE;
  1305. }
  1306. else if (r == MAILIMF_ERROR_PARSE)
  1307. break;
  1308. else {
  1309. res = r;
  1310. goto free;
  1311. }
  1312. }
  1313. if (first) {
  1314. res = MAILIMF_ERROR_PARSE;
  1315. goto free;
  1316. }
  1317. if (has_missing_closing_quote) {
  1318. r = mailimf_char_parse(message, length, &cur_token, '\"');
  1319. }
  1320. str = strdup(gphrase->str);
  1321. if (str == NULL) {
  1322. res = MAILIMF_ERROR_MEMORY;
  1323. goto free;
  1324. }
  1325. mmap_string_free(gphrase);
  1326. * result = str;
  1327. * indx = cur_token;
  1328. return MAILIMF_NO_ERROR;
  1329. free:
  1330. mmap_string_free(gphrase);
  1331. err:
  1332. return res;
  1333. }
  1334. /*
  1335. utext = NO-WS-CTL / ; Non white space controls
  1336. %d33-126 / ; The rest of US-ASCII
  1337. obs-utext
  1338. added : WSP
  1339. */
  1340. enum {
  1341. UNSTRUCTURED_START,
  1342. UNSTRUCTURED_CR,
  1343. UNSTRUCTURED_LF,
  1344. UNSTRUCTURED_WSP,
  1345. UNSTRUCTURED_OUT
  1346. };
  1347. static int mailimf_unstructured_parse(const char * message, size_t length,
  1348. size_t * indx, char ** result)
  1349. {
  1350. size_t cur_token;
  1351. int state;
  1352. size_t begin;
  1353. size_t terminal;
  1354. char * str;
  1355. cur_token = * indx;
  1356. while (1) {
  1357. int r;
  1358. r = mailimf_wsp_parse(message, length, &cur_token);
  1359. if (r == MAILIMF_NO_ERROR) {
  1360. /* do nothing */
  1361. }
  1362. else if (r == MAILIMF_ERROR_PARSE)
  1363. break;
  1364. else {
  1365. return r;
  1366. }
  1367. }
  1368. state = UNSTRUCTURED_START;
  1369. begin = cur_token;
  1370. terminal = cur_token;
  1371. while (state != UNSTRUCTURED_OUT) {
  1372. switch(state) {
  1373. case UNSTRUCTURED_START:
  1374. if (cur_token >= length)
  1375. return MAILIMF_ERROR_PARSE;
  1376. terminal = cur_token;
  1377. switch(message[cur_token]) {
  1378. case '\r':
  1379. state = UNSTRUCTURED_CR;
  1380. break;
  1381. case '\n':
  1382. state = UNSTRUCTURED_LF;
  1383. break;
  1384. default:
  1385. state = UNSTRUCTURED_START;
  1386. break;
  1387. }
  1388. break;
  1389. case UNSTRUCTURED_CR:
  1390. if (cur_token >= length)
  1391. return MAILIMF_ERROR_PARSE;
  1392. switch(message[cur_token]) {
  1393. case '\n':
  1394. state = UNSTRUCTURED_LF;
  1395. break;
  1396. default:
  1397. state = UNSTRUCTURED_START;
  1398. break;
  1399. }
  1400. break;
  1401. case UNSTRUCTURED_LF:
  1402. if (cur_token >= length) {
  1403. state = UNSTRUCTURED_OUT;
  1404. break;
  1405. }
  1406. switch(message[cur_token]) {
  1407. case '\t':
  1408. case ' ':
  1409. state = UNSTRUCTURED_WSP;
  1410. break;
  1411. default:
  1412. state = UNSTRUCTURED_OUT;
  1413. break;
  1414. }
  1415. break;
  1416. case UNSTRUCTURED_WSP:
  1417. if (cur_token >= length)
  1418. return MAILIMF_ERROR_PARSE;
  1419. switch(message[cur_token]) {
  1420. case '\r':
  1421. state = UNSTRUCTURED_CR;
  1422. break;
  1423. case '\n':
  1424. state = UNSTRUCTURED_LF;
  1425. break;
  1426. default:
  1427. state = UNSTRUCTURED_START;
  1428. break;
  1429. }
  1430. break;
  1431. }
  1432. cur_token ++;
  1433. }
  1434. str = malloc(terminal - begin + 1);
  1435. if (str == NULL)
  1436. return MAILIMF_ERROR_MEMORY;
  1437. strncpy(str, message + begin, terminal - begin);
  1438. str[terminal - begin] = '\0';
  1439. * indx = terminal;
  1440. * result = str;
  1441. return MAILIMF_NO_ERROR;
  1442. }
  1443. static int mailimf_ignore_unstructured_parse(const char * message, size_t length,
  1444. size_t * indx)
  1445. {
  1446. size_t cur_token;
  1447. int state;
  1448. size_t terminal;
  1449. cur_token = * indx;
  1450. state = UNSTRUCTURED_START;
  1451. terminal = cur_token;
  1452. while (state != UNSTRUCTURED_OUT) {
  1453. switch(state) {
  1454. case UNSTRUCTURED_START:
  1455. if (cur_token >= length)
  1456. return MAILIMF_ERROR_PARSE;
  1457. terminal = cur_token;
  1458. switch(message[cur_token]) {
  1459. case '\r':
  1460. state = UNSTRUCTURED_CR;
  1461. break;
  1462. case '\n':
  1463. state = UNSTRUCTURED_LF;
  1464. break;
  1465. default:
  1466. state = UNSTRUCTURED_START;
  1467. break;
  1468. }
  1469. break;
  1470. case UNSTRUCTURED_CR:
  1471. if (cur_token >= length)
  1472. return MAILIMF_ERROR_PARSE;
  1473. switch(message[cur_token]) {
  1474. case '\n':
  1475. state = UNSTRUCTURED_LF;
  1476. break;
  1477. default:
  1478. state = UNSTRUCTURED_START;
  1479. break;
  1480. }
  1481. break;
  1482. case UNSTRUCTURED_LF:
  1483. if (cur_token >= length) {
  1484. state = UNSTRUCTURED_OUT;
  1485. break;
  1486. }
  1487. switch(message[cur_token]) {
  1488. case '\t':
  1489. case ' ':
  1490. state = UNSTRUCTURED_WSP;
  1491. break;
  1492. default:
  1493. state = UNSTRUCTURED_OUT;
  1494. break;
  1495. }
  1496. break;
  1497. case UNSTRUCTURED_WSP:
  1498. if (cur_token >= length)
  1499. return MAILIMF_ERROR_PARSE;
  1500. switch(message[cur_token]) {
  1501. case '\r':
  1502. state = UNSTRUCTURED_CR;
  1503. break;
  1504. case '\n':
  1505. state = UNSTRUCTURED_LF;
  1506. break;
  1507. default:
  1508. state = UNSTRUCTURED_START;
  1509. break;
  1510. }
  1511. break;
  1512. }
  1513. cur_token ++;
  1514. }
  1515. * indx = terminal;
  1516. return MAILIMF_NO_ERROR;
  1517. }
  1518. LIBETPAN_EXPORT
  1519. int mailimf_ignore_field_parse(const char * message, size_t length,
  1520. size_t * indx)
  1521. {
  1522. int has_field;
  1523. size_t cur_token;
  1524. int state;
  1525. size_t terminal;
  1526. has_field =