From 4e752f4537bfc33e7b35b50263d69de9698adb56 Mon Sep 17 00:00:00 2001 From: "Sl (Shahaf Levi)" Date: Thu, 10 Jun 2021 20:58:41 +0300 Subject: [PATCH] Initial commit --- Package.swift | 31 + README.md | 64 + Sources/libetpan/data-types/Makefile.am | 55 + Sources/libetpan/data-types/base64.c | 148 + Sources/libetpan/data-types/base64.h | 65 + Sources/libetpan/data-types/carray.c | 162 + Sources/libetpan/data-types/carray.h | 149 + Sources/libetpan/data-types/charconv.c | 348 + Sources/libetpan/data-types/charconv.h | 84 + Sources/libetpan/data-types/chash.c | 414 + Sources/libetpan/data-types/chash.h | 191 + Sources/libetpan/data-types/clist.c | 275 + Sources/libetpan/data-types/clist.h | 146 + Sources/libetpan/data-types/connect.c | 383 + Sources/libetpan/data-types/connect.h | 62 + Sources/libetpan/data-types/hmac-md5.h | 94 + Sources/libetpan/data-types/mail.h | 56 + Sources/libetpan/data-types/mail_cache_db.c | 504 + Sources/libetpan/data-types/mail_cache_db.h | 158 + .../libetpan/data-types/mail_cache_db_types.h | 52 + Sources/libetpan/data-types/mail_cache_lmdb.c | 391 + Sources/libetpan/data-types/maillock.c | 379 + Sources/libetpan/data-types/maillock.h | 53 + Sources/libetpan/data-types/mailsasl.c | 143 + Sources/libetpan/data-types/mailsasl.h | 50 + .../libetpan/data-types/mailsasl_private.h | 18 + Sources/libetpan/data-types/mailsem.c | 286 + Sources/libetpan/data-types/mailsem.h | 59 + Sources/libetpan/data-types/mailstream.c | 422 + Sources/libetpan/data-types/mailstream.h | 135 + .../libetpan/data-types/mailstream_cancel.c | 216 + .../libetpan/data-types/mailstream_cancel.h | 45 + .../data-types/mailstream_cancel_types.h | 41 + .../libetpan/data-types/mailstream_cfstream.c | 1276 ++ .../libetpan/data-types/mailstream_cfstream.h | 114 + .../libetpan/data-types/mailstream_compress.c | 357 + .../libetpan/data-types/mailstream_compress.h | 72 + .../libetpan/data-types/mailstream_helper.c | 578 + .../libetpan/data-types/mailstream_helper.h | 88 + Sources/libetpan/data-types/mailstream_low.c | 591 + Sources/libetpan/data-types/mailstream_low.h | 123 + .../libetpan/data-types/mailstream_socket.c | 482 + .../libetpan/data-types/mailstream_socket.h | 59 + Sources/libetpan/data-types/mailstream_ssl.c | 1576 +++ Sources/libetpan/data-types/mailstream_ssl.h | 140 + .../data-types/mailstream_ssl_private.h | 48 + .../libetpan/data-types/mailstream_types.h | 137 + Sources/libetpan/data-types/md5.c | 578 + Sources/libetpan/data-types/md5.h | 88 + Sources/libetpan/data-types/md5global.h | 82 + Sources/libetpan/data-types/md5namespace.h | 45 + Sources/libetpan/data-types/mmapstring.c | 591 + Sources/libetpan/data-types/mmapstring.h | 161 + .../libetpan/data-types/mmapstring_private.h | 48 + Sources/libetpan/data-types/timeutils.c | 162 + Sources/libetpan/data-types/timeutils.h | 39 + Sources/libetpan/driver/Makefile.am | 43 + Sources/libetpan/driver/TODO | 9 + .../driver/implementation/Makefile.am | 57 + .../implementation/data-message/Makefile.am | 41 + .../data-message/data_message_driver.c | 134 + .../data-message/data_message_driver.h | 60 + .../driver/implementation/db/Makefile.am | 50 + .../driver/implementation/db/dbdriver.c | 1071 ++ .../driver/implementation/db/dbdriver.h | 53 + .../implementation/db/dbdriver_message.c | 314 + .../implementation/db/dbdriver_message.h | 52 + .../driver/implementation/db/dbdriver_types.h | 71 + .../driver/implementation/db/dbstorage.c | 149 + .../driver/implementation/db/dbstorage.h | 62 + .../driver/implementation/feed/Makefile.am | 51 + .../driver/implementation/feed/feeddriver.c | 796 ++ .../driver/implementation/feed/feeddriver.h | 52 + .../implementation/feed/feeddriver_message.c | 200 + .../implementation/feed/feeddriver_message.h | 52 + .../implementation/feed/feeddriver_types.h | 68 + .../driver/implementation/feed/feedstorage.c | 183 + .../driver/implementation/feed/feedstorage.h | 72 + .../driver/implementation/hotmail/Makefile.am | 42 + .../implementation/hotmail/hotmailstorage.c | 67 + .../implementation/hotmail/hotmailstorage.h | 57 + .../driver/implementation/imap/Makefile.am | 58 + .../driver/implementation/imap/imapdriver.c | 1290 ++ .../driver/implementation/imap/imapdriver.h | 52 + .../implementation/imap/imapdriver_cached.c | 1540 +++ .../implementation/imap/imapdriver_cached.h | 52 + .../imap/imapdriver_cached_message.c | 747 + .../imap/imapdriver_cached_message.h | 52 + .../implementation/imap/imapdriver_message.c | 1244 ++ .../implementation/imap/imapdriver_message.h | 52 + .../implementation/imap/imapdriver_tools.c | 3730 +++++ .../implementation/imap/imapdriver_tools.h | 88 + .../imap/imapdriver_tools_private.h | 62 + .../implementation/imap/imapdriver_types.h | 165 + .../driver/implementation/imap/imapstorage.c | 477 + .../driver/implementation/imap/imapstorage.h | 120 + .../driver/implementation/maildir/Makefile.am | 56 + .../implementation/maildir/maildirdriver.c | 685 + .../implementation/maildir/maildirdriver.h | 53 + .../maildir/maildirdriver_cached.c | 1163 ++ .../maildir/maildirdriver_cached.h | 53 + .../maildir/maildirdriver_cached_message.c | 344 + .../maildir/maildirdriver_cached_message.h | 52 + .../maildir/maildirdriver_message.c | 267 + .../maildir/maildirdriver_message.h | 52 + .../maildir/maildirdriver_tools.c | 202 + .../maildir/maildirdriver_tools.h | 53 + .../maildir/maildirdriver_types.h | 96 + .../implementation/maildir/maildirstorage.c | 198 + .../implementation/maildir/maildirstorage.h | 70 + .../driver/implementation/mbox/Makefile.am | 56 + .../driver/implementation/mbox/mboxdriver.c | 527 + .../driver/implementation/mbox/mboxdriver.h | 52 + .../implementation/mbox/mboxdriver_cached.c | 1350 ++ .../implementation/mbox/mboxdriver_cached.h | 54 + .../mbox/mboxdriver_cached_message.c | 367 + .../mbox/mboxdriver_cached_message.h | 52 + .../implementation/mbox/mboxdriver_message.c | 233 + .../implementation/mbox/mboxdriver_message.h | 52 + .../implementation/mbox/mboxdriver_tools.c | 439 + .../implementation/mbox/mboxdriver_tools.h | 85 + .../implementation/mbox/mboxdriver_types.h | 107 + .../driver/implementation/mbox/mboxstorage.c | 197 + .../driver/implementation/mbox/mboxstorage.h | 70 + .../driver/implementation/mh/Makefile.am | 56 + .../driver/implementation/mh/mhdriver.c | 894 ++ .../driver/implementation/mh/mhdriver.h | 52 + .../implementation/mh/mhdriver_cached.c | 1317 ++ .../implementation/mh/mhdriver_cached.h | 52 + .../mh/mhdriver_cached_message.c | 344 + .../mh/mhdriver_cached_message.h | 52 + .../implementation/mh/mhdriver_message.c | 221 + .../implementation/mh/mhdriver_message.h | 52 + .../driver/implementation/mh/mhdriver_tools.c | 493 + .../driver/implementation/mh/mhdriver_tools.h | 80 + .../driver/implementation/mh/mhdriver_types.h | 100 + .../driver/implementation/mh/mhstorage.c | 197 + .../driver/implementation/mh/mhstorage.h | 68 + .../implementation/mime-message/Makefile.am | 42 + .../mime-message/mime_message_driver.c | 511 + .../mime-message/mime_message_driver.h | 53 + .../driver/implementation/nntp/Makefile.am | 56 + .../driver/implementation/nntp/nntpdriver.c | 1187 ++ .../driver/implementation/nntp/nntpdriver.h | 52 + .../implementation/nntp/nntpdriver_cached.c | 1070 ++ .../implementation/nntp/nntpdriver_cached.h | 52 + .../nntp/nntpdriver_cached_message.c | 367 + .../nntp/nntpdriver_cached_message.h | 52 + .../implementation/nntp/nntpdriver_message.c | 173 + .../implementation/nntp/nntpdriver_message.h | 52 + .../implementation/nntp/nntpdriver_tools.c | 569 + .../implementation/nntp/nntpdriver_tools.h | 88 + .../implementation/nntp/nntpdriver_types.h | 149 + .../driver/implementation/nntp/nntpstorage.c | 308 + .../driver/implementation/nntp/nntpstorage.h | 104 + .../driver/implementation/pop3/Makefile.am | 56 + .../driver/implementation/pop3/pop3driver.c | 450 + .../driver/implementation/pop3/pop3driver.h | 52 + .../implementation/pop3/pop3driver_cached.c | 945 ++ .../implementation/pop3/pop3driver_cached.h | 52 + .../pop3/pop3driver_cached_message.c | 357 + .../pop3/pop3driver_cached_message.h | 52 + .../implementation/pop3/pop3driver_message.c | 197 + .../implementation/pop3/pop3driver_message.h | 52 + .../implementation/pop3/pop3driver_tools.c | 360 + .../implementation/pop3/pop3driver_tools.h | 82 + .../implementation/pop3/pop3driver_types.h | 175 + .../driver/implementation/pop3/pop3storage.c | 482 + .../driver/implementation/pop3/pop3storage.h | 125 + Sources/libetpan/driver/interface/Makefile.am | 57 + .../libetpan/driver/interface/maildriver.c | 444 + .../libetpan/driver/interface/maildriver.h | 607 + .../driver/interface/maildriver_errors.h | 103 + .../driver/interface/maildriver_tools.c | 797 ++ .../driver/interface/maildriver_tools.h | 81 + .../driver/interface/maildriver_types.c | 361 + .../driver/interface/maildriver_types.h | 822 ++ .../interface/maildriver_types_helper.c | 108 + .../interface/maildriver_types_helper.h | 99 + .../libetpan/driver/interface/mailfolder.c | 169 + .../libetpan/driver/interface/mailfolder.h | 80 + .../libetpan/driver/interface/mailmessage.c | 259 + .../libetpan/driver/interface/mailmessage.h | 379 + .../driver/interface/mailmessage_tools.c | 600 + .../driver/interface/mailmessage_tools.h | 103 + .../driver/interface/mailmessage_types.c | 98 + .../driver/interface/mailmessage_types.h | 50 + .../libetpan/driver/interface/mailstorage.c | 355 + .../libetpan/driver/interface/mailstorage.h | 110 + .../driver/interface/mailstorage_tools.c | 465 + .../driver/interface/mailstorage_tools.h | 89 + .../driver/interface/mailstorage_types.h | 203 + Sources/libetpan/driver/tools/Makefile.am | 47 + Sources/libetpan/driver/tools/generic_cache.c | 759 ++ Sources/libetpan/driver/tools/generic_cache.h | 109 + .../driver/tools/generic_cache_types.h | 56 + Sources/libetpan/driver/tools/imfcache.c | 1430 ++ Sources/libetpan/driver/tools/imfcache.h | 75 + Sources/libetpan/driver/tools/mailthread.c | 1684 +++ Sources/libetpan/driver/tools/mailthread.h | 111 + .../libetpan/driver/tools/mailthread_types.c | 99 + .../libetpan/driver/tools/mailthread_types.h | 64 + Sources/libetpan/engine/Makefile.am | 52 + Sources/libetpan/engine/mailengine.c | 1488 ++ Sources/libetpan/engine/mailengine.h | 190 + Sources/libetpan/engine/mailprivacy.c | 938 ++ Sources/libetpan/engine/mailprivacy.h | 145 + Sources/libetpan/engine/mailprivacy_gnupg.c | 3045 +++++ Sources/libetpan/engine/mailprivacy_gnupg.h | 60 + Sources/libetpan/engine/mailprivacy_smime.c | 1928 +++ Sources/libetpan/engine/mailprivacy_smime.h | 104 + Sources/libetpan/engine/mailprivacy_tools.c | 1578 +++ Sources/libetpan/engine/mailprivacy_tools.h | 120 + .../engine/mailprivacy_tools_private.h | 48 + Sources/libetpan/engine/mailprivacy_types.h | 83 + Sources/libetpan/include/acl.h | 165 + Sources/libetpan/include/acl_parser.h | 92 + Sources/libetpan/include/acl_sender.h | 66 + Sources/libetpan/include/acl_types.h | 169 + Sources/libetpan/include/annotatemore.h | 103 + .../libetpan/include/annotatemore_parser.h | 104 + .../libetpan/include/annotatemore_sender.h | 56 + Sources/libetpan/include/annotatemore_types.h | 268 + Sources/libetpan/include/base64.h | 65 + Sources/libetpan/include/carray.h | 149 + Sources/libetpan/include/charconv.h | 84 + Sources/libetpan/include/chash.h | 191 + Sources/libetpan/include/clientid.h | 66 + Sources/libetpan/include/clientid_sender.h | 49 + Sources/libetpan/include/clist.h | 146 + Sources/libetpan/include/condstore.h | 101 + Sources/libetpan/include/condstore_private.h | 50 + Sources/libetpan/include/condstore_types.h | 97 + Sources/libetpan/include/config.h | 191 + Sources/libetpan/include/connect.h | 62 + .../libetpan/include/data_message_driver.h | 60 + Sources/libetpan/include/date.h | 38 + Sources/libetpan/include/dbdriver.h | 53 + Sources/libetpan/include/dbdriver_message.h | 52 + Sources/libetpan/include/dbdriver_types.h | 71 + Sources/libetpan/include/dbstorage.h | 62 + Sources/libetpan/include/enable.h | 56 + Sources/libetpan/include/feeddriver.h | 52 + Sources/libetpan/include/feeddriver_message.h | 52 + Sources/libetpan/include/feeddriver_types.h | 68 + Sources/libetpan/include/feedstorage.h | 72 + Sources/libetpan/include/generic_cache.h | 109 + .../libetpan/include/generic_cache_types.h | 56 + Sources/libetpan/include/hotmailstorage.h | 57 + Sources/libetpan/include/idle.h | 64 + Sources/libetpan/include/imapdriver.h | 52 + Sources/libetpan/include/imapdriver_cached.h | 52 + .../include/imapdriver_cached_message.h | 52 + Sources/libetpan/include/imapdriver_message.h | 52 + Sources/libetpan/include/imapdriver_tools.h | 88 + .../include/imapdriver_tools_private.h | 62 + Sources/libetpan/include/imapdriver_types.h | 165 + Sources/libetpan/include/imapstorage.h | 120 + Sources/libetpan/include/imfcache.h | 75 + Sources/libetpan/include/libetpan-config.h | 26 + Sources/libetpan/include/libetpan.h | 189 + Sources/libetpan/include/libetpan_version.h | 66 + Sources/libetpan/include/mail.h | 56 + Sources/libetpan/include/mail_cache_db.h | 158 + .../libetpan/include/mail_cache_db_types.h | 52 + Sources/libetpan/include/maildir.h | 67 + Sources/libetpan/include/maildir_types.h | 93 + Sources/libetpan/include/maildirdriver.h | 53 + .../libetpan/include/maildirdriver_cached.h | 53 + .../include/maildirdriver_cached_message.h | 52 + .../libetpan/include/maildirdriver_message.h | 52 + .../libetpan/include/maildirdriver_tools.h | 53 + .../libetpan/include/maildirdriver_types.h | 96 + Sources/libetpan/include/maildirstorage.h | 70 + Sources/libetpan/include/maildriver.h | 607 + Sources/libetpan/include/maildriver_errors.h | 103 + Sources/libetpan/include/maildriver_tools.h | 81 + Sources/libetpan/include/maildriver_types.h | 822 ++ .../include/maildriver_types_helper.h | 99 + Sources/libetpan/include/mailengine.h | 190 + Sources/libetpan/include/mailfolder.h | 80 + Sources/libetpan/include/mailimap.h | 935 ++ Sources/libetpan/include/mailimap_compress.h | 68 + Sources/libetpan/include/mailimap_extension.h | 111 + .../include/mailimap_extension_types.h | 115 + Sources/libetpan/include/mailimap_helper.h | 71 + Sources/libetpan/include/mailimap_id.h | 64 + Sources/libetpan/include/mailimap_id_parser.h | 53 + Sources/libetpan/include/mailimap_id_sender.h | 50 + Sources/libetpan/include/mailimap_id_types.h | 72 + Sources/libetpan/include/mailimap_keywords.h | 107 + Sources/libetpan/include/mailimap_oauth2.h | 102 + Sources/libetpan/include/mailimap_parser.h | 221 + Sources/libetpan/include/mailimap_print.h | 54 + Sources/libetpan/include/mailimap_sender.h | 223 + Sources/libetpan/include/mailimap_socket.h | 67 + Sources/libetpan/include/mailimap_sort.h | 102 + .../libetpan/include/mailimap_sort_types.h | 121 + Sources/libetpan/include/mailimap_ssl.h | 68 + Sources/libetpan/include/mailimap_types.h | 3611 +++++ .../libetpan/include/mailimap_types_helper.h | 849 ++ Sources/libetpan/include/mailimf.h | 368 + Sources/libetpan/include/mailimf_types.h | 864 ++ .../libetpan/include/mailimf_types_helper.h | 394 + Sources/libetpan/include/mailimf_write.h | 134 + Sources/libetpan/include/mailimf_write_file.h | 180 + .../libetpan/include/mailimf_write_generic.h | 150 + Sources/libetpan/include/mailimf_write_mem.h | 143 + Sources/libetpan/include/maillock.h | 53 + Sources/libetpan/include/mailmbox.h | 144 + Sources/libetpan/include/mailmbox_parse.h | 56 + Sources/libetpan/include/mailmbox_types.h | 143 + Sources/libetpan/include/mailmessage.h | 379 + Sources/libetpan/include/mailmessage_tools.h | 103 + Sources/libetpan/include/mailmessage_types.h | 50 + Sources/libetpan/include/mailmh.h | 147 + Sources/libetpan/include/mailmime.h | 118 + Sources/libetpan/include/mailmime_content.h | 173 + Sources/libetpan/include/mailmime_decode.h | 62 + .../libetpan/include/mailmime_disposition.h | 62 + Sources/libetpan/include/mailmime_types.h | 503 + .../libetpan/include/mailmime_types_helper.h | 204 + Sources/libetpan/include/mailmime_write.h | 73 + .../libetpan/include/mailmime_write_file.h | 118 + .../libetpan/include/mailmime_write_generic.h | 73 + Sources/libetpan/include/mailmime_write_mem.h | 80 + Sources/libetpan/include/mailpop3.h | 146 + Sources/libetpan/include/mailpop3_helper.h | 64 + Sources/libetpan/include/mailpop3_socket.h | 64 + Sources/libetpan/include/mailpop3_ssl.h | 61 + Sources/libetpan/include/mailpop3_types.h | 131 + Sources/libetpan/include/mailprivacy.h | 145 + Sources/libetpan/include/mailprivacy_gnupg.h | 60 + Sources/libetpan/include/mailprivacy_smime.h | 104 + Sources/libetpan/include/mailprivacy_tools.h | 120 + .../include/mailprivacy_tools_private.h | 48 + Sources/libetpan/include/mailprivacy_types.h | 83 + Sources/libetpan/include/mailsasl.h | 50 + Sources/libetpan/include/mailsasl_private.h | 18 + Sources/libetpan/include/mailsem.h | 59 + Sources/libetpan/include/mailsmtp.h | 191 + Sources/libetpan/include/mailsmtp_helper.h | 107 + Sources/libetpan/include/mailsmtp_oauth2.h | 45 + Sources/libetpan/include/mailsmtp_private.h | 43 + Sources/libetpan/include/mailsmtp_socket.h | 62 + Sources/libetpan/include/mailsmtp_ssl.h | 63 + Sources/libetpan/include/mailsmtp_types.h | 158 + Sources/libetpan/include/mailstorage.h | 110 + Sources/libetpan/include/mailstorage_tools.h | 89 + Sources/libetpan/include/mailstorage_types.h | 203 + Sources/libetpan/include/mailstream.h | 135 + Sources/libetpan/include/mailstream_cancel.h | 45 + .../include/mailstream_cancel_types.h | 41 + .../libetpan/include/mailstream_cfstream.h | 114 + .../libetpan/include/mailstream_compress.h | 72 + Sources/libetpan/include/mailstream_helper.h | 88 + Sources/libetpan/include/mailstream_low.h | 123 + Sources/libetpan/include/mailstream_socket.h | 59 + Sources/libetpan/include/mailstream_ssl.h | 140 + .../libetpan/include/mailstream_ssl_private.h | 48 + Sources/libetpan/include/mailstream_types.h | 137 + Sources/libetpan/include/mailthread.h | 111 + Sources/libetpan/include/mailthread_types.h | 64 + Sources/libetpan/include/mboxdriver.h | 52 + Sources/libetpan/include/mboxdriver_cached.h | 54 + .../include/mboxdriver_cached_message.h | 52 + Sources/libetpan/include/mboxdriver_message.h | 52 + Sources/libetpan/include/mboxdriver_types.h | 107 + Sources/libetpan/include/mboxstorage.h | 70 + Sources/libetpan/include/md5.h | 88 + Sources/libetpan/include/md5global.h | 82 + Sources/libetpan/include/md5namespace.h | 45 + Sources/libetpan/include/mhdriver.h | 52 + Sources/libetpan/include/mhdriver_cached.h | 52 + .../include/mhdriver_cached_message.h | 52 + Sources/libetpan/include/mhdriver_message.h | 52 + Sources/libetpan/include/mhdriver_types.h | 100 + Sources/libetpan/include/mhstorage.h | 68 + .../libetpan/include/mime_message_driver.h | 53 + Sources/libetpan/include/mmapstring.h | 161 + Sources/libetpan/include/mmapstring_private.h | 48 + Sources/libetpan/include/namespace.h | 57 + Sources/libetpan/include/namespace_parser.h | 55 + Sources/libetpan/include/namespace_sender.h | 48 + Sources/libetpan/include/namespace_types.h | 93 + Sources/libetpan/include/newsfeed.h | 76 + Sources/libetpan/include/newsfeed_item.h | 71 + .../include/newsfeed_item_enclosure.h | 52 + Sources/libetpan/include/newsfeed_private.h | 59 + Sources/libetpan/include/newsfeed_types.h | 96 + Sources/libetpan/include/newsnntp.h | 695 + Sources/libetpan/include/newsnntp_socket.h | 58 + Sources/libetpan/include/newsnntp_ssl.h | 62 + Sources/libetpan/include/newsnntp_types.h | 155 + Sources/libetpan/include/nntpdriver.h | 52 + Sources/libetpan/include/nntpdriver_cached.h | 52 + .../include/nntpdriver_cached_message.h | 52 + Sources/libetpan/include/nntpdriver_message.h | 52 + Sources/libetpan/include/nntpdriver_types.h | 149 + Sources/libetpan/include/nntpstorage.h | 104 + Sources/libetpan/include/parser.h | 42 + Sources/libetpan/include/parser_atom03.h | 39 + Sources/libetpan/include/parser_atom10.h | 39 + Sources/libetpan/include/parser_rdf.h | 45 + Sources/libetpan/include/parser_rss20.h | 39 + Sources/libetpan/include/pop3driver.h | 52 + Sources/libetpan/include/pop3driver_cached.h | 52 + .../include/pop3driver_cached_message.h | 52 + Sources/libetpan/include/pop3driver_message.h | 52 + Sources/libetpan/include/pop3driver_types.h | 175 + Sources/libetpan/include/pop3storage.h | 125 + Sources/libetpan/include/qresync.h | 75 + Sources/libetpan/include/qresync_private.h | 46 + Sources/libetpan/include/qresync_types.h | 68 + Sources/libetpan/include/quota.h | 59 + Sources/libetpan/include/quota_parser.h | 53 + Sources/libetpan/include/quota_sender.h | 52 + Sources/libetpan/include/quota_types.h | 121 + Sources/libetpan/include/timeutils.h | 39 + Sources/libetpan/include/uidplus.h | 98 + Sources/libetpan/include/uidplus_parser.h | 55 + Sources/libetpan/include/uidplus_sender.h | 52 + Sources/libetpan/include/uidplus_types.h | 83 + Sources/libetpan/include/xgmlabels.h | 85 + Sources/libetpan/include/xgmmsgid.h | 52 + Sources/libetpan/include/xgmthrid.h | 52 + Sources/libetpan/include/xlist.h | 63 + Sources/libetpan/low-level/Makefile.am | 46 + Sources/libetpan/low-level/feed/Makefile.am | 48 + Sources/libetpan/low-level/feed/date.c | 390 + Sources/libetpan/low-level/feed/date.h | 38 + Sources/libetpan/low-level/feed/newsfeed.c | 559 + Sources/libetpan/low-level/feed/newsfeed.h | 76 + .../libetpan/low-level/feed/newsfeed_item.c | 272 + .../libetpan/low-level/feed/newsfeed_item.h | 71 + .../low-level/feed/newsfeed_item_enclosure.c | 124 + .../low-level/feed/newsfeed_item_enclosure.h | 52 + .../low-level/feed/newsfeed_private.c | 79 + .../low-level/feed/newsfeed_private.h | 59 + .../libetpan/low-level/feed/newsfeed_types.h | 96 + Sources/libetpan/low-level/feed/parser.c | 451 + Sources/libetpan/low-level/feed/parser.h | 42 + .../libetpan/low-level/feed/parser_atom03.c | 260 + .../libetpan/low-level/feed/parser_atom03.h | 39 + .../libetpan/low-level/feed/parser_atom10.c | 253 + .../libetpan/low-level/feed/parser_atom10.h | 39 + Sources/libetpan/low-level/feed/parser_rdf.c | 218 + Sources/libetpan/low-level/feed/parser_rdf.h | 45 + .../libetpan/low-level/feed/parser_rss20.c | 262 + .../libetpan/low-level/feed/parser_rss20.h | 39 + Sources/libetpan/low-level/imap/Makefile.am | 108 + Sources/libetpan/low-level/imap/TODO | 4 + Sources/libetpan/low-level/imap/acl.c | 383 + Sources/libetpan/low-level/imap/acl.h | 165 + Sources/libetpan/low-level/imap/acl_parser.c | 460 + Sources/libetpan/low-level/imap/acl_parser.h | 92 + Sources/libetpan/low-level/imap/acl_sender.c | 185 + Sources/libetpan/low-level/imap/acl_sender.h | 66 + Sources/libetpan/low-level/imap/acl_types.c | 173 + Sources/libetpan/low-level/imap/acl_types.h | 169 + .../libetpan/low-level/imap/annotatemore.c | 208 + .../libetpan/low-level/imap/annotatemore.h | 103 + .../low-level/imap/annotatemore_parser.c | 461 + .../low-level/imap/annotatemore_parser.h | 104 + .../low-level/imap/annotatemore_sender.c | 213 + .../low-level/imap/annotatemore_sender.h | 56 + .../low-level/imap/annotatemore_types.c | 392 + .../low-level/imap/annotatemore_types.h | 268 + Sources/libetpan/low-level/imap/clientid.c | 93 + Sources/libetpan/low-level/imap/clientid.h | 66 + .../libetpan/low-level/imap/clientid_sender.c | 70 + .../libetpan/low-level/imap/clientid_sender.h | 49 + Sources/libetpan/low-level/imap/condstore.c | 984 ++ Sources/libetpan/low-level/imap/condstore.h | 101 + .../low-level/imap/condstore_private.h | 50 + .../libetpan/low-level/imap/condstore_types.c | 140 + .../libetpan/low-level/imap/condstore_types.h | 97 + Sources/libetpan/low-level/imap/enable.c | 317 + Sources/libetpan/low-level/imap/enable.h | 56 + Sources/libetpan/low-level/imap/idle.c | 218 + Sources/libetpan/low-level/imap/idle.h | 64 + Sources/libetpan/low-level/imap/mailimap.c | 2806 ++++ Sources/libetpan/low-level/imap/mailimap.h | 935 ++ .../low-level/imap/mailimap_compress.c | 118 + .../low-level/imap/mailimap_compress.h | 68 + .../low-level/imap/mailimap_extension.c | 241 + .../low-level/imap/mailimap_extension.h | 111 + .../low-level/imap/mailimap_extension_types.h | 115 + .../libetpan/low-level/imap/mailimap_helper.c | 209 + .../libetpan/low-level/imap/mailimap_helper.h | 71 + Sources/libetpan/low-level/imap/mailimap_id.c | 231 + Sources/libetpan/low-level/imap/mailimap_id.h | 64 + .../low-level/imap/mailimap_id_parser.c | 193 + .../low-level/imap/mailimap_id_parser.h | 53 + .../low-level/imap/mailimap_id_sender.c | 113 + .../low-level/imap/mailimap_id_sender.h | 50 + .../low-level/imap/mailimap_id_types.c | 119 + .../low-level/imap/mailimap_id_types.h | 72 + .../low-level/imap/mailimap_keywords.c | 361 + .../low-level/imap/mailimap_keywords.h | 107 + .../libetpan/low-level/imap/mailimap_oauth2.c | 206 + .../libetpan/low-level/imap/mailimap_oauth2.h | 102 + .../libetpan/low-level/imap/mailimap_parser.c | 11238 ++++++++++++++++ .../libetpan/low-level/imap/mailimap_parser.h | 221 + .../libetpan/low-level/imap/mailimap_print.c | 1619 +++ .../libetpan/low-level/imap/mailimap_print.h | 54 + .../libetpan/low-level/imap/mailimap_sender.c | 3358 +++++ .../libetpan/low-level/imap/mailimap_sender.h | 223 + .../libetpan/low-level/imap/mailimap_socket.c | 187 + .../libetpan/low-level/imap/mailimap_socket.h | 67 + .../libetpan/low-level/imap/mailimap_sort.c | 455 + .../libetpan/low-level/imap/mailimap_sort.h | 105 + .../low-level/imap/mailimap_sort_types.c | 147 + .../low-level/imap/mailimap_sort_types.h | 121 + .../libetpan/low-level/imap/mailimap_ssl.c | 147 + .../libetpan/low-level/imap/mailimap_ssl.h | 68 + .../libetpan/low-level/imap/mailimap_types.c | 3287 +++++ .../libetpan/low-level/imap/mailimap_types.h | 3611 +++++ .../low-level/imap/mailimap_types_helper.c | 1351 ++ .../low-level/imap/mailimap_types_helper.h | 849 ++ Sources/libetpan/low-level/imap/namespace.c | 145 + Sources/libetpan/low-level/imap/namespace.h | 57 + .../low-level/imap/namespace_parser.c | 461 + .../low-level/imap/namespace_parser.h | 55 + .../low-level/imap/namespace_sender.c | 43 + .../low-level/imap/namespace_sender.h | 48 + .../libetpan/low-level/imap/namespace_types.c | 165 + .../libetpan/low-level/imap/namespace_types.h | 93 + Sources/libetpan/low-level/imap/qresync.c | 688 + Sources/libetpan/low-level/imap/qresync.h | 75 + .../libetpan/low-level/imap/qresync_private.h | 46 + .../libetpan/low-level/imap/qresync_types.c | 78 + .../libetpan/low-level/imap/qresync_types.h | 68 + Sources/libetpan/low-level/imap/quota.c | 185 + Sources/libetpan/low-level/imap/quota.h | 62 + .../libetpan/low-level/imap/quota_parser.c | 428 + .../libetpan/low-level/imap/quota_parser.h | 53 + .../libetpan/low-level/imap/quota_sender.c | 79 + .../libetpan/low-level/imap/quota_sender.h | 52 + Sources/libetpan/low-level/imap/quota_types.c | 151 + Sources/libetpan/low-level/imap/quota_types.h | 121 + Sources/libetpan/low-level/imap/uidplus.c | 311 + Sources/libetpan/low-level/imap/uidplus.h | 98 + .../libetpan/low-level/imap/uidplus_parser.c | 411 + .../libetpan/low-level/imap/uidplus_parser.h | 55 + .../libetpan/low-level/imap/uidplus_sender.c | 58 + .../libetpan/low-level/imap/uidplus_sender.h | 52 + .../libetpan/low-level/imap/uidplus_types.c | 104 + .../libetpan/low-level/imap/uidplus_types.h | 83 + Sources/libetpan/low-level/imap/xgmlabels.c | 464 + Sources/libetpan/low-level/imap/xgmlabels.h | 85 + Sources/libetpan/low-level/imap/xgmmsgid.c | 163 + Sources/libetpan/low-level/imap/xgmmsgid.h | 52 + Sources/libetpan/low-level/imap/xgmthrid.c | 163 + Sources/libetpan/low-level/imap/xgmthrid.h | 52 + Sources/libetpan/low-level/imap/xlist.c | 283 + Sources/libetpan/low-level/imap/xlist.h | 63 + Sources/libetpan/low-level/imf/Makefile.am | 48 + Sources/libetpan/low-level/imf/TODO | 12 + Sources/libetpan/low-level/imf/mailimf.c | 7843 +++++++++++ Sources/libetpan/low-level/imf/mailimf.h | 368 + .../libetpan/low-level/imf/mailimf_types.c | 925 ++ .../libetpan/low-level/imf/mailimf_types.h | 864 ++ .../low-level/imf/mailimf_types_helper.c | 1503 +++ .../low-level/imf/mailimf_types_helper.h | 394 + .../libetpan/low-level/imf/mailimf_write.h | 134 + .../low-level/imf/mailimf_write_file.c | 157 + .../low-level/imf/mailimf_write_file.h | 180 + .../low-level/imf/mailimf_write_generic.c | 2030 +++ .../low-level/imf/mailimf_write_generic.h | 150 + .../low-level/imf/mailimf_write_mem.c | 106 + .../low-level/imf/mailimf_write_mem.h | 143 + .../libetpan/low-level/maildir/Makefile.am | 41 + Sources/libetpan/low-level/maildir/maildir.c | 811 ++ Sources/libetpan/low-level/maildir/maildir.h | 67 + .../low-level/maildir/maildir_types.h | 93 + Sources/libetpan/low-level/mbox/Makefile.am | 44 + Sources/libetpan/low-level/mbox/TODO | 0 Sources/libetpan/low-level/mbox/mailmbox.c | 1566 +++ Sources/libetpan/low-level/mbox/mailmbox.h | 144 + .../libetpan/low-level/mbox/mailmbox_parse.c | 623 + .../libetpan/low-level/mbox/mailmbox_parse.h | 56 + .../libetpan/low-level/mbox/mailmbox_types.c | 252 + .../libetpan/low-level/mbox/mailmbox_types.h | 143 + Sources/libetpan/low-level/mh/Makefile.am | 41 + Sources/libetpan/low-level/mh/mailmh.c | 915 ++ Sources/libetpan/low-level/mh/mailmh.h | 147 + Sources/libetpan/low-level/mime/Makefile.am | 50 + Sources/libetpan/low-level/mime/TODO | 10 + Sources/libetpan/low-level/mime/mailmime.c | 1474 ++ Sources/libetpan/low-level/mime/mailmime.h | 118 + .../low-level/mime/mailmime_content.c | 2267 ++++ .../low-level/mime/mailmime_content.h | 173 + .../libetpan/low-level/mime/mailmime_decode.c | 733 + .../libetpan/low-level/mime/mailmime_decode.h | 62 + .../low-level/mime/mailmime_disposition.c | 621 + .../low-level/mime/mailmime_disposition.h | 62 + .../libetpan/low-level/mime/mailmime_types.c | 770 ++ .../libetpan/low-level/mime/mailmime_types.h | 503 + .../low-level/mime/mailmime_types_helper.c | 1426 ++ .../low-level/mime/mailmime_types_helper.h | 204 + .../libetpan/low-level/mime/mailmime_write.h | 73 + .../low-level/mime/mailmime_write_file.c | 164 + .../low-level/mime/mailmime_write_file.h | 118 + .../low-level/mime/mailmime_write_generic.c | 1545 +++ .../low-level/mime/mailmime_write_generic.h | 73 + .../low-level/mime/mailmime_write_mem.c | 114 + .../low-level/mime/mailmime_write_mem.h | 80 + Sources/libetpan/low-level/nntp/Makefile.am | 41 + Sources/libetpan/low-level/nntp/newsnntp.c | 2574 ++++ Sources/libetpan/low-level/nntp/newsnntp.h | 695 + .../libetpan/low-level/nntp/newsnntp_socket.c | 112 + .../libetpan/low-level/nntp/newsnntp_socket.h | 58 + .../libetpan/low-level/nntp/newsnntp_ssl.c | 135 + .../libetpan/low-level/nntp/newsnntp_ssl.h | 62 + .../libetpan/low-level/nntp/newsnntp_types.h | 155 + Sources/libetpan/low-level/pop3/Makefile.am | 42 + Sources/libetpan/low-level/pop3/mailpop3.c | 1695 +++ Sources/libetpan/low-level/pop3/mailpop3.h | 146 + .../libetpan/low-level/pop3/mailpop3_helper.c | 83 + .../libetpan/low-level/pop3/mailpop3_helper.h | 64 + .../libetpan/low-level/pop3/mailpop3_socket.c | 179 + .../libetpan/low-level/pop3/mailpop3_socket.h | 64 + .../libetpan/low-level/pop3/mailpop3_ssl.c | 133 + .../libetpan/low-level/pop3/mailpop3_ssl.h | 61 + .../libetpan/low-level/pop3/mailpop3_types.h | 131 + Sources/libetpan/low-level/smtp/Makefile.am | 49 + Sources/libetpan/low-level/smtp/TODO | 1 + Sources/libetpan/low-level/smtp/mailsmtp.c | 1654 +++ Sources/libetpan/low-level/smtp/mailsmtp.h | 191 + .../libetpan/low-level/smtp/mailsmtp_helper.c | 303 + .../libetpan/low-level/smtp/mailsmtp_helper.h | 107 + .../libetpan/low-level/smtp/mailsmtp_oauth2.c | 210 + .../libetpan/low-level/smtp/mailsmtp_oauth2.h | 45 + .../low-level/smtp/mailsmtp_private.h | 43 + .../libetpan/low-level/smtp/mailsmtp_socket.c | 171 + .../libetpan/low-level/smtp/mailsmtp_socket.h | 62 + .../libetpan/low-level/smtp/mailsmtp_ssl.c | 139 + .../libetpan/low-level/smtp/mailsmtp_ssl.h | 63 + .../libetpan/low-level/smtp/mailsmtp_types.h | 158 + Sources/libetpan/main/Makefile.am | 46 + Sources/libetpan/main/libetpan.h | 131 + Sources/libetpan/main/libetpan_version.c | 52 + Sources/libetpan/main/libetpan_version.h.in | 66 + 644 files changed, 182837 insertions(+) create mode 100644 Package.swift create mode 100644 README.md create mode 100644 Sources/libetpan/data-types/Makefile.am create mode 100644 Sources/libetpan/data-types/base64.c create mode 100644 Sources/libetpan/data-types/base64.h create mode 100644 Sources/libetpan/data-types/carray.c create mode 100644 Sources/libetpan/data-types/carray.h create mode 100644 Sources/libetpan/data-types/charconv.c create mode 100644 Sources/libetpan/data-types/charconv.h create mode 100644 Sources/libetpan/data-types/chash.c create mode 100644 Sources/libetpan/data-types/chash.h create mode 100644 Sources/libetpan/data-types/clist.c create mode 100644 Sources/libetpan/data-types/clist.h create mode 100644 Sources/libetpan/data-types/connect.c create mode 100644 Sources/libetpan/data-types/connect.h create mode 100644 Sources/libetpan/data-types/hmac-md5.h create mode 100644 Sources/libetpan/data-types/mail.h create mode 100644 Sources/libetpan/data-types/mail_cache_db.c create mode 100644 Sources/libetpan/data-types/mail_cache_db.h create mode 100644 Sources/libetpan/data-types/mail_cache_db_types.h create mode 100644 Sources/libetpan/data-types/mail_cache_lmdb.c create mode 100644 Sources/libetpan/data-types/maillock.c create mode 100644 Sources/libetpan/data-types/maillock.h create mode 100644 Sources/libetpan/data-types/mailsasl.c create mode 100644 Sources/libetpan/data-types/mailsasl.h create mode 100644 Sources/libetpan/data-types/mailsasl_private.h create mode 100644 Sources/libetpan/data-types/mailsem.c create mode 100644 Sources/libetpan/data-types/mailsem.h create mode 100644 Sources/libetpan/data-types/mailstream.c create mode 100644 Sources/libetpan/data-types/mailstream.h create mode 100644 Sources/libetpan/data-types/mailstream_cancel.c create mode 100644 Sources/libetpan/data-types/mailstream_cancel.h create mode 100644 Sources/libetpan/data-types/mailstream_cancel_types.h create mode 100644 Sources/libetpan/data-types/mailstream_cfstream.c create mode 100644 Sources/libetpan/data-types/mailstream_cfstream.h create mode 100644 Sources/libetpan/data-types/mailstream_compress.c create mode 100644 Sources/libetpan/data-types/mailstream_compress.h create mode 100644 Sources/libetpan/data-types/mailstream_helper.c create mode 100644 Sources/libetpan/data-types/mailstream_helper.h create mode 100644 Sources/libetpan/data-types/mailstream_low.c create mode 100644 Sources/libetpan/data-types/mailstream_low.h create mode 100644 Sources/libetpan/data-types/mailstream_socket.c create mode 100644 Sources/libetpan/data-types/mailstream_socket.h create mode 100644 Sources/libetpan/data-types/mailstream_ssl.c create mode 100644 Sources/libetpan/data-types/mailstream_ssl.h create mode 100644 Sources/libetpan/data-types/mailstream_ssl_private.h create mode 100644 Sources/libetpan/data-types/mailstream_types.h create mode 100644 Sources/libetpan/data-types/md5.c create mode 100644 Sources/libetpan/data-types/md5.h create mode 100644 Sources/libetpan/data-types/md5global.h create mode 100644 Sources/libetpan/data-types/md5namespace.h create mode 100644 Sources/libetpan/data-types/mmapstring.c create mode 100644 Sources/libetpan/data-types/mmapstring.h create mode 100644 Sources/libetpan/data-types/mmapstring_private.h create mode 100644 Sources/libetpan/data-types/timeutils.c create mode 100644 Sources/libetpan/data-types/timeutils.h create mode 100644 Sources/libetpan/driver/Makefile.am create mode 100644 Sources/libetpan/driver/TODO create mode 100644 Sources/libetpan/driver/implementation/Makefile.am create mode 100644 Sources/libetpan/driver/implementation/data-message/Makefile.am create mode 100644 Sources/libetpan/driver/implementation/data-message/data_message_driver.c create mode 100644 Sources/libetpan/driver/implementation/data-message/data_message_driver.h create mode 100644 Sources/libetpan/driver/implementation/db/Makefile.am create mode 100644 Sources/libetpan/driver/implementation/db/dbdriver.c create mode 100644 Sources/libetpan/driver/implementation/db/dbdriver.h create mode 100644 Sources/libetpan/driver/implementation/db/dbdriver_message.c create mode 100644 Sources/libetpan/driver/implementation/db/dbdriver_message.h create mode 100644 Sources/libetpan/driver/implementation/db/dbdriver_types.h create mode 100644 Sources/libetpan/driver/implementation/db/dbstorage.c create mode 100644 Sources/libetpan/driver/implementation/db/dbstorage.h create mode 100644 Sources/libetpan/driver/implementation/feed/Makefile.am create mode 100644 Sources/libetpan/driver/implementation/feed/feeddriver.c create mode 100644 Sources/libetpan/driver/implementation/feed/feeddriver.h create mode 100644 Sources/libetpan/driver/implementation/feed/feeddriver_message.c create mode 100644 Sources/libetpan/driver/implementation/feed/feeddriver_message.h create mode 100644 Sources/libetpan/driver/implementation/feed/feeddriver_types.h create mode 100644 Sources/libetpan/driver/implementation/feed/feedstorage.c create mode 100644 Sources/libetpan/driver/implementation/feed/feedstorage.h create mode 100644 Sources/libetpan/driver/implementation/hotmail/Makefile.am create mode 100644 Sources/libetpan/driver/implementation/hotmail/hotmailstorage.c create mode 100644 Sources/libetpan/driver/implementation/hotmail/hotmailstorage.h create mode 100644 Sources/libetpan/driver/implementation/imap/Makefile.am create mode 100644 Sources/libetpan/driver/implementation/imap/imapdriver.c create mode 100644 Sources/libetpan/driver/implementation/imap/imapdriver.h create mode 100644 Sources/libetpan/driver/implementation/imap/imapdriver_cached.c create mode 100644 Sources/libetpan/driver/implementation/imap/imapdriver_cached.h create mode 100644 Sources/libetpan/driver/implementation/imap/imapdriver_cached_message.c create mode 100644 Sources/libetpan/driver/implementation/imap/imapdriver_cached_message.h create mode 100644 Sources/libetpan/driver/implementation/imap/imapdriver_message.c create mode 100644 Sources/libetpan/driver/implementation/imap/imapdriver_message.h create mode 100644 Sources/libetpan/driver/implementation/imap/imapdriver_tools.c create mode 100644 Sources/libetpan/driver/implementation/imap/imapdriver_tools.h create mode 100644 Sources/libetpan/driver/implementation/imap/imapdriver_tools_private.h create mode 100644 Sources/libetpan/driver/implementation/imap/imapdriver_types.h create mode 100644 Sources/libetpan/driver/implementation/imap/imapstorage.c create mode 100644 Sources/libetpan/driver/implementation/imap/imapstorage.h create mode 100644 Sources/libetpan/driver/implementation/maildir/Makefile.am create mode 100644 Sources/libetpan/driver/implementation/maildir/maildirdriver.c create mode 100644 Sources/libetpan/driver/implementation/maildir/maildirdriver.h create mode 100644 Sources/libetpan/driver/implementation/maildir/maildirdriver_cached.c create mode 100644 Sources/libetpan/driver/implementation/maildir/maildirdriver_cached.h create mode 100644 Sources/libetpan/driver/implementation/maildir/maildirdriver_cached_message.c create mode 100644 Sources/libetpan/driver/implementation/maildir/maildirdriver_cached_message.h create mode 100644 Sources/libetpan/driver/implementation/maildir/maildirdriver_message.c create mode 100644 Sources/libetpan/driver/implementation/maildir/maildirdriver_message.h create mode 100644 Sources/libetpan/driver/implementation/maildir/maildirdriver_tools.c create mode 100644 Sources/libetpan/driver/implementation/maildir/maildirdriver_tools.h create mode 100644 Sources/libetpan/driver/implementation/maildir/maildirdriver_types.h create mode 100644 Sources/libetpan/driver/implementation/maildir/maildirstorage.c create mode 100644 Sources/libetpan/driver/implementation/maildir/maildirstorage.h create mode 100644 Sources/libetpan/driver/implementation/mbox/Makefile.am create mode 100644 Sources/libetpan/driver/implementation/mbox/mboxdriver.c create mode 100644 Sources/libetpan/driver/implementation/mbox/mboxdriver.h create mode 100644 Sources/libetpan/driver/implementation/mbox/mboxdriver_cached.c create mode 100644 Sources/libetpan/driver/implementation/mbox/mboxdriver_cached.h create mode 100644 Sources/libetpan/driver/implementation/mbox/mboxdriver_cached_message.c create mode 100644 Sources/libetpan/driver/implementation/mbox/mboxdriver_cached_message.h create mode 100644 Sources/libetpan/driver/implementation/mbox/mboxdriver_message.c create mode 100644 Sources/libetpan/driver/implementation/mbox/mboxdriver_message.h create mode 100644 Sources/libetpan/driver/implementation/mbox/mboxdriver_tools.c create mode 100644 Sources/libetpan/driver/implementation/mbox/mboxdriver_tools.h create mode 100644 Sources/libetpan/driver/implementation/mbox/mboxdriver_types.h create mode 100644 Sources/libetpan/driver/implementation/mbox/mboxstorage.c create mode 100644 Sources/libetpan/driver/implementation/mbox/mboxstorage.h create mode 100644 Sources/libetpan/driver/implementation/mh/Makefile.am create mode 100644 Sources/libetpan/driver/implementation/mh/mhdriver.c create mode 100644 Sources/libetpan/driver/implementation/mh/mhdriver.h create mode 100644 Sources/libetpan/driver/implementation/mh/mhdriver_cached.c create mode 100644 Sources/libetpan/driver/implementation/mh/mhdriver_cached.h create mode 100644 Sources/libetpan/driver/implementation/mh/mhdriver_cached_message.c create mode 100644 Sources/libetpan/driver/implementation/mh/mhdriver_cached_message.h create mode 100644 Sources/libetpan/driver/implementation/mh/mhdriver_message.c create mode 100644 Sources/libetpan/driver/implementation/mh/mhdriver_message.h create mode 100644 Sources/libetpan/driver/implementation/mh/mhdriver_tools.c create mode 100644 Sources/libetpan/driver/implementation/mh/mhdriver_tools.h create mode 100644 Sources/libetpan/driver/implementation/mh/mhdriver_types.h create mode 100644 Sources/libetpan/driver/implementation/mh/mhstorage.c create mode 100644 Sources/libetpan/driver/implementation/mh/mhstorage.h create mode 100644 Sources/libetpan/driver/implementation/mime-message/Makefile.am create mode 100644 Sources/libetpan/driver/implementation/mime-message/mime_message_driver.c create mode 100644 Sources/libetpan/driver/implementation/mime-message/mime_message_driver.h create mode 100644 Sources/libetpan/driver/implementation/nntp/Makefile.am create mode 100644 Sources/libetpan/driver/implementation/nntp/nntpdriver.c create mode 100644 Sources/libetpan/driver/implementation/nntp/nntpdriver.h create mode 100644 Sources/libetpan/driver/implementation/nntp/nntpdriver_cached.c create mode 100644 Sources/libetpan/driver/implementation/nntp/nntpdriver_cached.h create mode 100644 Sources/libetpan/driver/implementation/nntp/nntpdriver_cached_message.c create mode 100644 Sources/libetpan/driver/implementation/nntp/nntpdriver_cached_message.h create mode 100644 Sources/libetpan/driver/implementation/nntp/nntpdriver_message.c create mode 100644 Sources/libetpan/driver/implementation/nntp/nntpdriver_message.h create mode 100644 Sources/libetpan/driver/implementation/nntp/nntpdriver_tools.c create mode 100644 Sources/libetpan/driver/implementation/nntp/nntpdriver_tools.h create mode 100644 Sources/libetpan/driver/implementation/nntp/nntpdriver_types.h create mode 100644 Sources/libetpan/driver/implementation/nntp/nntpstorage.c create mode 100644 Sources/libetpan/driver/implementation/nntp/nntpstorage.h create mode 100644 Sources/libetpan/driver/implementation/pop3/Makefile.am create mode 100644 Sources/libetpan/driver/implementation/pop3/pop3driver.c create mode 100644 Sources/libetpan/driver/implementation/pop3/pop3driver.h create mode 100644 Sources/libetpan/driver/implementation/pop3/pop3driver_cached.c create mode 100644 Sources/libetpan/driver/implementation/pop3/pop3driver_cached.h create mode 100644 Sources/libetpan/driver/implementation/pop3/pop3driver_cached_message.c create mode 100644 Sources/libetpan/driver/implementation/pop3/pop3driver_cached_message.h create mode 100644 Sources/libetpan/driver/implementation/pop3/pop3driver_message.c create mode 100644 Sources/libetpan/driver/implementation/pop3/pop3driver_message.h create mode 100644 Sources/libetpan/driver/implementation/pop3/pop3driver_tools.c create mode 100644 Sources/libetpan/driver/implementation/pop3/pop3driver_tools.h create mode 100644 Sources/libetpan/driver/implementation/pop3/pop3driver_types.h create mode 100644 Sources/libetpan/driver/implementation/pop3/pop3storage.c create mode 100644 Sources/libetpan/driver/implementation/pop3/pop3storage.h create mode 100644 Sources/libetpan/driver/interface/Makefile.am create mode 100644 Sources/libetpan/driver/interface/maildriver.c create mode 100644 Sources/libetpan/driver/interface/maildriver.h create mode 100644 Sources/libetpan/driver/interface/maildriver_errors.h create mode 100644 Sources/libetpan/driver/interface/maildriver_tools.c create mode 100644 Sources/libetpan/driver/interface/maildriver_tools.h create mode 100644 Sources/libetpan/driver/interface/maildriver_types.c create mode 100644 Sources/libetpan/driver/interface/maildriver_types.h create mode 100644 Sources/libetpan/driver/interface/maildriver_types_helper.c create mode 100644 Sources/libetpan/driver/interface/maildriver_types_helper.h create mode 100644 Sources/libetpan/driver/interface/mailfolder.c create mode 100644 Sources/libetpan/driver/interface/mailfolder.h create mode 100644 Sources/libetpan/driver/interface/mailmessage.c create mode 100644 Sources/libetpan/driver/interface/mailmessage.h create mode 100644 Sources/libetpan/driver/interface/mailmessage_tools.c create mode 100644 Sources/libetpan/driver/interface/mailmessage_tools.h create mode 100644 Sources/libetpan/driver/interface/mailmessage_types.c create mode 100644 Sources/libetpan/driver/interface/mailmessage_types.h create mode 100644 Sources/libetpan/driver/interface/mailstorage.c create mode 100644 Sources/libetpan/driver/interface/mailstorage.h create mode 100644 Sources/libetpan/driver/interface/mailstorage_tools.c create mode 100644 Sources/libetpan/driver/interface/mailstorage_tools.h create mode 100644 Sources/libetpan/driver/interface/mailstorage_types.h create mode 100644 Sources/libetpan/driver/tools/Makefile.am create mode 100644 Sources/libetpan/driver/tools/generic_cache.c create mode 100644 Sources/libetpan/driver/tools/generic_cache.h create mode 100644 Sources/libetpan/driver/tools/generic_cache_types.h create mode 100644 Sources/libetpan/driver/tools/imfcache.c create mode 100644 Sources/libetpan/driver/tools/imfcache.h create mode 100644 Sources/libetpan/driver/tools/mailthread.c create mode 100644 Sources/libetpan/driver/tools/mailthread.h create mode 100644 Sources/libetpan/driver/tools/mailthread_types.c create mode 100644 Sources/libetpan/driver/tools/mailthread_types.h create mode 100644 Sources/libetpan/engine/Makefile.am create mode 100644 Sources/libetpan/engine/mailengine.c create mode 100644 Sources/libetpan/engine/mailengine.h create mode 100644 Sources/libetpan/engine/mailprivacy.c create mode 100644 Sources/libetpan/engine/mailprivacy.h create mode 100644 Sources/libetpan/engine/mailprivacy_gnupg.c create mode 100644 Sources/libetpan/engine/mailprivacy_gnupg.h create mode 100644 Sources/libetpan/engine/mailprivacy_smime.c create mode 100644 Sources/libetpan/engine/mailprivacy_smime.h create mode 100644 Sources/libetpan/engine/mailprivacy_tools.c create mode 100644 Sources/libetpan/engine/mailprivacy_tools.h create mode 100644 Sources/libetpan/engine/mailprivacy_tools_private.h create mode 100644 Sources/libetpan/engine/mailprivacy_types.h create mode 100644 Sources/libetpan/include/acl.h create mode 100644 Sources/libetpan/include/acl_parser.h create mode 100644 Sources/libetpan/include/acl_sender.h create mode 100644 Sources/libetpan/include/acl_types.h create mode 100644 Sources/libetpan/include/annotatemore.h create mode 100644 Sources/libetpan/include/annotatemore_parser.h create mode 100644 Sources/libetpan/include/annotatemore_sender.h create mode 100644 Sources/libetpan/include/annotatemore_types.h create mode 100644 Sources/libetpan/include/base64.h create mode 100644 Sources/libetpan/include/carray.h create mode 100644 Sources/libetpan/include/charconv.h create mode 100644 Sources/libetpan/include/chash.h create mode 100644 Sources/libetpan/include/clientid.h create mode 100644 Sources/libetpan/include/clientid_sender.h create mode 100644 Sources/libetpan/include/clist.h create mode 100644 Sources/libetpan/include/condstore.h create mode 100644 Sources/libetpan/include/condstore_private.h create mode 100644 Sources/libetpan/include/condstore_types.h create mode 100644 Sources/libetpan/include/config.h create mode 100644 Sources/libetpan/include/connect.h create mode 100644 Sources/libetpan/include/data_message_driver.h create mode 100644 Sources/libetpan/include/date.h create mode 100644 Sources/libetpan/include/dbdriver.h create mode 100644 Sources/libetpan/include/dbdriver_message.h create mode 100644 Sources/libetpan/include/dbdriver_types.h create mode 100644 Sources/libetpan/include/dbstorage.h create mode 100644 Sources/libetpan/include/enable.h create mode 100644 Sources/libetpan/include/feeddriver.h create mode 100644 Sources/libetpan/include/feeddriver_message.h create mode 100644 Sources/libetpan/include/feeddriver_types.h create mode 100644 Sources/libetpan/include/feedstorage.h create mode 100644 Sources/libetpan/include/generic_cache.h create mode 100644 Sources/libetpan/include/generic_cache_types.h create mode 100644 Sources/libetpan/include/hotmailstorage.h create mode 100644 Sources/libetpan/include/idle.h create mode 100644 Sources/libetpan/include/imapdriver.h create mode 100644 Sources/libetpan/include/imapdriver_cached.h create mode 100644 Sources/libetpan/include/imapdriver_cached_message.h create mode 100644 Sources/libetpan/include/imapdriver_message.h create mode 100644 Sources/libetpan/include/imapdriver_tools.h create mode 100644 Sources/libetpan/include/imapdriver_tools_private.h create mode 100644 Sources/libetpan/include/imapdriver_types.h create mode 100644 Sources/libetpan/include/imapstorage.h create mode 100644 Sources/libetpan/include/imfcache.h create mode 100644 Sources/libetpan/include/libetpan-config.h create mode 100644 Sources/libetpan/include/libetpan.h create mode 100644 Sources/libetpan/include/libetpan_version.h create mode 100644 Sources/libetpan/include/mail.h create mode 100644 Sources/libetpan/include/mail_cache_db.h create mode 100644 Sources/libetpan/include/mail_cache_db_types.h create mode 100644 Sources/libetpan/include/maildir.h create mode 100644 Sources/libetpan/include/maildir_types.h create mode 100644 Sources/libetpan/include/maildirdriver.h create mode 100644 Sources/libetpan/include/maildirdriver_cached.h create mode 100644 Sources/libetpan/include/maildirdriver_cached_message.h create mode 100644 Sources/libetpan/include/maildirdriver_message.h create mode 100644 Sources/libetpan/include/maildirdriver_tools.h create mode 100644 Sources/libetpan/include/maildirdriver_types.h create mode 100644 Sources/libetpan/include/maildirstorage.h create mode 100644 Sources/libetpan/include/maildriver.h create mode 100644 Sources/libetpan/include/maildriver_errors.h create mode 100644 Sources/libetpan/include/maildriver_tools.h create mode 100644 Sources/libetpan/include/maildriver_types.h create mode 100644 Sources/libetpan/include/maildriver_types_helper.h create mode 100644 Sources/libetpan/include/mailengine.h create mode 100644 Sources/libetpan/include/mailfolder.h create mode 100644 Sources/libetpan/include/mailimap.h create mode 100644 Sources/libetpan/include/mailimap_compress.h create mode 100644 Sources/libetpan/include/mailimap_extension.h create mode 100644 Sources/libetpan/include/mailimap_extension_types.h create mode 100644 Sources/libetpan/include/mailimap_helper.h create mode 100644 Sources/libetpan/include/mailimap_id.h create mode 100644 Sources/libetpan/include/mailimap_id_parser.h create mode 100644 Sources/libetpan/include/mailimap_id_sender.h create mode 100644 Sources/libetpan/include/mailimap_id_types.h create mode 100644 Sources/libetpan/include/mailimap_keywords.h create mode 100644 Sources/libetpan/include/mailimap_oauth2.h create mode 100644 Sources/libetpan/include/mailimap_parser.h create mode 100644 Sources/libetpan/include/mailimap_print.h create mode 100644 Sources/libetpan/include/mailimap_sender.h create mode 100644 Sources/libetpan/include/mailimap_socket.h create mode 100644 Sources/libetpan/include/mailimap_sort.h create mode 100644 Sources/libetpan/include/mailimap_sort_types.h create mode 100644 Sources/libetpan/include/mailimap_ssl.h create mode 100644 Sources/libetpan/include/mailimap_types.h create mode 100644 Sources/libetpan/include/mailimap_types_helper.h create mode 100644 Sources/libetpan/include/mailimf.h create mode 100644 Sources/libetpan/include/mailimf_types.h create mode 100644 Sources/libetpan/include/mailimf_types_helper.h create mode 100644 Sources/libetpan/include/mailimf_write.h create mode 100644 Sources/libetpan/include/mailimf_write_file.h create mode 100644 Sources/libetpan/include/mailimf_write_generic.h create mode 100644 Sources/libetpan/include/mailimf_write_mem.h create mode 100644 Sources/libetpan/include/maillock.h create mode 100644 Sources/libetpan/include/mailmbox.h create mode 100644 Sources/libetpan/include/mailmbox_parse.h create mode 100644 Sources/libetpan/include/mailmbox_types.h create mode 100644 Sources/libetpan/include/mailmessage.h create mode 100644 Sources/libetpan/include/mailmessage_tools.h create mode 100644 Sources/libetpan/include/mailmessage_types.h create mode 100644 Sources/libetpan/include/mailmh.h create mode 100644 Sources/libetpan/include/mailmime.h create mode 100644 Sources/libetpan/include/mailmime_content.h create mode 100644 Sources/libetpan/include/mailmime_decode.h create mode 100644 Sources/libetpan/include/mailmime_disposition.h create mode 100644 Sources/libetpan/include/mailmime_types.h create mode 100644 Sources/libetpan/include/mailmime_types_helper.h create mode 100644 Sources/libetpan/include/mailmime_write.h create mode 100644 Sources/libetpan/include/mailmime_write_file.h create mode 100644 Sources/libetpan/include/mailmime_write_generic.h create mode 100644 Sources/libetpan/include/mailmime_write_mem.h create mode 100644 Sources/libetpan/include/mailpop3.h create mode 100644 Sources/libetpan/include/mailpop3_helper.h create mode 100644 Sources/libetpan/include/mailpop3_socket.h create mode 100644 Sources/libetpan/include/mailpop3_ssl.h create mode 100644 Sources/libetpan/include/mailpop3_types.h create mode 100644 Sources/libetpan/include/mailprivacy.h create mode 100644 Sources/libetpan/include/mailprivacy_gnupg.h create mode 100644 Sources/libetpan/include/mailprivacy_smime.h create mode 100644 Sources/libetpan/include/mailprivacy_tools.h create mode 100644 Sources/libetpan/include/mailprivacy_tools_private.h create mode 100644 Sources/libetpan/include/mailprivacy_types.h create mode 100644 Sources/libetpan/include/mailsasl.h create mode 100644 Sources/libetpan/include/mailsasl_private.h create mode 100644 Sources/libetpan/include/mailsem.h create mode 100644 Sources/libetpan/include/mailsmtp.h create mode 100644 Sources/libetpan/include/mailsmtp_helper.h create mode 100644 Sources/libetpan/include/mailsmtp_oauth2.h create mode 100644 Sources/libetpan/include/mailsmtp_private.h create mode 100644 Sources/libetpan/include/mailsmtp_socket.h create mode 100644 Sources/libetpan/include/mailsmtp_ssl.h create mode 100644 Sources/libetpan/include/mailsmtp_types.h create mode 100644 Sources/libetpan/include/mailstorage.h create mode 100644 Sources/libetpan/include/mailstorage_tools.h create mode 100644 Sources/libetpan/include/mailstorage_types.h create mode 100644 Sources/libetpan/include/mailstream.h create mode 100644 Sources/libetpan/include/mailstream_cancel.h create mode 100644 Sources/libetpan/include/mailstream_cancel_types.h create mode 100644 Sources/libetpan/include/mailstream_cfstream.h create mode 100644 Sources/libetpan/include/mailstream_compress.h create mode 100644 Sources/libetpan/include/mailstream_helper.h create mode 100644 Sources/libetpan/include/mailstream_low.h create mode 100644 Sources/libetpan/include/mailstream_socket.h create mode 100644 Sources/libetpan/include/mailstream_ssl.h create mode 100644 Sources/libetpan/include/mailstream_ssl_private.h create mode 100644 Sources/libetpan/include/mailstream_types.h create mode 100644 Sources/libetpan/include/mailthread.h create mode 100644 Sources/libetpan/include/mailthread_types.h create mode 100644 Sources/libetpan/include/mboxdriver.h create mode 100644 Sources/libetpan/include/mboxdriver_cached.h create mode 100644 Sources/libetpan/include/mboxdriver_cached_message.h create mode 100644 Sources/libetpan/include/mboxdriver_message.h create mode 100644 Sources/libetpan/include/mboxdriver_types.h create mode 100644 Sources/libetpan/include/mboxstorage.h create mode 100644 Sources/libetpan/include/md5.h create mode 100644 Sources/libetpan/include/md5global.h create mode 100644 Sources/libetpan/include/md5namespace.h create mode 100644 Sources/libetpan/include/mhdriver.h create mode 100644 Sources/libetpan/include/mhdriver_cached.h create mode 100644 Sources/libetpan/include/mhdriver_cached_message.h create mode 100644 Sources/libetpan/include/mhdriver_message.h create mode 100644 Sources/libetpan/include/mhdriver_types.h create mode 100644 Sources/libetpan/include/mhstorage.h create mode 100644 Sources/libetpan/include/mime_message_driver.h create mode 100644 Sources/libetpan/include/mmapstring.h create mode 100644 Sources/libetpan/include/mmapstring_private.h create mode 100644 Sources/libetpan/include/namespace.h create mode 100644 Sources/libetpan/include/namespace_parser.h create mode 100644 Sources/libetpan/include/namespace_sender.h create mode 100644 Sources/libetpan/include/namespace_types.h create mode 100644 Sources/libetpan/include/newsfeed.h create mode 100644 Sources/libetpan/include/newsfeed_item.h create mode 100644 Sources/libetpan/include/newsfeed_item_enclosure.h create mode 100644 Sources/libetpan/include/newsfeed_private.h create mode 100644 Sources/libetpan/include/newsfeed_types.h create mode 100644 Sources/libetpan/include/newsnntp.h create mode 100644 Sources/libetpan/include/newsnntp_socket.h create mode 100644 Sources/libetpan/include/newsnntp_ssl.h create mode 100644 Sources/libetpan/include/newsnntp_types.h create mode 100644 Sources/libetpan/include/nntpdriver.h create mode 100644 Sources/libetpan/include/nntpdriver_cached.h create mode 100644 Sources/libetpan/include/nntpdriver_cached_message.h create mode 100644 Sources/libetpan/include/nntpdriver_message.h create mode 100644 Sources/libetpan/include/nntpdriver_types.h create mode 100644 Sources/libetpan/include/nntpstorage.h create mode 100644 Sources/libetpan/include/parser.h create mode 100644 Sources/libetpan/include/parser_atom03.h create mode 100644 Sources/libetpan/include/parser_atom10.h create mode 100644 Sources/libetpan/include/parser_rdf.h create mode 100644 Sources/libetpan/include/parser_rss20.h create mode 100644 Sources/libetpan/include/pop3driver.h create mode 100644 Sources/libetpan/include/pop3driver_cached.h create mode 100644 Sources/libetpan/include/pop3driver_cached_message.h create mode 100644 Sources/libetpan/include/pop3driver_message.h create mode 100644 Sources/libetpan/include/pop3driver_types.h create mode 100644 Sources/libetpan/include/pop3storage.h create mode 100644 Sources/libetpan/include/qresync.h create mode 100644 Sources/libetpan/include/qresync_private.h create mode 100644 Sources/libetpan/include/qresync_types.h create mode 100644 Sources/libetpan/include/quota.h create mode 100644 Sources/libetpan/include/quota_parser.h create mode 100644 Sources/libetpan/include/quota_sender.h create mode 100644 Sources/libetpan/include/quota_types.h create mode 100644 Sources/libetpan/include/timeutils.h create mode 100644 Sources/libetpan/include/uidplus.h create mode 100644 Sources/libetpan/include/uidplus_parser.h create mode 100644 Sources/libetpan/include/uidplus_sender.h create mode 100644 Sources/libetpan/include/uidplus_types.h create mode 100644 Sources/libetpan/include/xgmlabels.h create mode 100644 Sources/libetpan/include/xgmmsgid.h create mode 100644 Sources/libetpan/include/xgmthrid.h create mode 100644 Sources/libetpan/include/xlist.h create mode 100644 Sources/libetpan/low-level/Makefile.am create mode 100644 Sources/libetpan/low-level/feed/Makefile.am create mode 100644 Sources/libetpan/low-level/feed/date.c create mode 100644 Sources/libetpan/low-level/feed/date.h create mode 100644 Sources/libetpan/low-level/feed/newsfeed.c create mode 100644 Sources/libetpan/low-level/feed/newsfeed.h create mode 100644 Sources/libetpan/low-level/feed/newsfeed_item.c create mode 100644 Sources/libetpan/low-level/feed/newsfeed_item.h create mode 100644 Sources/libetpan/low-level/feed/newsfeed_item_enclosure.c create mode 100644 Sources/libetpan/low-level/feed/newsfeed_item_enclosure.h create mode 100644 Sources/libetpan/low-level/feed/newsfeed_private.c create mode 100644 Sources/libetpan/low-level/feed/newsfeed_private.h create mode 100644 Sources/libetpan/low-level/feed/newsfeed_types.h create mode 100644 Sources/libetpan/low-level/feed/parser.c create mode 100644 Sources/libetpan/low-level/feed/parser.h create mode 100644 Sources/libetpan/low-level/feed/parser_atom03.c create mode 100644 Sources/libetpan/low-level/feed/parser_atom03.h create mode 100644 Sources/libetpan/low-level/feed/parser_atom10.c create mode 100644 Sources/libetpan/low-level/feed/parser_atom10.h create mode 100644 Sources/libetpan/low-level/feed/parser_rdf.c create mode 100644 Sources/libetpan/low-level/feed/parser_rdf.h create mode 100644 Sources/libetpan/low-level/feed/parser_rss20.c create mode 100644 Sources/libetpan/low-level/feed/parser_rss20.h create mode 100644 Sources/libetpan/low-level/imap/Makefile.am create mode 100644 Sources/libetpan/low-level/imap/TODO create mode 100644 Sources/libetpan/low-level/imap/acl.c create mode 100644 Sources/libetpan/low-level/imap/acl.h create mode 100644 Sources/libetpan/low-level/imap/acl_parser.c create mode 100644 Sources/libetpan/low-level/imap/acl_parser.h create mode 100644 Sources/libetpan/low-level/imap/acl_sender.c create mode 100644 Sources/libetpan/low-level/imap/acl_sender.h create mode 100644 Sources/libetpan/low-level/imap/acl_types.c create mode 100644 Sources/libetpan/low-level/imap/acl_types.h create mode 100644 Sources/libetpan/low-level/imap/annotatemore.c create mode 100644 Sources/libetpan/low-level/imap/annotatemore.h create mode 100644 Sources/libetpan/low-level/imap/annotatemore_parser.c create mode 100644 Sources/libetpan/low-level/imap/annotatemore_parser.h create mode 100644 Sources/libetpan/low-level/imap/annotatemore_sender.c create mode 100644 Sources/libetpan/low-level/imap/annotatemore_sender.h create mode 100644 Sources/libetpan/low-level/imap/annotatemore_types.c create mode 100644 Sources/libetpan/low-level/imap/annotatemore_types.h create mode 100644 Sources/libetpan/low-level/imap/clientid.c create mode 100644 Sources/libetpan/low-level/imap/clientid.h create mode 100644 Sources/libetpan/low-level/imap/clientid_sender.c create mode 100644 Sources/libetpan/low-level/imap/clientid_sender.h create mode 100644 Sources/libetpan/low-level/imap/condstore.c create mode 100644 Sources/libetpan/low-level/imap/condstore.h create mode 100644 Sources/libetpan/low-level/imap/condstore_private.h create mode 100644 Sources/libetpan/low-level/imap/condstore_types.c create mode 100644 Sources/libetpan/low-level/imap/condstore_types.h create mode 100644 Sources/libetpan/low-level/imap/enable.c create mode 100644 Sources/libetpan/low-level/imap/enable.h create mode 100644 Sources/libetpan/low-level/imap/idle.c create mode 100644 Sources/libetpan/low-level/imap/idle.h create mode 100644 Sources/libetpan/low-level/imap/mailimap.c create mode 100644 Sources/libetpan/low-level/imap/mailimap.h create mode 100644 Sources/libetpan/low-level/imap/mailimap_compress.c create mode 100644 Sources/libetpan/low-level/imap/mailimap_compress.h create mode 100644 Sources/libetpan/low-level/imap/mailimap_extension.c create mode 100644 Sources/libetpan/low-level/imap/mailimap_extension.h create mode 100644 Sources/libetpan/low-level/imap/mailimap_extension_types.h create mode 100644 Sources/libetpan/low-level/imap/mailimap_helper.c create mode 100644 Sources/libetpan/low-level/imap/mailimap_helper.h create mode 100644 Sources/libetpan/low-level/imap/mailimap_id.c create mode 100644 Sources/libetpan/low-level/imap/mailimap_id.h create mode 100644 Sources/libetpan/low-level/imap/mailimap_id_parser.c create mode 100644 Sources/libetpan/low-level/imap/mailimap_id_parser.h create mode 100644 Sources/libetpan/low-level/imap/mailimap_id_sender.c create mode 100644 Sources/libetpan/low-level/imap/mailimap_id_sender.h create mode 100644 Sources/libetpan/low-level/imap/mailimap_id_types.c create mode 100644 Sources/libetpan/low-level/imap/mailimap_id_types.h create mode 100644 Sources/libetpan/low-level/imap/mailimap_keywords.c create mode 100644 Sources/libetpan/low-level/imap/mailimap_keywords.h create mode 100644 Sources/libetpan/low-level/imap/mailimap_oauth2.c create mode 100644 Sources/libetpan/low-level/imap/mailimap_oauth2.h create mode 100644 Sources/libetpan/low-level/imap/mailimap_parser.c create mode 100644 Sources/libetpan/low-level/imap/mailimap_parser.h create mode 100644 Sources/libetpan/low-level/imap/mailimap_print.c create mode 100644 Sources/libetpan/low-level/imap/mailimap_print.h create mode 100644 Sources/libetpan/low-level/imap/mailimap_sender.c create mode 100644 Sources/libetpan/low-level/imap/mailimap_sender.h create mode 100644 Sources/libetpan/low-level/imap/mailimap_socket.c create mode 100644 Sources/libetpan/low-level/imap/mailimap_socket.h create mode 100644 Sources/libetpan/low-level/imap/mailimap_sort.c create mode 100644 Sources/libetpan/low-level/imap/mailimap_sort.h create mode 100644 Sources/libetpan/low-level/imap/mailimap_sort_types.c create mode 100644 Sources/libetpan/low-level/imap/mailimap_sort_types.h create mode 100644 Sources/libetpan/low-level/imap/mailimap_ssl.c create mode 100644 Sources/libetpan/low-level/imap/mailimap_ssl.h create mode 100644 Sources/libetpan/low-level/imap/mailimap_types.c create mode 100644 Sources/libetpan/low-level/imap/mailimap_types.h create mode 100644 Sources/libetpan/low-level/imap/mailimap_types_helper.c create mode 100644 Sources/libetpan/low-level/imap/mailimap_types_helper.h create mode 100644 Sources/libetpan/low-level/imap/namespace.c create mode 100644 Sources/libetpan/low-level/imap/namespace.h create mode 100644 Sources/libetpan/low-level/imap/namespace_parser.c create mode 100644 Sources/libetpan/low-level/imap/namespace_parser.h create mode 100644 Sources/libetpan/low-level/imap/namespace_sender.c create mode 100644 Sources/libetpan/low-level/imap/namespace_sender.h create mode 100644 Sources/libetpan/low-level/imap/namespace_types.c create mode 100644 Sources/libetpan/low-level/imap/namespace_types.h create mode 100644 Sources/libetpan/low-level/imap/qresync.c create mode 100644 Sources/libetpan/low-level/imap/qresync.h create mode 100644 Sources/libetpan/low-level/imap/qresync_private.h create mode 100644 Sources/libetpan/low-level/imap/qresync_types.c create mode 100644 Sources/libetpan/low-level/imap/qresync_types.h create mode 100644 Sources/libetpan/low-level/imap/quota.c create mode 100644 Sources/libetpan/low-level/imap/quota.h create mode 100644 Sources/libetpan/low-level/imap/quota_parser.c create mode 100644 Sources/libetpan/low-level/imap/quota_parser.h create mode 100644 Sources/libetpan/low-level/imap/quota_sender.c create mode 100644 Sources/libetpan/low-level/imap/quota_sender.h create mode 100644 Sources/libetpan/low-level/imap/quota_types.c create mode 100644 Sources/libetpan/low-level/imap/quota_types.h create mode 100644 Sources/libetpan/low-level/imap/uidplus.c create mode 100644 Sources/libetpan/low-level/imap/uidplus.h create mode 100644 Sources/libetpan/low-level/imap/uidplus_parser.c create mode 100644 Sources/libetpan/low-level/imap/uidplus_parser.h create mode 100644 Sources/libetpan/low-level/imap/uidplus_sender.c create mode 100644 Sources/libetpan/low-level/imap/uidplus_sender.h create mode 100644 Sources/libetpan/low-level/imap/uidplus_types.c create mode 100644 Sources/libetpan/low-level/imap/uidplus_types.h create mode 100644 Sources/libetpan/low-level/imap/xgmlabels.c create mode 100644 Sources/libetpan/low-level/imap/xgmlabels.h create mode 100644 Sources/libetpan/low-level/imap/xgmmsgid.c create mode 100644 Sources/libetpan/low-level/imap/xgmmsgid.h create mode 100644 Sources/libetpan/low-level/imap/xgmthrid.c create mode 100644 Sources/libetpan/low-level/imap/xgmthrid.h create mode 100644 Sources/libetpan/low-level/imap/xlist.c create mode 100644 Sources/libetpan/low-level/imap/xlist.h create mode 100644 Sources/libetpan/low-level/imf/Makefile.am create mode 100644 Sources/libetpan/low-level/imf/TODO create mode 100644 Sources/libetpan/low-level/imf/mailimf.c create mode 100644 Sources/libetpan/low-level/imf/mailimf.h create mode 100644 Sources/libetpan/low-level/imf/mailimf_types.c create mode 100644 Sources/libetpan/low-level/imf/mailimf_types.h create mode 100644 Sources/libetpan/low-level/imf/mailimf_types_helper.c create mode 100644 Sources/libetpan/low-level/imf/mailimf_types_helper.h create mode 100644 Sources/libetpan/low-level/imf/mailimf_write.h create mode 100644 Sources/libetpan/low-level/imf/mailimf_write_file.c create mode 100644 Sources/libetpan/low-level/imf/mailimf_write_file.h create mode 100644 Sources/libetpan/low-level/imf/mailimf_write_generic.c create mode 100644 Sources/libetpan/low-level/imf/mailimf_write_generic.h create mode 100644 Sources/libetpan/low-level/imf/mailimf_write_mem.c create mode 100644 Sources/libetpan/low-level/imf/mailimf_write_mem.h create mode 100644 Sources/libetpan/low-level/maildir/Makefile.am create mode 100644 Sources/libetpan/low-level/maildir/maildir.c create mode 100644 Sources/libetpan/low-level/maildir/maildir.h create mode 100644 Sources/libetpan/low-level/maildir/maildir_types.h create mode 100644 Sources/libetpan/low-level/mbox/Makefile.am create mode 100644 Sources/libetpan/low-level/mbox/TODO create mode 100644 Sources/libetpan/low-level/mbox/mailmbox.c create mode 100644 Sources/libetpan/low-level/mbox/mailmbox.h create mode 100644 Sources/libetpan/low-level/mbox/mailmbox_parse.c create mode 100644 Sources/libetpan/low-level/mbox/mailmbox_parse.h create mode 100644 Sources/libetpan/low-level/mbox/mailmbox_types.c create mode 100644 Sources/libetpan/low-level/mbox/mailmbox_types.h create mode 100644 Sources/libetpan/low-level/mh/Makefile.am create mode 100644 Sources/libetpan/low-level/mh/mailmh.c create mode 100644 Sources/libetpan/low-level/mh/mailmh.h create mode 100644 Sources/libetpan/low-level/mime/Makefile.am create mode 100644 Sources/libetpan/low-level/mime/TODO create mode 100644 Sources/libetpan/low-level/mime/mailmime.c create mode 100644 Sources/libetpan/low-level/mime/mailmime.h create mode 100644 Sources/libetpan/low-level/mime/mailmime_content.c create mode 100644 Sources/libetpan/low-level/mime/mailmime_content.h create mode 100644 Sources/libetpan/low-level/mime/mailmime_decode.c create mode 100644 Sources/libetpan/low-level/mime/mailmime_decode.h create mode 100644 Sources/libetpan/low-level/mime/mailmime_disposition.c create mode 100644 Sources/libetpan/low-level/mime/mailmime_disposition.h create mode 100644 Sources/libetpan/low-level/mime/mailmime_types.c create mode 100644 Sources/libetpan/low-level/mime/mailmime_types.h create mode 100644 Sources/libetpan/low-level/mime/mailmime_types_helper.c create mode 100644 Sources/libetpan/low-level/mime/mailmime_types_helper.h create mode 100644 Sources/libetpan/low-level/mime/mailmime_write.h create mode 100644 Sources/libetpan/low-level/mime/mailmime_write_file.c create mode 100644 Sources/libetpan/low-level/mime/mailmime_write_file.h create mode 100644 Sources/libetpan/low-level/mime/mailmime_write_generic.c create mode 100644 Sources/libetpan/low-level/mime/mailmime_write_generic.h create mode 100644 Sources/libetpan/low-level/mime/mailmime_write_mem.c create mode 100644 Sources/libetpan/low-level/mime/mailmime_write_mem.h create mode 100644 Sources/libetpan/low-level/nntp/Makefile.am create mode 100644 Sources/libetpan/low-level/nntp/newsnntp.c create mode 100644 Sources/libetpan/low-level/nntp/newsnntp.h create mode 100644 Sources/libetpan/low-level/nntp/newsnntp_socket.c create mode 100644 Sources/libetpan/low-level/nntp/newsnntp_socket.h create mode 100644 Sources/libetpan/low-level/nntp/newsnntp_ssl.c create mode 100644 Sources/libetpan/low-level/nntp/newsnntp_ssl.h create mode 100644 Sources/libetpan/low-level/nntp/newsnntp_types.h create mode 100644 Sources/libetpan/low-level/pop3/Makefile.am create mode 100644 Sources/libetpan/low-level/pop3/mailpop3.c create mode 100644 Sources/libetpan/low-level/pop3/mailpop3.h create mode 100644 Sources/libetpan/low-level/pop3/mailpop3_helper.c create mode 100644 Sources/libetpan/low-level/pop3/mailpop3_helper.h create mode 100644 Sources/libetpan/low-level/pop3/mailpop3_socket.c create mode 100644 Sources/libetpan/low-level/pop3/mailpop3_socket.h create mode 100644 Sources/libetpan/low-level/pop3/mailpop3_ssl.c create mode 100644 Sources/libetpan/low-level/pop3/mailpop3_ssl.h create mode 100644 Sources/libetpan/low-level/pop3/mailpop3_types.h create mode 100644 Sources/libetpan/low-level/smtp/Makefile.am create mode 100644 Sources/libetpan/low-level/smtp/TODO create mode 100644 Sources/libetpan/low-level/smtp/mailsmtp.c create mode 100644 Sources/libetpan/low-level/smtp/mailsmtp.h create mode 100644 Sources/libetpan/low-level/smtp/mailsmtp_helper.c create mode 100644 Sources/libetpan/low-level/smtp/mailsmtp_helper.h create mode 100644 Sources/libetpan/low-level/smtp/mailsmtp_oauth2.c create mode 100644 Sources/libetpan/low-level/smtp/mailsmtp_oauth2.h create mode 100644 Sources/libetpan/low-level/smtp/mailsmtp_private.h create mode 100644 Sources/libetpan/low-level/smtp/mailsmtp_socket.c create mode 100644 Sources/libetpan/low-level/smtp/mailsmtp_socket.h create mode 100644 Sources/libetpan/low-level/smtp/mailsmtp_ssl.c create mode 100644 Sources/libetpan/low-level/smtp/mailsmtp_ssl.h create mode 100644 Sources/libetpan/low-level/smtp/mailsmtp_types.h create mode 100644 Sources/libetpan/main/Makefile.am create mode 100644 Sources/libetpan/main/libetpan.h create mode 100644 Sources/libetpan/main/libetpan_version.c create mode 100644 Sources/libetpan/main/libetpan_version.h.in diff --git a/Package.swift b/Package.swift new file mode 100644 index 00000000..21f437d8 --- /dev/null +++ b/Package.swift @@ -0,0 +1,31 @@ +// swift-tools-version:5.0 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "libetpan-swift", + products: [ + // Products define the executables and libraries produced by a package, and make them visible to other packages. + .library( + name: "libetpan", + targets: ["libetpan"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages which this package depends on. + .target( + name: "libetpan", + cSettings: [ + .define("HAVE_CONFIG_H", to: "1"), + .define("HAVE_CFNETWORK", to: "1"), + .define("LIBETPAN_IOS_DISABLE_SSL", to: "1"), + .define("NO_MACROS", to: "1"), + ] + ) + ] +) diff --git a/README.md b/README.md new file mode 100644 index 00000000..c6ed9da7 --- /dev/null +++ b/README.md @@ -0,0 +1,64 @@ +## LibEtPan + +The purpose of this mail library is to provide a portable, efficient framework for different kinds of mail access: IMAP, SMTP, POP and NNTP. + +It provides an API for C language. + +[![Build Status](https://travis-ci.org/dinhviethoa/libetpan.png?branch=master)](https://travis-ci.org/dinhviethoa/libetpan) +[![Code Quality: Cpp](https://img.shields.io/lgtm/grade/cpp/g/dinhviethoa/libetpan.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/dinhviethoa/libetpan/context:cpp) +[![Total Alerts](https://img.shields.io/lgtm/alerts/g/dinhviethoa/libetpan.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/dinhviethoa/libetpan/alerts) + +## Features + +- IMAP +- SMTP +- POP +- NNTP +- RFC822/MIME message builder +- RFC822/MIME message parser +- Maildir +- mbox +- MH + +## Build instructions + +### Unix + +You need to install autoconf, automake and libtool. +They can be installed using [brew](http://brew.sh/). + + $ ./autogen.sh + $ make + +You can use flag --with-poll for using poll() instead of select() for checking connection status + +### How to link with it + + $ gcc -c -o sample.o sample.c `pkg-config libetpan --cflags` + $ gcc -o sample sample.o `pkg-config libetpan --libs` + +### Mac / iOS + +- Download Xcode +- Open `build-mac/libetpan.xcodeproj` +- Choose the correct target "static libetpan" for Mac or "libetpan ios" for iOS. +- Build + +### Setup a Mac project + +- Add `libetpan.xcodeproj` as sub-project +- Link with libetpan.a + +### Setup an iOS project + +- Add `libetpan.xcodeproj` as sub-project +- Link with libetpan-ios.a +- Set "Other Linker Flags": `-lsasl2` + +### Build on Windows + +- See README and Visual Studio Solution in build-windows folder + +## More information + +See http://etpan.org/libetpan.html for more information and examples. diff --git a/Sources/libetpan/data-types/Makefile.am b/Sources/libetpan/data-types/Makefile.am new file mode 100644 index 00000000..d2f00301 --- /dev/null +++ b/Sources/libetpan/data-types/Makefile.am @@ -0,0 +1,55 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +etpaninclude_HEADERS = \ + mmapstring.h mailstream.h mailstream_helper.h mail.h \ + mailstream_low.h \ + mailstream_socket.h mailstream_ssl.h mailstream_cfstream.h \ + mailstream_compress.h \ + mailstream_types.h \ + carray.h clist.h chash.h \ + charconv.h mailsem.h maillock.h + +AM_CPPFLAGS = -I$(top_builddir)/include + +noinst_LTLIBRARIES = libdata-types.la + +libdata_types_la_SOURCES = connect.h connect.c base64.h hmac-md5.h \ + md5global.h md5namespace.h md5.h md5.c mmapstring.c mailstream_helper.c \ + mailstream_low.c mailstream.c mailstream_socket.c \ + mailstream_ssl.c carray.c clist.c chash.c \ + charconv.c maillock.c base64.c mail_cache_db_types.h \ + mail_cache_db.h mail_cache_db.c mail_cache_lmdb.c mailsem.c mailsasl.h \ + mailsasl.c mailstream_cancel_types.h mailstream_cancel.h \ + mailstream_cancel.c timeutils.h timeutils.c \ + mmapstring_private.h mailstream_ssl_private.h \ + mailstream_cfstream.c mailstream_cfstream.h \ + mailstream_compress.c mailstream_compress.h diff --git a/Sources/libetpan/data-types/base64.c b/Sources/libetpan/data-types/base64.c new file mode 100644 index 00000000..14903ddd --- /dev/null +++ b/Sources/libetpan/data-types/base64.c @@ -0,0 +1,148 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - Juergen Graf + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: base64.c,v 1.3 2005/06/01 12:21:57 smarinier Exp $ + */ + +#include "base64.h" + +#include + +#define OUTPUT_SIZE 513 +#define CHAR64(c) (((c) < 0 || (c) > 127) ? -1 : index_64[(c)]) + +static char index_64[128] = { + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, + 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, + 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, + -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, + 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 +}; + +static char basis_64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +LIBETPAN_EXPORT +char * encode_base64(const char * in, int len) +{ + char * output, * tmp; + unsigned char oval; + int out_len; + const unsigned char * uin = (const unsigned char *) in; + + out_len = ((len + 2) / 3 * 4) + 1; + + if ((len > 0) && (in == NULL)) + return NULL; + + output = malloc(out_len); + if (!output) + return NULL; + + tmp = output; + while (len >= 3) { + *tmp++ = basis_64[uin[0] >> 2]; + *tmp++ = basis_64[((uin[0] << 4) & 0x30) | (uin[1] >> 4)]; + *tmp++ = basis_64[((uin[1] << 2) & 0x3c) | (uin[2] >> 6)]; + *tmp++ = basis_64[uin[2] & 0x3f]; + uin += 3; + len -= 3; + } + if (len > 0) { + *tmp++ = basis_64[uin[0] >> 2]; + oval = (uin[0] << 4) & 0x30; + if (len > 1) oval |= uin[1] >> 4; + *tmp++ = basis_64[oval]; + *tmp++ = (len < 2) ? '=' : basis_64[(uin[1] << 2) & 0x3c]; + *tmp++ = '='; + } + + *tmp = '\0'; + + return output; +} + +LIBETPAN_EXPORT +char * decode_base64(const char * in, int len) +{ + char * output, * out; + int i, c1, c2, c3, c4, out_len; + + out_len = 0; + + output = malloc(OUTPUT_SIZE); + if (output == NULL) + return NULL; + out = output; + + if (in[0] == '+' && in[1] == ' ') + in += 2; + + for (i = 0; i < (len / 4); i++) { + c1 = in[0]; + c2 = in[1]; + c3 = in[2]; + c4 = in[3]; + if (CHAR64(c1) == -1 || CHAR64(c2) == -1 || + (c3 != '=' && CHAR64(c3) == -1) || + (c4 != '=' && CHAR64(c4) == -1)) { + free(out); + return NULL; + } + + in += 4; + *output++ = (CHAR64(c1) << 2) | (CHAR64(c2) >> 4); + if (++out_len >= OUTPUT_SIZE) + return NULL; + + if (c3 != '=') { + *output++ = ((CHAR64(c2) << 4) & 0xf0) | (CHAR64(c3) >> 2); + if (++out_len >= OUTPUT_SIZE) + return NULL; + + if (c4 != '=') { + *output++ = ((CHAR64(c3) << 6) & 0xc0) | CHAR64(c4); + if (++out_len >= OUTPUT_SIZE) + return NULL; + } + } + } + + *output = 0; + + return out; +} + + diff --git a/Sources/libetpan/data-types/base64.h b/Sources/libetpan/data-types/base64.h new file mode 100644 index 00000000..61461773 --- /dev/null +++ b/Sources/libetpan/data-types/base64.h @@ -0,0 +1,65 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - Juergen Graf + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: base64.h,v 1.3 2005/06/01 12:21:57 smarinier Exp $ + */ + +#ifndef BASE64_H +#define BASE64_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef LIBETPAN_CONFIG_H +# include "libetpan-config.h" +#endif + +/** + * creates (malloc) a new base64 encoded string from a standard 8bit string + * don't forget to free it when time comes ;) + */ +LIBETPAN_EXPORT +char * encode_base64(const char * in, int len); + +/** + * creates (malloc) a new standard 8bit string from an base64 encoded string + * don't forget to free it when time comes ;) + */ +LIBETPAN_EXPORT +char * decode_base64(const char * in, int len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/data-types/carray.c b/Sources/libetpan/data-types/carray.c new file mode 100644 index 00000000..0c9e2470 --- /dev/null +++ b/Sources/libetpan/data-types/carray.c @@ -0,0 +1,162 @@ +/* + * libEtPan! -- a mail stuff library + * + * carray - Implements simple dynamic pointer arrays + * + * Copyright (c) 1999-2005, Gaël Roualland + * interface changes - 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: carray.c,v 1.11 2008/02/20 22:15:50 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include "carray.h" + +#define MIN_ARRAY_SIZE 4 + +LIBETPAN_EXPORT +carray * carray_new(unsigned int initsize) { + carray * array; + + array = (carray *) malloc(sizeof(carray)); + if (!array) return NULL; + + if (initsize < MIN_ARRAY_SIZE) + initsize = MIN_ARRAY_SIZE; + + array->len = 0; + array->max = initsize; + array->array = (void **) malloc(sizeof(void *) * initsize); + if (!array->array) { + free(array); + return NULL; + } + return array; +} + +LIBETPAN_EXPORT +int carray_add(carray * array, void * data, unsigned int * indx) { + int r; + + r = carray_set_size(array, array->len + 1); + if (r < 0) + return r; + + array->array[array->len - 1] = data; + if (indx != NULL) + * indx = array->len - 1; + + return 0; +} + +LIBETPAN_EXPORT +int carray_set_size(carray * array, unsigned int new_size) +{ + if (new_size > array->max) { + unsigned int n = array->max * 2; + void * new; + + while (n <= new_size) + n *= 2; + + new = (void **) realloc(array->array, sizeof(void *) * n); + if (!new) + return -1; + array->array = new; + array->max = n; + } + array->len = new_size; + + return 0; +} + +LIBETPAN_EXPORT +int carray_delete_fast(carray * array, unsigned int indx) { + if (indx >= array->len) + return -1; + + array->array[indx] = NULL; + + return 0; +} + +LIBETPAN_EXPORT +int carray_delete(carray * array, unsigned int indx) { + if (indx >= array->len) + return -1; + + if (indx != --array->len) + array->array[indx] = array->array[array->len]; + return 0; +} + +LIBETPAN_EXPORT +int carray_delete_slow(carray * array, unsigned int indx) { + if (indx >= array->len) + return -1; + + if (indx != --array->len) + memmove(array->array + indx, array->array + indx + 1, + (array->len - indx) * sizeof(void *)); + return 0; +} + +#ifdef NO_MACROS +LIBETPAN_EXPORT +void ** carray_data(carray * array) { + return array->array; +} + +LIBETPAN_EXPORT +unsigned int carray_count(carray * array) { + return array->len; +} + +LIBETPAN_EXPORT +void * carray_get(carray * array, unsigned int indx) { + return array->array[indx]; +} + +LIBETPAN_EXPORT +void carray_set(carray * array, unsigned int indx, void * value) { + array->array[indx] = value; +} +#endif + +LIBETPAN_EXPORT +void carray_free(carray * array) { + free(array->array); + free(array); +} diff --git a/Sources/libetpan/data-types/carray.h b/Sources/libetpan/data-types/carray.h new file mode 100644 index 00000000..dd2ff65d --- /dev/null +++ b/Sources/libetpan/data-types/carray.h @@ -0,0 +1,149 @@ +/* + * libEtPan! -- a mail stuff library + * + * carray - Implements simple dynamic pointer arrays + * + * Copyright (c) 1999-2005, Gaël Roualland + * interface changes - 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: carray.h,v 1.18 2010/11/16 20:46:35 hoa Exp $ + */ + +#ifndef CARRAY_H +#define CARRAY_H + +#ifndef LIBETPAN_CONFIG_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +struct carray_s { + void ** array; + unsigned int len; + unsigned int max; +}; + +typedef struct carray_s carray; + +/* Creates a new array of pointers, with initsize preallocated cells */ +LIBETPAN_EXPORT +carray * carray_new(unsigned int initsize); + +/* Adds the pointer to data in the array. + Returns the index of the pointer in the array or -1 on error */ +LIBETPAN_EXPORT +int carray_add(carray * array, void * data, unsigned int * indx); + +LIBETPAN_EXPORT +int carray_set_size(carray * array, unsigned int new_size); + +/* Removes the cell at this index position. Returns TRUE on success. + Order of elements in the array IS changed. */ +LIBETPAN_EXPORT +int carray_delete(carray * array, unsigned int indx); + +/* Removes the cell at this index position. Returns TRUE on success. + Order of elements in the array IS not changed. */ +LIBETPAN_EXPORT +int carray_delete_slow(carray * array, unsigned int indx); + +/* remove without decreasing the size of the array */ +LIBETPAN_EXPORT +int carray_delete_fast(carray * array, unsigned int indx); + +/* Some of the following routines can be implemented as macros to + be faster. If you don't want it, define NO_MACROS */ +#ifdef NO_MACROS + +/* Returns the array itself */ +LIBETPAN_EXPORT +void ** carray_data(carray *); + +/* Returns the number of elements in the array */ +LIBETPAN_EXPORT +unsigned int carray_count(carray *); + +/* Returns the contents of one cell */ +LIBETPAN_EXPORT +void * carray_get(carray * array, unsigned int indx); + +/* Sets the contents of one cell */ +LIBETPAN_EXPORT +void carray_set(carray * array, unsigned int indx, void * value); + +#else + +#if 0 +#define carray_data(a) (a->array) +#define carray_count(a) (a->len) +#define carray_get(a, indx) (a->array[indx]) +#define carray_set(a, indx, v) do { a->array[indx]=v; } while(0) +#endif + +#ifndef INLINE +#ifdef _MSC_VER +#define INLINE __inline +#else +#define INLINE inline +#endif +#endif + +static INLINE void ** carray_data(carray * array) +{ + return array->array; +} + +static INLINE unsigned int carray_count(carray * array) +{ + return array->len; +} + +static INLINE void * carray_get(carray * array, unsigned int indx) +{ + return array->array[indx]; +} + +static INLINE void carray_set(carray * array, unsigned int indx, void * value) +{ + array->array[indx] = value; +} +#endif + +LIBETPAN_EXPORT +void carray_free(carray * array); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/data-types/charconv.c b/Sources/libetpan/data-types/charconv.c new file mode 100644 index 00000000..161f493f --- /dev/null +++ b/Sources/libetpan/data-types/charconv.c @@ -0,0 +1,348 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: charconv.c,v 1.25 2011/03/29 14:39:55 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "charconv.h" + +#ifdef HAVE_ICONV +#include +#endif +#include +#include +#include +#include + +#include "mmapstring.h" + +int (*extended_charconv)(const char * tocode, const char * fromcode, const char * str, size_t length, + char * result, size_t* result_len) = NULL; + +#ifdef HAVE_ICONV +static size_t mail_iconv (iconv_t cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft, + char **inrepls, char *outrepl) +{ + size_t ret = 0, ret1; + /* XXX - force const to mutable */ + char *ib = (char *) *inbuf; + size_t ibl = *inbytesleft; + char *ob = *outbuf; + size_t obl = *outbytesleft; + + for (;;) + { +#ifdef HAVE_ICONV_PROTO_CONST + ret1 = iconv (cd, (const char **) &ib, &ibl, &ob, &obl); +#else + ret1 = iconv (cd, &ib, &ibl, &ob, &obl); +#endif + if (ret1 != (size_t)-1) + ret += ret1; + if (ibl && obl && errno == EILSEQ) + { + if (inrepls) + { + /* Try replacing the input */ + char **t; + for (t = inrepls; *t; t++) + { + char *ib1 = *t; + size_t ibl1 = strlen (*t); + char *ob1 = ob; + size_t obl1 = obl; +#ifdef HAVE_ICONV_PROTO_CONST + iconv (cd, (const char **) &ib1, &ibl1, &ob1, &obl1); +#else + iconv (cd, &ib1, &ibl1, &ob1, &obl1); +#endif + if (!ibl1) + { + ++ib, --ibl; + ob = ob1, obl = obl1; + ++ret; + break; + } + } + if (*t) + continue; + } + if (outrepl) + { + /* Try replacing the output */ + size_t n = strlen (outrepl); + if (n <= obl) + { + memcpy (ob, outrepl, n); + ++ib, --ibl; + ob += n, obl -= n; + ++ret; + continue; + } + } + } + *inbuf = ib, *inbytesleft = ibl; + *outbuf = ob, *outbytesleft = obl; + return ret; + } +} +#endif + +static const char * get_valid_charset(const char * fromcode) +{ + if ((strcasecmp(fromcode, "GB2312") == 0) || (strcasecmp(fromcode, "GB_2312-80") == 0)) { + fromcode = "GBK"; + } + else if ((strcasecmp(fromcode, "iso-8859-8-i") == 0) || (strcasecmp(fromcode, "iso_8859-8-i") == 0) || + (strcasecmp(fromcode, "iso8859-8-i") == 0)) { + fromcode = "iso-8859-8"; + } + else if ((strcasecmp(fromcode, "iso-8859-8-e") == 0) || (strcasecmp(fromcode, "iso_8859-8-e") == 0) || + (strcasecmp(fromcode, "iso8859-8-e") == 0)) { + fromcode = "iso-8859-8"; + } + else if (strcasecmp(fromcode, "ks_c_5601-1987") == 0) { + fromcode = "euckr"; + } + else if (strcasecmp(fromcode, "iso-2022-jp") == 0) { + fromcode = "iso-2022-jp-2"; + } + + return fromcode; +} + +LIBETPAN_EXPORT +int charconv(const char * tocode, const char * fromcode, + const char * str, size_t length, + char ** result) +{ +#ifdef HAVE_ICONV + iconv_t conv; + size_t r; + char * pout; + size_t out_size; + size_t old_out_size; + size_t count; +#endif + char * out; + int res; + + fromcode = get_valid_charset(fromcode); + + if (extended_charconv != NULL) { + size_t result_length; + result_length = length * 6; + *result = malloc( length * 6 + 1); + if (*result == NULL) { + res = MAIL_CHARCONV_ERROR_MEMORY; + } else { + res = (*extended_charconv)( tocode, fromcode, str, length, *result, &result_length); + if (res != MAIL_CHARCONV_NO_ERROR) { + free( *result); + } else { + out = realloc( *result, result_length + 1); + if (out != NULL) *result = out; + /* also a cstring, just in case */ + (*result)[result_length] = '\0'; + } + } + if (res != MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET) + return res; + /* else, let's try with iconv, if available */ + } + +#ifndef HAVE_ICONV + return MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET; +#else + + conv = iconv_open(tocode, fromcode); + if (conv == (iconv_t) -1) { + res = MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET; + goto err; + } + + out_size = 6 * length; /* UTF-8 can be encoded up to 6 bytes */ + + out = malloc(out_size + 1); + if (out == NULL) { + res = MAIL_CHARCONV_ERROR_MEMORY; + goto close_iconv; + } + + pout = out; + old_out_size = out_size; + + r = mail_iconv(conv, &str, &length, &pout, &out_size, NULL, "?"); + + if (r == (size_t) -1) { + res = MAIL_CHARCONV_ERROR_CONV; + goto free; + } + + iconv_close(conv); + + * pout = '\0'; + count = old_out_size - out_size; + pout = realloc(out, count + 1); + if (pout != NULL) + out = pout; + + * result = out; + + return MAIL_CHARCONV_NO_ERROR; + + free: + free(out); + close_iconv: + iconv_close(conv); + err: + return res; +#endif +} + +LIBETPAN_EXPORT +int charconv_buffer(const char * tocode, const char * fromcode, + const char * str, size_t length, + char ** result, size_t * result_len) +{ +#ifdef HAVE_ICONV + iconv_t conv; + size_t iconv_r; + int r; + char * out; + char * pout; + size_t out_size; + size_t old_out_size; + size_t count; +#endif + int res; + MMAPString * mmapstr; + + fromcode = get_valid_charset(fromcode); + + if (extended_charconv != NULL) { + size_t result_length; + result_length = length * 6; + mmapstr = mmap_string_sized_new( result_length + 1); + *result_len = 0; + if (mmapstr == NULL) { + res = MAIL_CHARCONV_ERROR_MEMORY; + } else { + res = (*extended_charconv)( tocode, fromcode, str, length, mmapstr->str, &result_length); + if (res != MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET) { + if (res == MAIL_CHARCONV_NO_ERROR) { + *result = mmapstr->str; + res = mmap_string_ref(mmapstr); + if (res < 0) { + res = MAIL_CHARCONV_ERROR_MEMORY; + mmap_string_free(mmapstr); + } else { + mmap_string_set_size( mmapstr, result_length); /* can't fail */ + *result_len = result_length; + } + } + else { + mmap_string_free(mmapstr); + } + } + else { + mmap_string_free(mmapstr); + } + return res; + } + /* else, let's try with iconv, if available */ + } + +#ifndef HAVE_ICONV + return MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET; +#else + + conv = iconv_open(tocode, fromcode); + if (conv == (iconv_t) -1) { + res = MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET; + goto err; + } + + out_size = 6 * length; /* UTF-8 can be encoded up to 6 bytes */ + + mmapstr = mmap_string_sized_new(out_size + 1); + if (mmapstr == NULL) { + res = MAIL_CHARCONV_ERROR_MEMORY; + goto err; + } + + out = mmapstr->str; + + pout = out; + old_out_size = out_size; + + iconv_r = mail_iconv(conv, &str, &length, &pout, &out_size, NULL, "?"); + + if (iconv_r == (size_t) -1) { + res = MAIL_CHARCONV_ERROR_CONV; + goto free; + } + + iconv_close(conv); + + * pout = '\0'; + + count = old_out_size - out_size; + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAIL_CHARCONV_ERROR_MEMORY; + goto free; + } + + * result = out; + * result_len = count; + + return MAIL_CHARCONV_NO_ERROR; + + free: + mmap_string_free(mmapstr); + err: + return res; +#endif +} + +LIBETPAN_EXPORT +void charconv_buffer_free(char * str) +{ + mmap_string_unref(str); +} diff --git a/Sources/libetpan/data-types/charconv.h b/Sources/libetpan/data-types/charconv.h new file mode 100644 index 00000000..30d259bf --- /dev/null +++ b/Sources/libetpan/data-types/charconv.h @@ -0,0 +1,84 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: charconv.h,v 1.13 2006/06/16 09:25:23 smarinier Exp $ + */ + +#ifndef CHARCONV_H + +#define CHARCONV_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifndef LIBETPAN_CONFIG_H +#include +#endif + +enum { + MAIL_CHARCONV_NO_ERROR = 0, + MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET, + MAIL_CHARCONV_ERROR_MEMORY, + MAIL_CHARCONV_ERROR_CONV +}; + +/** +* define your own conversion. +* - result is big enough to contain your converted string +* - result_len contain the maximum size available (out value must contain the final converted size) +* - your conversion return an error code based on upper enum values +*/ +LIBETPAN_EXPORT +extern int (*extended_charconv)(const char * tocode, const char * fromcode, const char * str, size_t length, + char * result, size_t* result_len); + +LIBETPAN_EXPORT +int charconv(const char * tocode, const char * fromcode, + const char * str, size_t length, + char ** result); + +LIBETPAN_EXPORT +int charconv_buffer(const char * tocode, const char * fromcode, + const char * str, size_t length, + char ** result, size_t * result_len); + +LIBETPAN_EXPORT +void charconv_buffer_free(char * str); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/data-types/chash.c b/Sources/libetpan/data-types/chash.c new file mode 100644 index 00000000..86f89972 --- /dev/null +++ b/Sources/libetpan/data-types/chash.c @@ -0,0 +1,414 @@ +/* + * libEtPan! -- a mail stuff library + * + * chash - Implements generic hash tables. + * + * Copyright (c) 1999-2005, Gaël Roualland + * interface changes - 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: chash.c,v 1.16 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include "chash.h" + +/* This defines the maximum (average) number of entries per bucket. + The hash is resized everytime inserting an entry makes the + average go over that value. */ +#define CHASH_MAXDEPTH 3 + +static inline unsigned int chash_func(const char * key, unsigned int len) { +#if 0 + register unsigned int c = 0, t; + register const char * k = key; + + while (len--) { + c += (c << 4) + *k++; + if ((t = c & 0xF0000000)) { + c ^= t >> 24; + c ^= t; + } + } + return c; +#endif + register unsigned int c = 5381; + register const char * k = key; + + while (len--) { + c = ((c << 5) + c) + *k++; + } + + return c; +} + +static inline char * chash_dup(const void * data, unsigned int len) +{ + void * r; + + r = (char *) malloc(len); + if (!r) + return NULL; + memcpy(r, data, len); + return r; +} + +LIBETPAN_EXPORT +chash * chash_new(unsigned int size, int flags) +{ + chash * h; + + h = (chash *) malloc(sizeof(chash)); + if (h == NULL) + return NULL; + + if (size < CHASH_DEFAULTSIZE) + size = CHASH_DEFAULTSIZE; + + h->count = 0; + h->cells = (struct chashcell **) calloc(size, sizeof(struct chashcell *)); + if (h->cells == NULL) { + free(h); + return NULL; + } + h->size = size; + h->copykey = flags & CHASH_COPYKEY; + h->copyvalue = flags & CHASH_COPYVALUE; + + return h; +} + +LIBETPAN_EXPORT +int chash_get(chash * hash, + chashdatum * key, chashdatum * result) +{ + unsigned int func; + chashiter * iter; + + func = chash_func(key->data, key->len); + + /* look for the key in existing cells */ + iter = hash->cells[func % hash->size]; + while (iter) { + if (iter->key.len == key->len && iter->func == func + && !memcmp(iter->key.data, key->data, key->len)) { + * result = iter->value; /* found */ + + return 0; + } + iter = iter->next; + } + + return -1; +} + +LIBETPAN_EXPORT +int chash_set(chash * hash, + chashdatum * key, + chashdatum * value, + chashdatum * oldvalue) +{ + unsigned int func, indx; + chashiter * iter, * cell; + int r; + + if (hash->count > hash->size * CHASH_MAXDEPTH) { + r = chash_resize(hash, (hash->count / CHASH_MAXDEPTH) * 2 + 1); + if (r < 0) + goto err; + } + + func = chash_func(key->data, key->len); + indx = func % hash->size; + + /* look for the key in existing cells */ + iter = hash->cells[indx]; + while (iter) { + if (iter->key.len == key->len && iter->func == func + && !memcmp(iter->key.data, key->data, key->len)) { + /* found, replacing entry */ + if (hash->copyvalue) { + char * data; + + data = chash_dup(value->data, value->len); + if (data == NULL) + goto err; + + free(iter->value.data); + iter->value.data = data; + iter->value.len = value->len; + } else { + if (oldvalue != NULL) { + oldvalue->data = iter->value.data; + oldvalue->len = iter->value.len; + } + iter->value.data = value->data; + iter->value.len = value->len; + } + if (!hash->copykey) + iter->key.data = key->data; + + if (oldvalue != NULL) { + oldvalue->data = value->data; + oldvalue->len = value->len; + } + + return 0; + } + iter = iter->next; + } + + if (oldvalue != NULL) { + oldvalue->data = NULL; + oldvalue->len = 0; + } + + /* not found, adding entry */ + cell = (struct chashcell *) malloc(sizeof(struct chashcell)); + if (cell == NULL) + goto err; + + if (hash->copykey) { + cell->key.data = chash_dup(key->data, key->len); + if (cell->key.data == NULL) + goto free; + } + else + cell->key.data = key->data; + + cell->key.len = key->len; + if (hash->copyvalue) { + cell->value.data = chash_dup(value->data, value->len); + if (cell->value.data == NULL) + goto free_key_data; + } + else + cell->value.data = value->data; + + cell->value.len = value->len; + cell->func = func; + cell->next = hash->cells[indx]; + hash->cells[indx] = cell; + hash->count++; + + return 0; + + free_key_data: + if (hash->copykey) + free(cell->key.data); + free: + free(cell); + err: + return -1; +} + +LIBETPAN_EXPORT +int chash_delete(chash * hash, chashdatum * key, chashdatum * oldvalue) +{ + /* chashdatum result = { NULL, TRUE }; */ + unsigned int func, indx; + chashiter * iter, * old; + + /* + if (!keylen) + keylen = strlen(key) + 1; + */ + + func = chash_func(key->data, key->len); + indx = func % hash->size; + + /* look for the key in existing cells */ + old = NULL; + iter = hash->cells[indx]; + while (iter) { + if (iter->key.len == key->len && iter->func == func + && !memcmp(iter->key.data, key->data, key->len)) { + /* found, deleting */ + if (old) + old->next = iter->next; + else + hash->cells[indx] = iter->next; + if (hash->copykey) + free(iter->key.data); + if (hash->copyvalue) + free(iter->value.data); + else { + if (oldvalue != NULL) { + oldvalue->data = iter->value.data; + oldvalue->len = iter->value.len; + } + } + free(iter); + hash->count--; + return 0; + } + old = iter; + iter = iter->next; + } + + return -1; /* not found */ +} + +LIBETPAN_EXPORT +void chash_free(chash * hash) { + unsigned int indx; + chashiter * iter, * next; + + /* browse the hash table */ + for(indx = 0; indx < hash->size; indx++) { + iter = hash->cells[indx]; + while (iter) { + next = iter->next; + if (hash->copykey) + free(iter->key.data); + if (hash->copyvalue) + free(iter->value.data); + free(iter); + iter = next; + } + } + free(hash->cells); + free(hash); +} + +LIBETPAN_EXPORT +void chash_clear(chash * hash) { + unsigned int indx; + chashiter * iter, * next; + + /* browse the hash table */ + for(indx = 0; indx < hash->size; indx++) { + iter = hash->cells[indx]; + while (iter) { + next = iter->next; + if (hash->copykey) + free(iter->key.data); + if (hash->copyvalue) + free(iter->value.data); + free(iter); + iter = next; + } + } + memset(hash->cells, 0, hash->size * sizeof(* hash->cells)); + hash->count = 0; +} + +LIBETPAN_EXPORT +chashiter * chash_begin(chash * hash) { + chashiter * iter; + unsigned int indx = 0; + + iter = hash->cells[0]; + while(!iter) { + indx++; + if (indx >= hash->size) + return NULL; + iter = hash->cells[indx]; + } + return iter; +} + +LIBETPAN_EXPORT +chashiter * chash_next(chash * hash, chashiter * iter) { + unsigned int indx; + + if (!iter) + return NULL; + + indx = iter->func % hash->size; + iter = iter->next; + + while(!iter) { + indx++; + if (indx >= hash->size) + return NULL; + iter = hash->cells[indx]; + } + return iter; +} + +LIBETPAN_EXPORT +int chash_resize(chash * hash, unsigned int size) +{ + struct chashcell ** cells; + unsigned int indx, nindx; + chashiter * iter, * next; + + if (hash->size == size) + return 0; + + cells = (struct chashcell **) calloc(size, sizeof(struct chashcell *)); + if (!cells) + return -1; + + /* browse initial hash and copy items in second hash */ + for(indx = 0; indx < hash->size; indx++) { + iter = hash->cells[indx]; + while (iter) { + next = iter->next; + nindx = iter->func % size; + iter->next = cells[nindx]; + cells[nindx] = iter; + iter = next; + } + } + free(hash->cells); + hash->size = size; + hash->cells = cells; + + return 0; +} + +#ifdef NO_MACROS +LIBETPAN_EXPORT +unsigned int chash_count(chash * hash) { + return hash->count; +} + +LIBETPAN_EXPORT +unsigned int chash_size(chash * hash) { + return hash->size; +} + +LIBETPAN_EXPORT +void chash_value(chashiter * iter, chashdatum * result) { + * result = iter->value; +} + +LIBETPAN_EXPORT +void chash_key(chashiter * iter, chashdatum * result) { + * result = iter->key; +} +#endif diff --git a/Sources/libetpan/data-types/chash.h b/Sources/libetpan/data-types/chash.h new file mode 100644 index 00000000..98aa3c67 --- /dev/null +++ b/Sources/libetpan/data-types/chash.h @@ -0,0 +1,191 @@ +/* + * libEtPan! -- a mail stuff library + * + * chash - Implements generic hash tables. + * + * Copyright (c) 1999-2005, Gaël Roualland + * interface changes - 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: chash.h,v 1.16 2010/11/16 20:46:35 hoa Exp $ + */ + +#ifndef CHASH_H +#define CHASH_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef LIBETPAN_CONFIG_H +#include +#endif + +typedef struct { + void * data; + unsigned int len; +} chashdatum; + +struct chash { + unsigned int size; + unsigned int count; + int copyvalue; + int copykey; + struct chashcell ** cells; +}; + +typedef struct chash chash; + +struct chashcell { + unsigned int func; + chashdatum key; + chashdatum value; + struct chashcell * next; +}; + +typedef struct chashcell chashiter; + +#define CHASH_COPYNONE 0 +#define CHASH_COPYKEY 1 +#define CHASH_COPYVALUE 2 +#define CHASH_COPYALL (CHASH_COPYKEY | CHASH_COPYVALUE) + +#define CHASH_DEFAULTSIZE 13 + +/* Allocates a new (empty) hash using this initial size and the given flags, + specifying which data should be copied in the hash. + CHASH_COPYNONE : Keys/Values are not copied. + CHASH_COPYKEY : Keys are dupped and freed as needed in the hash. + CHASH_COPYVALUE : Values are dupped and freed as needed in the hash. + CHASH_COPYALL : Both keys and values are dupped in the hash. + */ +LIBETPAN_EXPORT +chash * chash_new(unsigned int size, int flags); + +/* Frees a hash */ +LIBETPAN_EXPORT +void chash_free(chash * hash); + +/* Removes all elements from a hash */ +LIBETPAN_EXPORT +void chash_clear(chash * hash); + +/* Adds an entry in the hash table. + Length can be 0 if key/value are strings. + If an entry already exists for this key, it is replaced, and its value + is returned. Otherwise, the data pointer will be NULL and the length + field be set to TRUE or FALSe to indicate success or failure. */ +LIBETPAN_EXPORT +int chash_set(chash * hash, + chashdatum * key, + chashdatum * value, + chashdatum * oldvalue); + +/* Retrieves the data associated to the key if it is found in the hash table. + The data pointer and the length will be NULL if not found*/ +LIBETPAN_EXPORT +int chash_get(chash * hash, + chashdatum * key, chashdatum * result); + +/* Removes the entry associated to this key if it is found in the hash table, + and returns its contents if not dupped (otherwise, pointer will be NULL + and len TRUE). If entry is not found both pointer and len will be NULL. */ +LIBETPAN_EXPORT +int chash_delete(chash * hash, + chashdatum * key, + chashdatum * oldvalue); + +/* Resizes the hash table to the passed size. */ +LIBETPAN_EXPORT +int chash_resize(chash * hash, unsigned int size); + +/* Returns an iterator to the first non-empty entry of the hash table */ +LIBETPAN_EXPORT +chashiter * chash_begin(chash * hash); + +/* Returns the next non-empty entry of the hash table */ +LIBETPAN_EXPORT +chashiter * chash_next(chash * hash, chashiter * iter); + +/* Some of the following routines can be implemented as macros to + be faster. If you don't want it, define NO_MACROS */ +#ifdef NO_MACROS +/* Returns the size of the hash table */ +LIBETPAN_EXPORT +unsigned int chash_size(chash * hash); + +/* Returns the number of entries in the hash table */ +LIBETPAN_EXPORT +unsigned int chash_count(chash * hash); + +/* Returns the key part of the entry pointed by the iterator */ +LIBETPAN_EXPORT +void chash_key(chashiter * iter, chashdatum * result); + +/* Returns the value part of the entry pointed by the iterator */ +LIBETPAN_EXPORT +void chash_value(chashiter * iter, chashdatum * result); + +#else + +#ifndef INLINE +#ifdef _MSC_VER +#define INLINE __inline +#else +#define INLINE inline +#endif +#endif + +static INLINE unsigned int chash_size(chash * hash) +{ + return hash->size; +} + +static INLINE unsigned int chash_count(chash * hash) +{ + return hash->count; +} + +static INLINE void chash_key(chashiter * iter, chashdatum * result) +{ + * result = iter->key; +} + +static INLINE void chash_value(chashiter * iter, chashdatum * result) +{ + * result = iter->value; +} + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/data-types/clist.c b/Sources/libetpan/data-types/clist.c new file mode 100644 index 00000000..7fcfbc5f --- /dev/null +++ b/Sources/libetpan/data-types/clist.c @@ -0,0 +1,275 @@ +/* + * libEtPan! -- a mail stuff library + * + * clist - Implements simple generic double-linked pointer lists + * + * Copyright (c) 1999-2005, Gaël Roualland + * interface changes - 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: clist.c,v 1.11 2008/02/20 22:15:50 hoa Exp $ + */ +#define HAVE_CONFIG_H 1 +//#define NO_MACROS 1 + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#ifndef LIBETPAN_CONFIG_H +# include "libetpan-config.h" +#endif + +#include "clist.h" + +clist * clist_new(void) { + clist * lst; + + lst = (clist *) malloc(sizeof(clist)); + if (!lst) return NULL; + + lst->first = lst->last = NULL; + lst->count = 0; + + return lst; +} + +void clist_free(clist * lst) { + clistcell * l1, * l2; + + l1 = lst->first; + while (l1) { + l2 = l1->next; + free(l1); + l1 = l2; + } + + free(lst); +} + +#ifdef NO_MACROS +int clist_isempty(clist * lst) { + return ((lst->first==lst->last) && (lst->last==NULL)); +} + +clistiter * clist_begin(clist * lst) { + return lst->first; +} + +clistiter * clist_end(clist * lst) { + return lst->last; +} + +clistiter * clist_next(clistiter * iter) { + if (iter) + return iter->next; + else + return NULL; +} + +clistiter * clist_previous(clistiter * iter) { + if (iter) + return iter->previous; + else + return NULL; +} + +void * clist_content(clistiter * iter) { + if (iter) + return iter->data; + else + return NULL; +} + +int clist_count(clist * lst) { + return lst->count; +} + +int clist_prepend(clist * lst, void * data) { + return clist_insert_before(lst, lst->first, data); +} + +int clist_append(clist * lst, void * data) { + return clist_insert_after(lst, lst->last, data); +} +#endif + +int clist_insert_before(clist * lst, clistiter * iter, void * data) { + clistcell * c; + + c = (clistcell *) malloc(sizeof(clistcell)); + if (!c) return -1; + + c->data = data; + lst->count++; + + if (clist_isempty(lst)) { + c->previous = c->next = NULL; + lst->first = lst->last = c; + return 0; + } + + if (!iter) { + c->previous = lst->last; + c->previous->next = c; + c->next = NULL; + lst->last = c; + return 0; + } + + c->previous = iter->previous; + c->next = iter; + c->next->previous = c; + if (c->previous) + c->previous->next = c; + else + lst->first = c; + + return 0; +} + +int clist_insert_after(clist * lst, clistiter * iter, void * data) { + clistcell * c; + + c = (clistcell *) malloc(sizeof(clistcell)); + if (!c) return -1; + + c->data = data; + lst->count++; + + if (clist_isempty(lst)) { + c->previous = c->next = NULL; + lst->first = lst->last = c; + return 0; + } + + if (!iter) { + c->previous = lst->last; + c->previous->next = c; + c->next = NULL; + lst->last = c; + return 0; + } + + c->previous = iter; + c->next = iter->next; + if (c->next) + c->next->previous = c; + else + lst->last = c; + c->previous->next = c; + + return 0; +} + +clistiter * clist_delete(clist * lst, clistiter * iter) { + clistiter * ret; + + if (!iter) return NULL; + + if (iter->previous) + iter->previous->next = iter->next; + else + lst->first = iter->next; + + if (iter->next) { + iter->next->previous = iter->previous; + ret = iter->next; + } else { + lst->last = iter->previous; + ret = NULL; + } + + free(iter); + lst->count--; + + return ret; +} + + + +void clist_foreach(clist * lst, clist_func func, void * data) +{ + clistiter * cur; + + for(cur = clist_begin(lst) ; cur != NULL ; cur = cur->next) + func(cur->data, data); +} + +void clist_concat(clist * dest, clist * src) +{ + if (src->first == NULL) { + /* do nothing */ + } + else if (dest->last == NULL) { + dest->first = src->first; + dest->last = src->last; + } + else { + dest->last->next = src->first; + src->first->previous = dest->last; + dest->last = src->last; + } + + dest->count += src->count; + src->last = src->first = NULL; +} + +static inline clistiter * internal_clist_nth(clist * lst, int indx) +{ + clistiter * cur; + + cur = clist_begin(lst); + while ((indx > 0) && (cur != NULL)) { + cur = cur->next; + indx --; + } + + if (cur == NULL) + return NULL; + + return cur; +} + +void * clist_nth_data(clist * lst, int indx) +{ + clistiter * cur; + + cur = internal_clist_nth(lst, indx); + if (cur == NULL) + return NULL; + + return cur->data; +} + +clistiter * clist_nth(clist * lst, int indx) +{ + return internal_clist_nth(lst, indx); +} diff --git a/Sources/libetpan/data-types/clist.h b/Sources/libetpan/data-types/clist.h new file mode 100644 index 00000000..1a80c478 --- /dev/null +++ b/Sources/libetpan/data-types/clist.h @@ -0,0 +1,146 @@ +/* + * libEtPan! -- a mail stuff library + * + * clist - Implements simple generic double-linked pointer lists + * + * Copyright (c) 1999-2005, Gaël Roualland + * interface changes - 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: clist.h,v 1.13 2011/05/09 21:49:46 hoa Exp $ + */ + +#ifndef CLIST_H +#define CLIST_H + +#ifndef LIBETPAN_CONFIG_H +# include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clistcell_s { + void * data; + struct clistcell_s * previous; + struct clistcell_s * next; +} clistcell; + +struct clist_s { + clistcell * first; + clistcell * last; + int count; +}; + +typedef struct clist_s clist; +typedef clistcell clistiter; + +/* Allocate a new pointer list */ +LIBETPAN_EXPORT +clist * clist_new(void); + +/* Destroys a list. Data pointed by data pointers is NOT freed. */ +LIBETPAN_EXPORT +void clist_free(clist *); + +/* Some of the following routines can be implemented as macros to + be faster. If you don't want it, define NO_MACROS */ +#ifdef NO_MACROS + +/* Returns TRUE if list is empty */ +int clist_isempty(clist *); + +/* Returns the number of elements in the list */ +int clist_count(clist *); + +/* Returns an iterator to the first element of the list */ +clistiter * clist_begin(clist *); + +/* Returns an iterator to the last element of the list */ +clistiter * clist_end(clist *); + +/* Returns an iterator to the next element of the list */ +clistiter * clist_next(clistiter *); + +/* Returns an iterator to the previous element of the list */ +clistiter * clist_previous(clistiter *); + +/* Returns the data pointer of this element of the list */ +void* clist_content(clistiter *); + +/* Inserts this data pointer at the beginning of the list */ +int clist_prepend(clist *, void *); + +/* Inserts this data pointer at the end of the list */ +int clist_append(clist *, void *); +#else +#define clist_isempty(lst) (((lst)->first==(lst)->last) && ((lst)->last==NULL)) +#define clist_count(lst) ((lst)->count) +#define clist_begin(lst) ((lst)->first) +#define clist_end(lst) ((lst)->last) +#define clist_next(iter) (iter ? (iter)->next : NULL) +#define clist_previous(iter) (iter ? (iter)->previous : NULL) +#define clist_content(iter) (iter ? (iter)->data : NULL) +#define clist_prepend(lst, data) (clist_insert_before(lst, (lst)->first, data)) +#define clist_append(lst, data) (clist_insert_after(lst, (lst)->last, data)) +#endif + +/* Inserts this data pointer before the element pointed by the iterator */ +LIBETPAN_EXPORT +int clist_insert_before(clist *, clistiter *, void *); + +/* Inserts this data pointer after the element pointed by the iterator */ +LIBETPAN_EXPORT +int clist_insert_after(clist *, clistiter *, void *); + +/* Deletes the element pointed by the iterator. + Returns an iterator to the next element. */ +LIBETPAN_EXPORT +clistiter * clist_delete(clist *, clistiter *); + +typedef void (* clist_func)(void *, void *); + +LIBETPAN_EXPORT +void clist_foreach(clist * lst, clist_func func, void * data); + +LIBETPAN_EXPORT +void clist_concat(clist * dest, clist * src); + +LIBETPAN_EXPORT +void * clist_nth_data(clist * lst, int indx); + +LIBETPAN_EXPORT +clistiter * clist_nth(clist * lst, int indx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/data-types/connect.c b/Sources/libetpan/data-types/connect.c new file mode 100644 index 00000000..e17a5e03 --- /dev/null +++ b/Sources/libetpan/data-types/connect.c @@ -0,0 +1,383 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: connect.c,v 1.29 2011/02/27 01:11:50 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "connect.h" + +#include "mailstream.h" + +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include + +#ifdef WIN32 +# include "win_etpan.h" +#else +# include +# include +# include +# ifdef HAVE_SYS_POLL_H +# include +# endif +# include +# include +#endif + +uint16_t mail_get_service_port(const char * name, char * protocol) +{ + struct servent * service; + + service = getservbyname(name, protocol); + + if (service == NULL) + return 0; + + return ntohs(service->s_port); +} + +static int prepare_fd(int fd) +{ +#ifndef WIN32 + int fd_flags; + int r; + + fd_flags = fcntl(fd, F_GETFL, 0); + fd_flags |= O_NDELAY; + r = fcntl(fd, F_SETFL, fd_flags); + if (r < 0) + return -1; +#endif + + return 0; +} + +#ifdef HAVE_IPV6 +static int verify_sock_errors(int s) +{ + socklen_t len; + int val; + len = sizeof(val); + if (getsockopt(s, SOL_SOCKET, SO_ERROR, &val, &len) < 0) { + return -1; + } else if (val != 0) { + return -1; + } + return 0; +} +#endif + +static int wait_connect(int s, int r, time_t timeout_seconds) +{ +#if defined(WIN32) || !USE_POLL + fd_set fds; +#else + struct pollfd pfd; +#endif // WIN32 + struct timeval timeout; + + if (r == 0) { + /* connected immediately */ + return 0; + } + else if (r == -1) { + if (errno == EINPROGRESS) { + /* select */ + } + else { + return -1; + } + } + + if (timeout_seconds == 0) { + timeout = mailstream_network_delay; + } + else { + timeout.tv_sec = timeout_seconds; + timeout.tv_usec = 0; + } + +#if defined(WIN32) || !USE_POLL + FD_ZERO(&fds); + FD_SET(s, &fds); + /* TODO: how to cancel this ? -> could be cancelled using a cancel fd */ + r = select(s + 1, NULL, &fds, NULL, &timeout); + if (r <= 0) { + return -1; + } + + if (!FD_ISSET(s, &fds)) { + /* though, it's strange */ + return -1; + } +#else + pfd.fd = s; + pfd.events = POLLOUT; + pfd.revents = 0; + + r = poll(&pfd, 1, timeout.tv_sec * 1000 + timeout.tv_usec / 1000); + if (r <= 0) { + return -1; + } + + if (pfd.revents & POLLOUT != POLLOUT) { + return -1; + } +#endif + + return 0; +} + +int mail_tcp_connect(const char * server, uint16_t port) +{ + return mail_tcp_connect_with_local_address(server, port, NULL, 0); +} + +int mail_tcp_connect_timeout(const char * server, uint16_t port, time_t timeout) +{ + return mail_tcp_connect_with_local_address_timeout(server, port, NULL, 0, timeout); +} + +int mail_tcp_connect_with_local_address(const char * server, uint16_t port, + const char * local_address, uint16_t local_port) +{ + return mail_tcp_connect_with_local_address_timeout(server, port, local_address, local_port, 0); +} + +#ifndef WIN32 +#include +int mail_unix_connect_socket(const char *path) +{ + struct sockaddr_un sa; + int s; + + if (sizeof(sa.sun_path) <= strlen(path)) { + return -1; + } + + if (!(memcpy(sa.sun_path, path, strlen(path)+1))) { + return -1; + } + sa.sun_family = AF_UNIX; + + + if (0 > (s = socket(AF_UNIX, SOCK_STREAM, 0))) + return -1; + + if (prepare_fd(s)) + goto close_socket; + if (connect(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_un))) + goto close_socket; + return s; + +close_socket: + close(s); + return -1; +} +#endif + +int mail_tcp_connect_with_local_address_timeout(const char * server, uint16_t port, + const char * local_address, uint16_t local_port, time_t timeout) +{ +#ifndef HAVE_IPV6 + struct hostent * remotehost; + struct sockaddr_in sa; +#else /* HAVE_IPV6 */ + struct addrinfo hints, *res, *ai; + struct addrinfo la_hints; + char port_str[6]; +#endif +#ifdef WIN32 + SOCKET s; + long r; +#else + int s; + int r; + + if ('/' == server[0]) + return mail_unix_connect_socket(server); +#endif + +#ifndef HAVE_IPV6 + s = socket(PF_INET, SOCK_STREAM, 0); + if (s == -1) + goto err; + + if ((local_address != NULL) || (local_port != 0)) { + struct sockaddr_in la; + + la.sin_family = AF_INET; + la.sin_port = htons(local_port); + if (local_address == NULL) { + la.sin_addr.s_addr = htonl(INADDR_ANY); + } + r = inet_aton(local_address, &la.sin_addr); + if (r == 0) + goto close_socket; + r = bind(s, (struct sockaddr *) &la, sizeof(struct sockaddr_in)); + if (r == -1) + goto close_socket; + } + + remotehost = gethostbyname(server); + if (remotehost == NULL) + goto close_socket; + + sa.sin_family = AF_INET; + sa.sin_port = htons(port); + memcpy(&sa.sin_addr, remotehost->h_addr, remotehost->h_length); + + r = prepare_fd(s); + if (r == -1) { + goto close_socket; + } + + r = connect(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)); + r = wait_connect(s, r, timeout); + if (r == -1) { + goto close_socket; + } +#else /* HAVE_IPV6 */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + memset(&la_hints, 0, sizeof(la_hints)); + la_hints.ai_family = AF_UNSPEC; + la_hints.ai_socktype = SOCK_STREAM; + la_hints.ai_flags = AI_PASSIVE; + + /* convert port from integer to string. */ + snprintf(port_str, sizeof(port_str), "%d", port); + + res = NULL; + if (getaddrinfo(server, port_str, &hints, &res) != 0) + goto err; + + s = -1; + for (ai = res; ai != NULL; ai = ai->ai_next) { + s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + + if (s == -1) + continue; + + // Christopher Lyon Anderson - prevent SigPipe +#ifdef SO_NOSIGPIPE + int kOne = 1; + int err = setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, &kOne, sizeof(kOne)); + if (err != 0) + continue; +#endif + + if ((local_address != NULL) || (local_port != 0)) { + char local_port_str[6]; + char * p_local_port_str; + struct addrinfo * la_res; + + if (local_port != 0) { + snprintf(local_port_str, sizeof(local_port_str), "%d", local_port); + p_local_port_str = local_port_str; + } + else { + p_local_port_str = NULL; + } + la_res = NULL; + r = getaddrinfo(local_address, p_local_port_str, &la_hints, &la_res); + if (r != 0) + goto close_socket; + r = bind(s, (struct sockaddr *) la_res->ai_addr, la_res->ai_addrlen); + if (la_res != NULL) + freeaddrinfo(la_res); + if (r == -1) + goto close_socket; + } + + r = prepare_fd(s); + if (r == -1) { + goto close_socket; + } + + r = connect(s, ai->ai_addr, ai->ai_addrlen); + r = wait_connect(s, r, timeout); + + if (r != -1) { + r = verify_sock_errors(s); + } + + if (r == -1) { + if (ai->ai_next) { +#ifdef WIN32 + closesocket(s); +#else + close(s); +#endif + continue; + } else { + goto close_socket; + } + } + /* if we're here, we're good */ + break; + } + + if (res != NULL) + freeaddrinfo(res); + + if (ai == NULL) + goto err; +#endif + return s; + + close_socket: +#ifdef HAVE_IPV6 + if (res != NULL) + freeaddrinfo(res); +#endif +#ifdef WIN32 + closesocket(s); +#else + close(s); +#endif + err: + return -1; +} diff --git a/Sources/libetpan/data-types/connect.h b/Sources/libetpan/data-types/connect.h new file mode 100644 index 00000000..43f8f923 --- /dev/null +++ b/Sources/libetpan/data-types/connect.h @@ -0,0 +1,62 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: connect.h,v 1.16 2007/06/30 12:58:21 hoa Exp $ + */ + +#ifndef CONNECT_H + +#define CONNECT_H + +#ifdef HAVE_INTTYPES_H +# include +#endif +#include + +#ifdef __cplusplus +extern "C" { +#endif + +uint16_t mail_get_service_port(const char * name, char * protocol); +int mail_tcp_connect(const char * server, uint16_t port); +int mail_tcp_connect_timeout(const char * server, uint16_t port, time_t timeout); +int mail_tcp_connect_with_local_address(const char * server, uint16_t port, + const char * local_address, uint16_t local_port); +int mail_tcp_connect_with_local_address_timeout(const char * server, uint16_t port, + const char * local_address, uint16_t local_port, time_t timeout); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Sources/libetpan/data-types/hmac-md5.h b/Sources/libetpan/data-types/hmac-md5.h new file mode 100644 index 00000000..74f106e8 --- /dev/null +++ b/Sources/libetpan/data-types/hmac-md5.h @@ -0,0 +1,94 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* hmac-md5.h -- HMAC_MD5 functions + */ + +/* + * $Id: hmac-md5.h,v 1.4 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef HMAC_MD5_H +#define HMAC_MD5_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#define HMAC_MD5_SIZE 16 + +/* intermediate MD5 context */ +typedef struct HMAC_MD5_CTX_s { + MD5_CTX ictx, octx; +} HMAC_MD5_CTX; + +/* intermediate HMAC state + * values stored in network byte order (Big Endian) + */ +typedef struct HMAC_MD5_STATE_s { + UINT4 istate[4]; + UINT4 ostate[4]; +} HMAC_MD5_STATE; + +/* One step hmac computation + * + * digest may be same as text or key + */ +void hmac_md5(const unsigned char *text, int text_len, + const unsigned char *key, int key_len, + unsigned char digest[HMAC_MD5_SIZE]); + +/* create context from key + */ +void hmac_md5_init(HMAC_MD5_CTX *hmac, + const unsigned char *key, int key_len); + +/* precalculate intermediate state from key + */ +void hmac_md5_precalc(HMAC_MD5_STATE *hmac, + const unsigned char *key, int key_len); + +/* initialize context from intermediate state + */ +void hmac_md5_import(HMAC_MD5_CTX *hmac, HMAC_MD5_STATE *state); + +#define hmac_md5_update(hmac, text, text_len) MD5Update(&(hmac)->ictx, (text), (text_len)) + +/* finish hmac from intermediate result. Intermediate result is zeroed. + */ +void hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE], + HMAC_MD5_CTX *hmac); + +#ifdef __cplusplus +} +#endif + +#endif /* HMAC_MD5_H */ diff --git a/Sources/libetpan/data-types/mail.h b/Sources/libetpan/data-types/mail.h new file mode 100644 index 00000000..ed4f5b0a --- /dev/null +++ b/Sources/libetpan/data-types/mail.h @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mail.h,v 1.8 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef MAIL_H + +#define MAIL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/data-types/mail_cache_db.c b/Sources/libetpan/data-types/mail_cache_db.c new file mode 100644 index 00000000..98badfe2 --- /dev/null +++ b/Sources/libetpan/data-types/mail_cache_db.c @@ -0,0 +1,504 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mail_cache_db.c,v 1.20 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifndef LMDB + +#include "mail_cache_db.h" + +#include +#include +#include +#include +#include + +#include "libetpan-config.h" + +#include "maillock.h" + +#if DBVERS >= 1 +#include +#endif + +#if DBVERS >= 1 +static struct mail_cache_db * mail_cache_db_new(DB * db) +{ + struct mail_cache_db * cache_db; + + cache_db = malloc(sizeof(* cache_db)); + if (cache_db == NULL) + return NULL; + cache_db->internal_database = db; + + return cache_db; +} + +static void mail_cache_db_free(struct mail_cache_db * cache_db) +{ + free(cache_db); +} +#endif + +int mail_cache_db_open(const char * filename, + struct mail_cache_db ** pcache_db) +{ +#if DBVERS >= 1 + DB * dbp; +#if DBVERS > 1 + int r; +#endif + struct mail_cache_db * cache_db; + +#if DB_VERSION_MAJOR >= 3 + r = db_create(&dbp, NULL, 0); + if (r != 0) + goto err; + +#if (DB_VERSION_MAJOR >= 4) && ((DB_VERSION_MAJOR > 4) || (DB_VERSION_MINOR >= 1)) + r = dbp->open(dbp, NULL, filename, NULL, DB_BTREE, DB_CREATE, + S_IRUSR | S_IWUSR); +#else + r = dbp->open(dbp, filename, NULL, DB_BTREE, DB_CREATE, S_IRUSR | S_IWUSR); +#endif + if (r != 0) + goto close_db; +#else +#if DBVERS > 1 + r = db_open(filename, DB_BTREE, DB_CREATE, S_IRUSR | S_IWUSR, + NULL, NULL, &dbp); + if (r != 0) + goto err; +#elif DBVERS == 1 + dbp = dbopen(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, DB_BTREE, NULL); + if (dbp == NULL) + goto err; +#else + goto err; +#endif +#endif + + cache_db = mail_cache_db_new(dbp); + if (cache_db == NULL) + goto close_db; + + * pcache_db = cache_db; + + return 0; + + close_db: +#if DBVERS > 1 + dbp->close(dbp, 0); +#elif DBVERS == 1 + dbp->close(dbp); +#endif + err: + return -1; +#else + return -1; +#endif +} + +void mail_cache_db_close(struct mail_cache_db * cache_db) +{ +#if DBVERS >= 1 + DB * dbp; + + dbp = cache_db->internal_database; + +#if DBVERS > 1 + dbp->close(cache_db->internal_database, 0); +#elif DBVERS == 1 + dbp->close(cache_db->internal_database); +#endif + + mail_cache_db_free(cache_db); +#endif +} + +int mail_cache_db_open_lock(const char * filename, + struct mail_cache_db ** pcache_db) +{ + int r; + struct mail_cache_db * cache_db; + + r = maillock_write_lock(filename, -1); + if (r < 0) + goto err; + + r = mail_cache_db_open(filename, &cache_db); + if (r < 0) + goto unlock; + + * pcache_db = cache_db; + + return 0; + + unlock: + maillock_write_unlock(filename, -1); + err: + return -1; +} + +void mail_cache_db_close_unlock(const char * filename, + struct mail_cache_db * cache_db) +{ + mail_cache_db_close(cache_db); + maillock_write_unlock(filename, -1); +} + + +int mail_cache_db_put(struct mail_cache_db * cache_db, + const void * key, size_t key_len, const void * value, size_t value_len) +{ +#if DBVERS >= 1 + int r; + DBT db_key; + DBT db_data; + DB * dbp; + + dbp = cache_db->internal_database; + + memset(&db_key, 0, sizeof(db_key)); + memset(&db_data, 0, sizeof(db_data)); + db_key.data = (void *) key; + db_key.size = key_len; + db_data.data = (void *) value; + db_data.size = value_len; + +#if DBVERS > 1 + r = dbp->put(dbp, NULL, &db_key, &db_data, 0); +#elif DBVERS == 1 + r = dbp->put(dbp, &db_key, &db_data, 0); +#else + r = -1; +#endif + if (r != 0) + return -1; + + return 0; +#else + return -1; +#endif +} + +int mail_cache_db_get(struct mail_cache_db * cache_db, + const void * key, size_t key_len, void ** pvalue, size_t * pvalue_len) +{ +#if DBVERS >= 1 + int r; + DBT db_key; + DBT db_data; + DB * dbp; + + dbp = cache_db->internal_database; + + memset(&db_key, 0, sizeof(db_key)); + memset(&db_data, 0, sizeof(db_data)); + db_key.data = (void *) key; + db_key.size = key_len; + +#if DBVERS > 1 + r = dbp->get(dbp, NULL, &db_key, &db_data, 0); +#elif DBVERS == 1 + r = dbp->get(dbp, &db_key, &db_data, 0); +#else + r = -1; +#endif + + if (r != 0) + return -1; + + * pvalue = db_data.data; + * pvalue_len = db_data.size; + + return 0; +#else + return -1; +#endif +} + +int mail_cache_db_del(struct mail_cache_db * cache_db, + const void * key, size_t key_len) +{ +#if DBVERS >= 1 + int r; + DBT db_key; + DB * dbp; + + dbp = cache_db->internal_database; + + memset(&db_key, 0, sizeof(db_key)); + db_key.data = (void *) key; + db_key.size = key_len; + +#if DBVERS > 1 + r = dbp->del(dbp, NULL, &db_key, 0); +#elif DBVERS == 1 + r = dbp->del(dbp, &db_key, 0); +#else + r = -1; +#endif + if (r != 0) + return -1; + + return 0; +#else + return -1; +#endif +} + +#if DBVERS > 1 +int mail_cache_db_clean_up(struct mail_cache_db * cache_db, + chash * exist) +{ + DB * dbp; + int r; + DBC * dbcp; + DBT db_key; + DBT db_data; + + dbp = cache_db->internal_database; + +#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6 + r = dbp->cursor(dbp, NULL, &dbcp); +#else + r = dbp->cursor(dbp, NULL, &dbcp, 0); +#endif + if (r != 0) + return -1; + + memset(&db_key, 0, sizeof(db_key)); + memset(&db_data, 0, sizeof(db_data)); + + while (1) { + chashdatum hash_key; + chashdatum hash_data; + + r = dbcp->c_get(dbcp, &db_key, &db_data, DB_NEXT); + if (r != 0) + break; + + hash_key.data = db_key.data; + hash_key.len = db_key.size; + + r = chash_get(exist, &hash_key, &hash_data); + if (r < 0) { + r = dbcp->c_del(dbcp, 0); + if (r != 0) + return -1; + } + } + + r = dbcp->c_close(dbcp); + if (r != 0) + return -1; + + return 0; +} +#elif DBVERS == 1 +int mail_cache_db_clean_up(struct mail_cache_db * cache_db, + chash * exist) +{ + DB * dbp; + int r; + DBT db_key; + DBT db_data; + + dbp = cache_db->internal_database; + + r = dbp->seq(dbp, &db_key, &db_data, R_FIRST); + if (r == -1) + return -1; + + while (r == 0) { + chashdatum hash_key; + chashdatum hash_data; + + hash_key.data = db_key.data; + hash_key.len = (unsigned int) db_key.size; + + r = chash_get(exist, &hash_key, &hash_data); + if (r < 0) { + r = dbp->del(dbp, &db_key, 0); + if (r != 0) + return -1; + } + + r = dbp->seq(dbp, &db_key, &db_data, R_NEXT); + if (r < 0) + return -1; + } + + return 0; +} +#else +int mail_cache_db_clean_up(struct mail_cache_db * cache_db, + chash * exist) +{ + return -1; +} +#endif + +int mail_cache_db_get_size(struct mail_cache_db * cache_db, + const void * key, size_t key_len, size_t * pvalue_len) +{ +#if DBVERS >= 1 + int r; + DBT db_key; + DBT db_data; + DB * dbp; + + dbp = cache_db->internal_database; + + memset(&db_key, 0, sizeof(db_key)); + memset(&db_data, 0, sizeof(db_data)); + db_key.data = (void *) key; + db_key.size = key_len; +#if DBVERS > 1 + db_data.flags = DB_DBT_USERMEM; + db_data.ulen = 0; +#endif + +#if DBVERS > 1 + r = dbp->get(dbp, NULL, &db_key, &db_data, 0); +#elif DBVERS == 1 + r = dbp->get(dbp, &db_key, &db_data, 0); +#else + r = -1; +#endif + + if (r != 0) + return -1; + + * pvalue_len = db_data.size; + + return 0; +#else + return -1; +#endif +} + +#if DBVERS > 1 +int mail_cache_db_get_keys(struct mail_cache_db * cache_db, + chash * keys) +{ + DB * dbp; + int r; + DBC * dbcp; + DBT db_key; + DBT db_data; + + dbp = cache_db->internal_database; + + r = dbp->cursor(dbp, NULL, &dbcp, 0); + if (r != 0) + return -1; + + memset(&db_key, 0, sizeof(db_key)); + memset(&db_data, 0, sizeof(db_data)); + + while (1) { + chashdatum hash_key; + chashdatum hash_data; + + r = dbcp->c_get(dbcp, &db_key, &db_data, DB_NEXT); + if (r != 0) + break; + + hash_key.data = db_key.data; + hash_key.len = db_key.size; + hash_data.data = NULL; + hash_data.len = 0; + + r = chash_set(keys, &hash_key, &hash_data, NULL); + if (r < 0) { + return -1; + } + } + + r = dbcp->c_close(dbcp); + if (r != 0) + return -1; + + return 0; +} +#elif DBVERS == 1 +int mail_cache_db_get_keys(struct mail_cache_db * cache_db, + chash * keys) +{ + DB * dbp; + int r; + DBT db_key; + DBT db_data; + + dbp = cache_db->internal_database; + + r = dbp->seq(dbp, &db_key, &db_data, R_FIRST); + if (r == -1) + return -1; + + while (r == 0) { + chashdatum hash_key; + chashdatum hash_data; + + hash_key.data = db_key.data; + hash_key.len = (unsigned int) db_key.size; + hash_data.data = NULL; + hash_data.len = 0; + + r = chash_set(keys, &hash_key, &hash_data, NULL); + if (r < 0) { + return -1; + } + + r = dbp->seq(dbp, &db_key, &db_data, R_NEXT); + if (r < 0) + return -1; + } + + return 0; +} +#else +int mail_cache_db_get_keys(struct mail_cache_db * cache_db, + chash * keys) +{ + return -1; +} +#endif + +#endif diff --git a/Sources/libetpan/data-types/mail_cache_db.h b/Sources/libetpan/data-types/mail_cache_db.h new file mode 100644 index 00000000..ec8a9fa3 --- /dev/null +++ b/Sources/libetpan/data-types/mail_cache_db.h @@ -0,0 +1,158 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mail_cache_db.h,v 1.6 2005/04/07 00:05:25 hoa Exp $ + */ + +#ifndef MAIL_CACHE_DB_H + +#define MAIL_CACHE_DB_H + +#include +#include "mail_cache_db_types.h" +#include "chash.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + this module will handle a database "f(key) -> value" in a file + + berkeley DB or other can be used for implementation of low-level file. +*/ + +/* + mail_cache_db_open() + + This function opens the file "filename". + The pointer return in pcache_db should be used for further references + to the database. +*/ + +int mail_cache_db_open(const char * filename, + struct mail_cache_db ** pcache_db); + +/* + mail_cache_db_close() + + This function closes the opened database. + The pointer cannot be used later. +*/ + +void mail_cache_db_close(struct mail_cache_db * cache_db); + +/* + mail_cache_db_open_lock() + + This function opens and locks the file "filename". + The pointer return in pcache_db should be used for further references + to the database. +*/ + +int mail_cache_db_open_lock(const char * filename, + struct mail_cache_db ** pcache_db); + +/* + mail_cache_db_open_unlock() + + This function closes and unlocks the opened database. + The pointer cannot be used later. +*/ + +void mail_cache_db_close_unlock(const char * filename, + struct mail_cache_db * cache_db); + +/* + mail_cache_db_put() + + This function will store a given key and value in the database. +*/ + +int mail_cache_db_put(struct mail_cache_db * cache_db, + const void * key, size_t key_len, const void * value, size_t value_len); + +/* + mail_cache_db_get() + + This function will retrieve the value corresponding to a given key + from the database. +*/ + +int mail_cache_db_get(struct mail_cache_db * cache_db, + const void * key, size_t key_len, void ** pvalue, size_t * pvalue_len); + +/* + mail_cache_db_get_size() + + This function will retrieve the size of the value corresponding + to a given key from the database. +*/ + +int mail_cache_db_get_size(struct mail_cache_db * cache_db, + const void * key, size_t key_len, size_t * pvalue_len); + +/* + mail_cache_db_del() + + This function will delete the given key and the corresponding value + from the database. +*/ + +int mail_cache_db_del(struct mail_cache_db * cache_db, + const void * key, size_t key_len); + +/* + mail_cache_clean_up() + + This function will delete the key all the key/value pairs of the + database file which key does not exist in the given hash. +*/ + +int mail_cache_db_clean_up(struct mail_cache_db * cache_db, + chash * exist); + +/* + mail_cache_db_get_keys() + + This function will get all keys of the database and will + store them to the given chash. +*/ + +int mail_cache_db_get_keys(struct mail_cache_db * cache_db, + chash * keys); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/data-types/mail_cache_db_types.h b/Sources/libetpan/data-types/mail_cache_db_types.h new file mode 100644 index 00000000..7ebc1e45 --- /dev/null +++ b/Sources/libetpan/data-types/mail_cache_db_types.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mail_cache_db_types.h,v 1.2 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef MAIL_CACHE_DB_TYPES_H + +#define MAIL_CACHE_DB_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct mail_cache_db { + void * internal_database; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/data-types/mail_cache_lmdb.c b/Sources/libetpan/data-types/mail_cache_lmdb.c new file mode 100644 index 00000000..154d5b61 --- /dev/null +++ b/Sources/libetpan/data-types/mail_cache_lmdb.c @@ -0,0 +1,391 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mail_cache_lmdb.c,v 1.20 2018/10/12 13:39:40 lay Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef LMDB + +#include "mail_cache_db.h" + +#include +#include +#include +#include +#include +#include + +#include "libetpan-config.h" + +#include "maillock.h" + + +static struct mail_cache_db * mail_cache_lmdb_new(MDB_env *env) +{ + struct mail_cache_db * cache_db; + + cache_db = malloc(sizeof(* cache_db)); + if (cache_db == NULL) + return NULL; + cache_db->internal_database = env; + + return cache_db; +} + +static void mail_cache_db_free(struct mail_cache_db * cache_db) +{ + free(cache_db); +} + + +void mail_cache_db_close(struct mail_cache_db * cache_db) +{ + MDB_env *env; + + env = cache_db->internal_database; + mdb_env_close(env); + mail_cache_db_free(cache_db); +} + +int mail_cache_db_open(const char * filename, + struct mail_cache_db ** pcache_db) +{ + int r; + struct mail_cache_db * cache_db; + MDB_env *env; + + r = mdb_env_create(&env); + if (r != 0) + return -1; + + r = mdb_env_set_mapsize(env, 512*1024*1024 /*max mmap and file size*/); + if (r != 0) + return -1; + + r = mdb_env_open(env, filename, MDB_NOSUBDIR, 0660); + if (r != 0) + goto close_db; + + cache_db = mail_cache_lmdb_new(env); + if (cache_db == NULL) + goto close_db; + + * pcache_db = cache_db; + + return 0; + + close_db: + mdb_env_close(env); + return -1; + +} + +int mail_cache_db_open_lock(const char * filename, + struct mail_cache_db ** pcache_db) +{ + int r; + struct mail_cache_db * cache_db; + + r = maillock_write_lock(filename, -1); + if (r < 0) + goto err; + r = mail_cache_db_open(filename, &cache_db); + if (r < 0) + goto unlock; + + * pcache_db = cache_db; + + return 0; + + unlock: + maillock_write_unlock(filename, -1); + err: + return -1; +} + +void mail_cache_db_close_unlock(const char * filename, + struct mail_cache_db * cache_db) +{ + mail_cache_db_close(cache_db); + maillock_write_unlock(filename, -1); +} + + +int mail_cache_db_put(struct mail_cache_db * cache_db, + const void * key, size_t key_len, const void * value, size_t value_len) +{ + int r; + MDB_env *env; + MDB_txn *txn; + MDB_dbi dbi; + MDB_val mdb_key; + MDB_val mdb_val; + + env = cache_db->internal_database; + + mdb_key.mv_size = key_len; + mdb_key.mv_data = (void *) key; + mdb_val.mv_size = value_len; + mdb_val.mv_data = (void *) value; + + r = mdb_txn_begin(env, NULL, 0, &txn); + if (r != 0) + return -1; + r = mdb_dbi_open(txn, NULL, 0, &dbi); + if (r != 0) + goto error; + + r = mdb_put(txn, dbi, &mdb_key, &mdb_val, 0); + if (r != 0) + goto error; + + mdb_txn_commit(txn); + return 0; + + error: + mdb_txn_abort(txn); + return -1; +} + +int mail_cache_db_get(struct mail_cache_db * cache_db, + const void * key, size_t key_len, void ** pvalue, size_t * pvalue_len) +{ + int r; + MDB_env *env; + MDB_txn *txn; + MDB_dbi dbi; + MDB_val mdb_key; + MDB_val mdb_val; + + env = cache_db->internal_database; + + mdb_key.mv_size = key_len; + mdb_key.mv_data = (void *) key; + + r = mdb_txn_begin(env, NULL, 0, &txn); + if (r != 0) + return -1; + r = mdb_dbi_open(txn, NULL, 0, &dbi); + if (r != 0) + goto error; + + r = mdb_get(txn, dbi, &mdb_key, &mdb_val); + if (r != 0) + goto error; + + * pvalue = mdb_val.mv_data; + * pvalue_len = mdb_val.mv_size; + mdb_txn_commit(txn); + return 0; + + error: + mdb_txn_abort(txn); + return -1; +} + +int mail_cache_db_del(struct mail_cache_db * cache_db, + const void * key, size_t key_len) +{ + int r; + MDB_env *env; + MDB_txn *txn; + MDB_dbi dbi; + MDB_val mdb_key; + + env = cache_db->internal_database; + + mdb_key.mv_size = key_len; + mdb_key.mv_data = (void *) key; + + r = mdb_txn_begin(env, NULL, 0, &txn); + if (r != 0) + return -1; + r = mdb_dbi_open(txn, NULL, 0, &dbi); + if (r != 0) + goto error; + + r = mdb_del(txn, dbi, &mdb_key, NULL); + if (r != 0) + goto error; + + return 0; + + error: + mdb_txn_abort(txn); + return -1; +} + +int mail_cache_db_clean_up(struct mail_cache_db * cache_db, + chash * exist) +{ + int r; + MDB_env *env; + MDB_txn *txn; + MDB_dbi dbi; + MDB_cursor *cursor; + MDB_val mdb_key; + MDB_val mdb_val; + + env = cache_db->internal_database; + + r = mdb_txn_begin(env, NULL, 0, &txn); + if (r != 0) + return -1; + r = mdb_dbi_open(txn, NULL, 0, &dbi); + if (r != 0) + goto error; + + r = mdb_cursor_open(txn, dbi, &cursor); + if (r != 0) + goto error; + + r = mdb_cursor_get(cursor, &mdb_key, &mdb_val, MDB_FIRST); + if (r != 0) + goto cursor_error; + + while (r == 0) { + chashdatum hash_key; + chashdatum hash_data; + + hash_key.data = mdb_key.mv_data; + hash_key.len = (unsigned int) mdb_key.mv_size; + + r = chash_get(exist, &hash_key, &hash_data); + if (r < 0) { + r = mdb_cursor_del(cursor, 0); + if (r != 0) + goto cursor_error; + } + r = mdb_cursor_get(cursor, &mdb_key, &mdb_val, MDB_NEXT); + } + + mdb_txn_commit(txn); + return 0; + cursor_error: + mdb_cursor_close(cursor); + error: + mdb_txn_abort(txn); + return -1; +} + +int mail_cache_db_get_size(struct mail_cache_db * cache_db, + const void * key, size_t key_len, size_t * pvalue_len) +{ + int r; + MDB_env *env; + MDB_txn *txn; + MDB_dbi dbi; + MDB_val mdb_key; + MDB_val mdb_val; + + env = cache_db->internal_database; + + mdb_key.mv_size = key_len; + mdb_key.mv_data = (void *) key; + + r = mdb_txn_begin(env, NULL, 0, &txn); + if (r != 0) + return -1; + r = mdb_dbi_open(txn, NULL, 0, &dbi); + if (r != 0) + goto error; + + r = mdb_get(txn, dbi, &mdb_key, &mdb_val); + if (r != 0) + goto error; + + * pvalue_len = mdb_val.mv_size; + mdb_txn_commit(txn); + return 0; + + error: + mdb_txn_abort(txn); + return -1; +} + +int mail_cache_db_get_keys(struct mail_cache_db * cache_db, + chash * keys) +{ + int r; + MDB_env *env; + MDB_txn *txn; + MDB_dbi dbi; + MDB_cursor *cursor; + MDB_val mdb_key; + MDB_val mdb_val; + + env = cache_db->internal_database; + + r = mdb_txn_begin(env, NULL, 0, &txn); + if (r != 0) + return -1; + r = mdb_dbi_open(txn, NULL, 0, &dbi); + if (r != 0) + goto error; + + r = mdb_cursor_open(txn, dbi, &cursor); + if (r != 0) + goto error; + + r = mdb_cursor_get(cursor, &mdb_key, &mdb_val, MDB_FIRST); + if (r != 0) + goto cursor_error; + + while (r == 0) { + chashdatum hash_key; + chashdatum hash_data; + + hash_key.data = mdb_key.mv_data; + hash_key.len = (unsigned int) mdb_key.mv_size; + hash_data.data = NULL; + hash_data.len = 0; + + r = chash_set(keys, &hash_key, &hash_data, NULL); + if (r != 0) + goto cursor_error; + r = mdb_cursor_get(cursor, &mdb_key, &mdb_val, MDB_NEXT); + } + + mdb_txn_commit(txn); + return 0; + + cursor_error: + mdb_cursor_close(cursor); + error: + mdb_txn_abort(txn); + return -1; +} +#endif diff --git a/Sources/libetpan/data-types/maillock.c b/Sources/libetpan/data-types/maillock.c new file mode 100644 index 00000000..4847d777 --- /dev/null +++ b/Sources/libetpan/data-types/maillock.c @@ -0,0 +1,379 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maillock.c,v 1.19 2010/04/05 14:21:35 hoa Exp $ + */ +#define HAVE_CONFIG_H 1 + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "maillock.h" + +#include "libetpan-config.h" + +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#include +#ifdef WIN32 +# include "win_etpan.h" +#endif +#ifdef HAVE_LIBLOCKFILE +#include +#endif + +/* ********************************************************************** */ + +/* lock primitives */ + +/* the lock code is modified from the dot lock file code from mail.local.c */ + +/* + SENDMAIL LICENSE + +The following license terms and conditions apply, unless a different +license is obtained from Sendmail, Inc., 6425 Christie Ave, Fourth Floor, +Emeryville, CA 94608, or by electronic mail at license@sendmail.com. + +License Terms: + +Use, Modification and Redistribution (including distribution of any +modified or derived work) in source and binary forms is permitted only if +each of the following conditions is met: + +1. Redistributions qualify as "freeware" or "Open Source Software" under + one of the following terms: + + (a) Redistributions are made at no charge beyond the reasonable cost of + materials and delivery. + + (b) Redistributions are accompanied by a copy of the Source Code or by an + irrevocable offer to provide a copy of the Source Code for up to three + years at the cost of materials and delivery. Such redistributions + must allow further use, modification, and redistribution of the Source + Code under substantially the same terms as this license. For the + purposes of redistribution "Source Code" means the complete compilable + and linkable source code of sendmail including all modifications. + +2. Redistributions of source code must retain the copyright notices as they + appear in each source code file, these license terms, and the + disclaimer/limitation of liability set forth as paragraph 6 below. + +3. Redistributions in binary form must reproduce the Copyright Notice, + these license terms, and the disclaimer/limitation of liability set + forth as paragraph 6 below, in the documentation and/or other materials + provided with the distribution. For the purposes of binary distribution + the "Copyright Notice" refers to the following language: + "Copyright (c) 1998-2002 Sendmail, Inc. All rights reserved." + +4. Neither the name of Sendmail, Inc. nor the University of California nor + the names of their contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. The name "sendmail" is a trademark of Sendmail, Inc. + +5. All redistributions must comply with the conditions imposed by the + University of California on certain embedded code, whose copyright + notice and conditions for redistribution are as follows: + + (a) Copyright (c) 1988, 1993 The Regents of the University of + California. All rights reserved. + + (b) Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + (i) Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + (ii) Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + (iii) Neither the name of the University nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +6. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY + SENDMAIL, INC. AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + NO EVENT SHALL SENDMAIL, INC., THE REGENTS OF THE UNIVERSITY OF + CALIFORNIA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +*/ + +/* + TODO : lock, prefer fcntl() over flock() + AND use dotlock code above +*/ + +#define LOCKTO_RM 300 /* timeout for stale lockfile removal */ +#define LOCKTO_GLOB 400 /* global timeout for lockfile creation */ + +#ifdef WIN32 +# define F_RDLCK 0 +# define F_WRLCK 1 +# include +#endif + +static int lock_common(const char * filename, int fd, short locktype) +{ +#ifdef WIN32 + time_t start; + + /* SEB try implementation */ +#ifdef SEB_TRY + int reslock; + + lseek( fd, 0L, SEEK_SET ); + reslock = _locking( fd, _LK_NBLCK, LONG_MAX); + if (reslock == 0) return 0; + if (errno != EACCES) return -1; + + time(&start); + + while (1) { + time_t now; + sleep( 5); + reslock = _locking( fd, _LK_NBLCK, LONG_MAX); + if (reslock == 0) return 0; + if (errno != EACCES) return -1; + time(&now); + if (now > start + LOCKTO_GLOB) { + return -1; +#else /* SEB_TRY */ + if (fd != -1) { + lseek( fd, 0L, SEEK_SET ); + if (_locking( fd, _LK_NBLCK, LONG_MAX) == 0) return 0; + + time(&start); + + while (1) { + time_t now; + sleep( 5); + if (_locking( fd, _LK_NBLCK, LONG_MAX) == 0) return 0; + time(&now); + if (now > start + LOCKTO_GLOB) { + return -1; + } +#endif /* SEB_TRY */ + } + } + return 0; /* SEB 20070709 */ + +#else /* WIN32 */ + char lockfilename[PATH_MAX]; +#ifndef HAVE_LIBLOCKFILE + struct flock lock; + /* dot lock file */ + int statfailed = 0; + time_t start; + int r; +#endif /* HAVE_LIBLOCKFILE */ + int res; + + /* dot lock file */ + + if (strlen(filename) + 6 > PATH_MAX) { + res = -1; + goto err; + } + + snprintf(lockfilename, PATH_MAX, "%s.lock", filename); + +#ifdef HAVE_LIBLOCKFILE + return lockfile_create(lockfilename, LOCKTO_GLOB, 0); +#else + + if (fd != -1) { + lock.l_start = 0; + lock.l_len = 0; + lock.l_pid = getpid(); + lock.l_type = locktype; + lock.l_whence = SEEK_SET; + + r = fcntl(fd, F_SETLKW, &lock); + if (r < 0) { + /* WARNING POSIX lock could not be applied */ + } + } + + time(&start); + while (1) { + int fd2; + struct stat st; + time_t now; + + /* global timeout */ + time(&now); + if (now > start + LOCKTO_GLOB) { + res = -1; + goto unlock; + } + + fd2 = open(lockfilename, O_WRONLY|O_EXCL|O_CREAT, 0); + if (fd2 >= 0) { + /* defeat lock checking programs which test pid */ + r = (int) write(fd2, "0", 2); + close(fd2); + break; + } + + /* libEtPan! - adds a delay of 5 seconds between each tries */ + sleep(5); + + if (stat(lockfilename, &st) < 0) { + if (statfailed++ > 5) { + res = -1; + goto unlock; + } + continue; + } + statfailed = 0; + time(&now); + + if (now < st.st_ctime + LOCKTO_RM) + continue; + + /* try to remove stale lockfile */ + if (unlink(lockfilename) < 0) { + res = -1; + goto unlock; + } + + /* + libEtPan! - removes this delay of 5 seconds, + maybe it was misplaced ? + */ +#if 0 + sleep(5); +#endif + } + + return 0; + + unlock: + if (fd != -1) { + lock.l_start = 0; + lock.l_len = 0; + lock.l_pid = getpid(); + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + + r = fcntl(fd, F_SETLK, &lock); + if (r < 0) { + /* WARNING POSIX lock could not be applied */ + } + } +#endif /* HAVE_LIBLOCKFILE */ + err: + return res; +#endif /* WIN32 */ +} + +static int unlock_common(const char * filename, int fd) +{ +/* SEB */ +#ifdef WIN32 + if (fd != -1) { + lseek( fd, 0L, SEEK_SET ); + _locking( fd, _LK_UNLCK, LONG_MAX); + } + return 0; +#else + char lockfilename[PATH_MAX]; +#ifndef HAVE_LIBLOCKFILE + struct flock lock; + int r; +#endif + + if (strlen(filename) + 6 > PATH_MAX) + return -1; + + snprintf(lockfilename, PATH_MAX, "%s.lock", filename); + +#ifdef HAVE_LIBLOCKFILE + return lockfile_remove(lockfilename); +#else + + unlink(lockfilename); + + if (fd != -1) { + lock.l_start = 0; + lock.l_len = 0; + lock.l_pid = getpid(); + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + + r = fcntl(fd, F_SETLK, &lock); + if (r < 0) { + /* WARNING POSIX lock could not be applied */ + } + } + + return 0; +#endif +#endif /* WIN32 */ +} + +int maillock_read_lock(const char * filename, int fd) +{ + return lock_common(filename, fd, F_RDLCK); +} + +int maillock_read_unlock(const char * filename, int fd) +{ + return unlock_common(filename, fd); +} + +int maillock_write_lock(const char * filename, int fd) +{ + return lock_common(filename, fd, F_WRLCK); +} + +int maillock_write_unlock(const char * filename, int fd) +{ + return unlock_common(filename, fd); +} diff --git a/Sources/libetpan/data-types/maillock.h b/Sources/libetpan/data-types/maillock.h new file mode 100644 index 00000000..c4d2a794 --- /dev/null +++ b/Sources/libetpan/data-types/maillock.h @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maillock.h,v 1.5 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef MAILLOCK_H + +#define MAILLOCK_H + +#ifdef __cplusplus +extern "C" { +#endif + +int maillock_read_lock(const char * filename, int fd); +int maillock_read_unlock(const char * filename, int fd); +int maillock_write_lock(const char * filename, int fd); +int maillock_write_unlock(const char * filename, int fd); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/data-types/mailsasl.c b/Sources/libetpan/data-types/mailsasl.c new file mode 100644 index 00000000..8623fd8e --- /dev/null +++ b/Sources/libetpan/data-types/mailsasl.c @@ -0,0 +1,143 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailsasl.h" + +#ifdef USE_SASL + +#ifdef LIBETPAN_REENTRANT +#if defined(HAVE_PTHREAD_H) && !defined(IGNORE_PTHREAD_H) +#include +#elif (defined WIN32) +#include +#endif +#endif + +#include +#include + +#ifdef LIBETPAN_REENTRANT +#if defined(HAVE_PTHREAD_H) && !defined(IGNORE_PTHREAD_H) +static pthread_mutex_t sasl_lock = PTHREAD_MUTEX_INITIALIZER; +#elif (defined WIN32) +static CRITICAL_SECTION sasl_lock = { 0 }; +static int sasl_lock_init_done = 0; +#endif +#endif + +#ifdef LIBETPAN_REENTRANT +#if defined(HAVE_PTHREAD_H) && !defined(IGNORE_PTHREAD_H) +#define LOCK_SASL() pthread_mutex_lock(&sasl_lock) +#define UNLOCK_SASL() pthread_mutex_unlock(&sasl_lock) +#elif (defined WIN32) +#define LOCK_SASL() EnterCriticalSection(&sasl_lock) +#define UNLOCK_SASL() LeaveCriticalSection(&sasl_lock) +#endif +#else +#define LOCK_SASL() do {} while(0) +#define UNLOCK_SASL() do {} while(0) +#endif + +static int sasl_use_count = 0; + +#ifdef LIBETPAN_REENTRANT + +void mailsasl_init_lock(){ +#if defined(HAVE_PTHREAD_H) && !defined(IGNORE_PTHREAD_H) + // nothing to do +#elif (defined WIN32) + static int volatile mainsasl_init_lock_done = 0; + if (InterlockedExchange(&mainsasl_init_lock_done, 1) == 0){ + InitializeCriticalSection(&sasl_lock); + } +#endif +} + +void mailsasl_uninit_lock(){ +#if defined(HAVE_PTHREAD_H) && !defined(IGNORE_PTHREAD_H) + // nothing to do +#elif (defined WIN32) + static int volatile mainsasl_init_lock_done = 0; + if (InterlockedExchange(&mainsasl_init_lock_done, 1) == 0){ + DeleteCriticalSection(&sasl_lock); + } +#endif +} + + +#endif + +void mailsasl_external_ref(void) +{ + LOCK_SASL(); + sasl_use_count ++; + UNLOCK_SASL(); +} + +void mailsasl_ref(void) +{ + LOCK_SASL(); + sasl_use_count ++; + if (sasl_use_count == 1) + sasl_client_init(NULL); + UNLOCK_SASL(); +} + +void mailsasl_unref(void) +{ + LOCK_SASL(); + sasl_use_count --; + if (sasl_use_count == 0) { +#if 0 /* workaround libsasl bug */ + sasl_done(); +#endif + } + UNLOCK_SASL(); +} + +#else + +void mailsasl_external_ref(void) +{ +} + +void mailsasl_ref(void) +{ +} + +void mailsasl_unref(void) +{ +} + +#endif diff --git a/Sources/libetpan/data-types/mailsasl.h b/Sources/libetpan/data-types/mailsasl.h new file mode 100644 index 00000000..6d567889 --- /dev/null +++ b/Sources/libetpan/data-types/mailsasl.h @@ -0,0 +1,50 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILSASL_H + +#define MAILSASL_H + +#ifdef __cplusplus +extern"C"{ +#endif + +/* if Cyrus-SASL is used outside of libetpan */ +void mailsasl_external_ref(void); + +void mailsasl_ref(void); +void mailsasl_unref(void); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/Sources/libetpan/data-types/mailsasl_private.h b/Sources/libetpan/data-types/mailsasl_private.h new file mode 100644 index 00000000..3ee1c38b --- /dev/null +++ b/Sources/libetpan/data-types/mailsasl_private.h @@ -0,0 +1,18 @@ +#ifndef MAILSASL_PRIVATE_H + +#define MAILSASL_PRIVATE_H + +#ifdef __cplusplus +extern"C"{ +#endif + +extern void mailsasl_init_lock(void); + +extern void mailsasl_uninit_lock(void); + +#ifdef __cplusplus +} +#endif + + +#endif \ No newline at end of file diff --git a/Sources/libetpan/data-types/mailsem.c b/Sources/libetpan/data-types/mailsem.c new file mode 100644 index 00000000..5ed3e432 --- /dev/null +++ b/Sources/libetpan/data-types/mailsem.c @@ -0,0 +1,286 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsem.c,v 1.11 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailsem.h" +#include +#include +#include +#include +#include +#ifndef _MSC_VER +#include +#endif + +#ifdef LIBETPAN_REENTRANT +#if defined(HAVE_PTHREAD_H) && !defined(IGNORE_PTHREAD_H) +#include +#include +#elif (defined WIN32) +#include +#endif +#endif + +struct mailsem_internal { + /* Current count of the semaphore. */ + unsigned int count; + + /* Number of threads that have called . */ + unsigned long waiters_count; + +#ifdef LIBETPAN_REENTRANT +#if defined(HAVE_PTHREAD_H) && !defined(IGNORE_PTHREAD_H) + /* Serialize access to and . */ + pthread_mutex_t lock; + + /* Condition variable that blocks the 0. */ + pthread_cond_t count_nonzero; +#elif (defined WIN32) + HANDLE semaphore; +#endif +#endif +}; + +#if (defined(LIBETPAN_REENTRANT) && defined(HAVE_PTHREAD_H) && !defined(IGNORE_PTHREAD_H)) || !defined(LIBETPAN_REENTRANT) + +static int mailsem_internal_init(struct mailsem_internal * s, + unsigned int initial_count) +{ +#ifdef LIBETPAN_REENTRANT + int r; + + r = pthread_mutex_init(&s->lock, NULL); + if (r != 0) + goto err; + + r = pthread_cond_init(&s->count_nonzero, NULL); + if (r != 0) + goto destroy_mutex; + + s->count = initial_count; + s->waiters_count = 0; + + return 0; + + destroy_mutex: + pthread_mutex_destroy(&s->lock); + err: + return -1; +#else + return -1; +#endif +} + +static void mailsem_internal_destroy(struct mailsem_internal * s) +{ +#ifdef LIBETPAN_REENTRANT + pthread_cond_destroy(&s->count_nonzero); + pthread_mutex_destroy(&s->lock); +#endif +} + +int mailsem_internal_wait(struct mailsem_internal * s) +{ +#ifdef LIBETPAN_REENTRANT + int r; + + /* Acquire mutex to enter critical section. */ + r = pthread_mutex_lock(&s->lock); + if (r != 0) + goto err; + + /* Keep track of the number of waiters so that works correctly. */ + s->waiters_count ++; + + /* Wait until the semaphore count is > 0, then atomically release */ + /* and wait for to be signaled. */ + while (s->count == 0) { + r = pthread_cond_wait(&s->count_nonzero, &s->lock); + if (r != 0) + goto unlock; + } + + /* lock> is now held. */ + + /* Decrement the waiters count. */ + s->waiters_count --; + + /* Decrement the semaphore's count. */ + s->count --; + + /* Release mutex to leave critical section. */ + pthread_mutex_unlock(&s->lock); + + return 0; + + unlock: + pthread_mutex_unlock(&s->lock); + err: + return -1; +#else + return -1; +#endif +} + +static int mailsem_internal_post(struct mailsem_internal * s) +{ +#ifdef LIBETPAN_REENTRANT + int r; + + r = pthread_mutex_lock(&s->lock); + if (r != 0) + goto err; + + /* Always allow one thread to continue if it is waiting. */ + if (s->waiters_count > 0) { + r = pthread_cond_signal(&s->count_nonzero); + if (r != 0) + goto unlock; + } + + /* Increment the semaphore's count. */ + s->count ++; + + pthread_mutex_unlock(&s->lock); + + return 0; + + unlock: + pthread_mutex_unlock(&s->lock); + err: + return -1; +#else + return -1; +#endif +} + +#elif (defined WIN32) + +static int mailsem_internal_init(struct mailsem_internal * s, + unsigned int initial_count) +{ + s->semaphore = CreateSemaphore( + NULL, // default security attributes + initial_count, // initial count + 0x7FFFFFFF, // maximum count + NULL); // unnamed semaphore + + return s->semaphore == NULL ? -1 : 0; +} + +static void mailsem_internal_destroy(struct mailsem_internal * s) +{ + if (s->semaphore != NULL){ + CloseHandle(s->semaphore); + } +} + +int mailsem_internal_wait(struct mailsem_internal * s) +{ + DWORD dwWaitResult = WAIT_TIMEOUT; + + while (dwWaitResult != WAIT_OBJECT_0 && dwWaitResult != WAIT_FAILED){ + dwWaitResult = WaitForSingleObject( + s->semaphore, // handle to semaphore + INFINITE); // zero-second time-out interval + } + + return dwWaitResult == WAIT_FAILED ? -1 : 0; +} + +static int mailsem_internal_post(struct mailsem_internal * s) +{ + if (!ReleaseSemaphore( + s->semaphore, // handle to semaphore + 1, // increase count by one + NULL) ) // not interested in previous count + { + return -1; + } + return 0; +} + +#endif + +LIBETPAN_EXPORT +struct mailsem * mailsem_new(void) +{ + struct mailsem * sem; + int r; + + sem = malloc(sizeof(* sem)); + if (sem == NULL) + goto err; + + sem->sem_sem = malloc(sizeof(struct mailsem_internal)); + if (sem->sem_sem == NULL) + goto free; + + r = mailsem_internal_init(sem->sem_sem, 0); + if (r < 0) + goto free_sem; + + return sem; + + free_sem: + free(sem->sem_sem); + free: + free(sem); + err: + return NULL; +} + +LIBETPAN_EXPORT +void mailsem_free(struct mailsem * sem) +{ + mailsem_internal_destroy(sem->sem_sem); + free(sem->sem_sem); + free(sem); +} + +LIBETPAN_EXPORT +int mailsem_up(struct mailsem * sem) +{ + return mailsem_internal_post(sem->sem_sem); +} + +LIBETPAN_EXPORT +int mailsem_down(struct mailsem * sem) +{ + return mailsem_internal_wait(sem->sem_sem); +} diff --git a/Sources/libetpan/data-types/mailsem.h b/Sources/libetpan/data-types/mailsem.h new file mode 100644 index 00000000..94049945 --- /dev/null +++ b/Sources/libetpan/data-types/mailsem.h @@ -0,0 +1,59 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsem.h,v 1.2 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef MAILSEM_H + +#define MAILSEM_H + +#include + +struct mailsem { + void * sem_sem; + int sem_kind; +}; + +LIBETPAN_EXPORT +struct mailsem * mailsem_new(void); + +LIBETPAN_EXPORT +void mailsem_free(struct mailsem * sem); + +LIBETPAN_EXPORT +int mailsem_up(struct mailsem * sem); + +LIBETPAN_EXPORT +int mailsem_down(struct mailsem * sem); + +#endif diff --git a/Sources/libetpan/data-types/mailstream.c b/Sources/libetpan/data-types/mailstream.c new file mode 100644 index 00000000..11b17356 --- /dev/null +++ b/Sources/libetpan/data-types/mailstream.c @@ -0,0 +1,422 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream.c,v 1.25 2011/03/11 21:49:36 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef WIN32 +# include "win_etpan.h" +#endif + +#include "mailstream.h" +#include "maillock.h" +#include "mailstream_cfstream.h" +#include "mailstream_compress.h" +#include "mailstream_cancel.h" +#include +#include +#include +#include + +#define DEFAULT_NETWORK_TIMEOUT 300 + +struct timeval mailstream_network_delay = +{ DEFAULT_NETWORK_TIMEOUT, 0 }; + +LIBETPAN_EXPORT +mailstream * mailstream_new(mailstream_low * low, size_t buffer_size) +{ + mailstream * s; + + s = malloc(sizeof(* s)); + if (s == NULL) + goto err; + + s->read_buffer = malloc(buffer_size); + if (s->read_buffer == NULL) + goto free_s; + s->read_buffer_len = 0; + + s->write_buffer = malloc(buffer_size); + if (s->write_buffer == NULL) + goto free_read_buffer; + s->write_buffer_len = 0; + + s->buffer_max_size = buffer_size; + s->low = NULL; + + s->idle = NULL; + s->idling = 0; + + s->logger = NULL; + s->logger_context = NULL; + + mailstream_set_low(s, low); + + return s; + + free_read_buffer: + free(s->read_buffer); + free_s: + free(s); + err: + return NULL; +} + +static size_t write_to_internal_buffer(mailstream * s, + const void * buf, size_t count) +{ + memcpy(s->write_buffer + s->write_buffer_len, buf, count); + s->write_buffer_len += count; + + return count; +} + +static ssize_t write_direct(mailstream * s, const void * buf, size_t count) +{ + size_t left; + const char * cur_buf; + ssize_t written; + + cur_buf = buf; + left = count; + while (left > 0) { + written = mailstream_low_write(s->low, cur_buf, left); + + if (written < 0) { + if (count == left) + return -1; + else + return count - left; + } + + cur_buf += written; + left -= written; + } + + return count; +} + +LIBETPAN_EXPORT +ssize_t mailstream_write(mailstream * s, const void * buf, size_t count) +{ + int r; + + if (s == NULL) + return -1; + + if (count + s->write_buffer_len > s->buffer_max_size) { + r = mailstream_flush(s); + if (r == -1) + return -1; + + if (count > s->buffer_max_size) + return write_direct(s, buf, count); + } + + return write_to_internal_buffer(s, buf, count); +} + +LIBETPAN_EXPORT +int mailstream_flush(mailstream * s) +{ + char * cur_buf; + size_t left; + ssize_t written; + + if (s == NULL) + return -1; + + cur_buf = s->write_buffer; + left = s->write_buffer_len; + while (left > 0) { + written = mailstream_low_write(s->low, cur_buf, left); + + if (written < 0) + goto move_buffer; + cur_buf += written; + left -= written; + } + + s->write_buffer_len = 0; + + return 0; + + move_buffer: + memmove(s->write_buffer, cur_buf, left); + s->write_buffer_len = left; + return -1; +} + +static ssize_t read_from_internal_buffer(mailstream * s, + void * buf, size_t count) +{ + if (count >= s->read_buffer_len) + count = s->read_buffer_len; + if (count != 0) + memcpy(buf, s->read_buffer, count); + + s->read_buffer_len -= count; + if (s->read_buffer_len != 0) + memmove(s->read_buffer, s->read_buffer + count, + s->read_buffer_len); + + return count; +} + +LIBETPAN_EXPORT +ssize_t mailstream_read(mailstream * s, void * buf, size_t count) +{ + ssize_t read_bytes; + char * cur_buf; + size_t left; + + if (s == NULL) + return -1; + + left = count; + cur_buf = buf; + read_bytes = read_from_internal_buffer(s, cur_buf, left); + cur_buf += read_bytes; + left -= read_bytes; + + if (left == 0) { + return read_bytes; + } + + if (left > s->buffer_max_size) { + read_bytes = mailstream_low_read(s->low, cur_buf, left); + + if (read_bytes == -1) { + if (count == left) + return -1; + else { + return count - left; + } + } + + cur_buf += read_bytes; + left -= read_bytes; + + return count - left; + } + + read_bytes = mailstream_low_read(s->low, s->read_buffer, s->buffer_max_size); + if (read_bytes < 0) { + if (left == count) + return -1; + else { + return count - left; + } + } + else + s->read_buffer_len += read_bytes; + + read_bytes = read_from_internal_buffer(s, cur_buf, left); + cur_buf += read_bytes; + left -= read_bytes; + + return count - left; +} + +LIBETPAN_EXPORT +mailstream_low * mailstream_get_low(mailstream * s) +{ + return s->low; +} + +static void low_logger(mailstream_low * s, int log_type, + const char * str, size_t size, void * context) +{ + mailstream * stream = context; + if (stream->logger != NULL) { + stream->logger(context, log_type, str, size, stream->logger_context); + } +} + +LIBETPAN_EXPORT +void mailstream_set_low(mailstream * s, mailstream_low * low) +{ + s->low = low; + mailstream_low_set_logger(low, low_logger, s); +} + +LIBETPAN_EXPORT +int mailstream_close(mailstream * s) +{ + if (s->idle != NULL) { + mailstream_cancel_free(s->idle); + } + + mailstream_low_close(s->low); + mailstream_low_free(s->low); + + free(s->read_buffer); + free(s->write_buffer); + + free(s); + + return 0; +} + +LIBETPAN_EXPORT +ssize_t mailstream_feed_read_buffer(mailstream * s) +{ + ssize_t read_bytes; + + if (s == NULL) + return -1; + + if (s->read_buffer_len == 0) { + read_bytes = mailstream_low_read(s->low, s->read_buffer, + s->buffer_max_size); + if (read_bytes < 0) + return -1; + s->read_buffer_len += read_bytes; + } + + return s->read_buffer_len; +} + +LIBETPAN_EXPORT +void mailstream_cancel(mailstream * s) +{ + if (s == NULL) + return; + + mailstream_low_cancel(s->low); +} + +LIBETPAN_EXPORT +void mailstream_log_error(mailstream * s, char * buf, size_t count) +{ + mailstream_low_log_error(s->low, buf, count); +} + +LIBETPAN_EXPORT +void mailstream_set_privacy(mailstream * s, int can_be_public) +{ + mailstream_low_set_privacy(s->low, can_be_public); +} + +LIBETPAN_EXPORT +int mailstream_wait_idle(mailstream * s, int max_idle_delay) +{ + return mailstream_low_wait_idle(s->low, s->idle, max_idle_delay); +} + +LIBETPAN_EXPORT +int mailstream_setup_idle(mailstream * s) +{ + int r; + + if (s->idling) { + return -1; + } + + r = mailstream_low_setup_idle(s->low); + if (r < 0) { + s->idle = mailstream_cancel_new(); + if (s->idle == NULL) + return -1; + } + + s->idling = 1; + + return 0; +} + +LIBETPAN_EXPORT +void mailstream_interrupt_idle(mailstream * s) +{ + int r; + + if (!s->idling) { + return; + } + + r = mailstream_low_interrupt_idle(s->low); + if (r < 0) { + mailstream_cancel_notify(s->idle); + } +} + +LIBETPAN_EXPORT +void mailstream_unsetup_idle(mailstream * s) +{ + int r; + + if (!s->idling) { + return; + } + + r = mailstream_low_unsetup_idle(s->low); + if (r < 0) { + mailstream_cancel_free(s->idle); + s->idle = NULL; + } + + s->idling = 0; +} + +LIBETPAN_EXPORT +void mailstream_set_logger(mailstream * s, void (* logger)(mailstream * s, int log_type, + const char * str, size_t size, void * context), void * logger_context) +{ + s->logger = logger; + s->logger_context = logger_context; +} + +LIBETPAN_EXPORT +carray * mailstream_get_certificate_chain(mailstream * s) +{ + return mailstream_low_get_certificate_chain(s->low); +} + +LIBETPAN_EXPORT +void mailstream_certificate_chain_free(carray * certificate_chain) +{ + unsigned int i; + + if (certificate_chain == NULL) + return; + + for(i = 0 ; i < carray_count(certificate_chain) ; i ++) { + mmap_string_free(carray_get(certificate_chain, i)); + } + carray_free(certificate_chain); +} + diff --git a/Sources/libetpan/data-types/mailstream.h b/Sources/libetpan/data-types/mailstream.h new file mode 100644 index 00000000..680a36e7 --- /dev/null +++ b/Sources/libetpan/data-types/mailstream.h @@ -0,0 +1,135 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream.h,v 1.21 2011/03/11 21:49:36 hoa Exp $ + */ + +#ifndef MAILSTREAM_H + +#define MAILSTREAM_H + +#ifndef _MSC_VER +# include +#endif + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +LIBETPAN_EXPORT +mailstream * mailstream_new(mailstream_low * low, size_t buffer_size); + +LIBETPAN_EXPORT +ssize_t mailstream_write(mailstream * s, const void * buf, size_t count); + +LIBETPAN_EXPORT +ssize_t mailstream_read(mailstream * s, void * buf, size_t count); + +LIBETPAN_EXPORT +int mailstream_close(mailstream * s); + +LIBETPAN_EXPORT +int mailstream_flush(mailstream * s); + +LIBETPAN_EXPORT +ssize_t mailstream_feed_read_buffer(mailstream * s); + +LIBETPAN_EXPORT +void mailstream_log_error(mailstream * s, char * buf, size_t count); + +LIBETPAN_EXPORT +mailstream_low * mailstream_get_low(mailstream * s); + +LIBETPAN_EXPORT +void mailstream_set_low(mailstream * s, mailstream_low * low); + +LIBETPAN_EXPORT +void mailstream_cancel(mailstream * s); + +LIBETPAN_EXPORT +void mailstream_set_privacy(mailstream * s, int can_be_public); + +#ifdef LIBETPAN_MAILSTREAM_DEBUG +LIBETPAN_EXPORT +extern int mailstream_debug; + +/* direction is 1 for send, 0 for receive, -1 when it does not apply */ +LIBETPAN_EXPORT +extern void (* mailstream_logger)(int direction, + const char * str, size_t size); +LIBETPAN_EXPORT +extern void (* mailstream_logger_id)(mailstream_low * s, int is_stream_data, int direction, + const char * str, size_t size); +#endif + +LIBETPAN_EXPORT +void mailstream_set_logger(mailstream * s, void (* logger)(mailstream * s, int log_type, + const char * str, size_t size, void * context), void * logger_context); + +/* can be run in thread */ +LIBETPAN_EXPORT +int mailstream_wait_idle(mailstream * s, int max_idle_delay); + +/* in main thread */ +LIBETPAN_EXPORT +int mailstream_setup_idle(mailstream * s); + +LIBETPAN_EXPORT +void mailstream_unsetup_idle(mailstream * s); + +LIBETPAN_EXPORT +void mailstream_interrupt_idle(mailstream * s); + +/* Get certificate chain. Returns an array of MMAPString containing DER data or NULL if it's not a SSL connection */ +LIBETPAN_EXPORT +carray * mailstream_get_certificate_chain(mailstream * s); + +LIBETPAN_EXPORT +void mailstream_certificate_chain_free(carray * certificate_chain); + +#define LIBETPAN_MAILSTREAM_NETWORK_DELAY +LIBETPAN_EXPORT +extern struct timeval mailstream_network_delay; + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Sources/libetpan/data-types/mailstream_cancel.c b/Sources/libetpan/data-types/mailstream_cancel.c new file mode 100644 index 00000000..9520d0ed --- /dev/null +++ b/Sources/libetpan/data-types/mailstream_cancel.c @@ -0,0 +1,216 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#define HAVE_CONFIG_H 1 + +#include "mailstream_cancel.h" + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef WIN32 +# include +#endif + +#ifdef LIBETPAN_REENTRANT +# ifndef WIN32 +# include +# endif +#endif + +#include +#ifdef HAVE_UNISTD_H +# include +#endif + +#ifdef WIN32 +# include +# include +#endif + +#ifdef LIBETPAN_REENTRANT +# ifdef WIN32 +# define MUTEX_KEY CRITICAL_SECTION + static int MUTEX_INIT(CRITICAL_SECTION* mutex) { + InitializeCriticalSection( mutex); + return 0; + } +# define MUTEX_LOCK(x) EnterCriticalSection(x) +# define MUTEX_UNLOCK(x) LeaveCriticalSection(x) +# define MUTEX_DESTROY(x) DeleteCriticalSection(x); +# else +# define MUTEX_KEY pthread_mutex_t +# define MUTEX_INIT(x) pthread_mutex_init(x, NULL) +# define MUTEX_DESTROY(x) pthread_mutex_destroy(x); +# define MUTEX_LOCK(x) pthread_mutex_lock(x) +# define MUTEX_UNLOCK(x) pthread_mutex_unlock(x) +# endif +#else +# define MUTEX_INIT(x) +# define MUTEX_DESTROY(x) +# define MUTEX_LOCK(x) +# define MUTEX_UNLOCK(x) +#endif + +struct mailstream_cancel_internal { +#ifdef LIBETPAN_REENTRANT + MUTEX_KEY ms_lock; +#endif +#ifdef WIN32 + HANDLE event; +#endif +}; + +struct mailstream_cancel * mailstream_cancel_new(void) +{ + int r; + struct mailstream_cancel * cancel; + struct mailstream_cancel_internal * ms_internal; + + cancel = malloc(sizeof(struct mailstream_cancel)); + if (cancel == NULL) + goto err; + + cancel->ms_cancelled = 0; + + ms_internal = malloc(sizeof(* ms_internal)); + if (ms_internal == NULL) + goto free; + cancel->ms_internal = ms_internal; + +#ifndef WIN32 + r = pipe(cancel->ms_fds); + if (r < 0) + goto free_internal; +#else + ms_internal->event = CreateEvent(NULL, TRUE, FALSE, NULL); + if (ms_internal->event == NULL) + goto free_internal; +#endif + +#ifdef LIBETPAN_REENTRANT + r = MUTEX_INIT(&ms_internal->ms_lock); + if (r != 0) + goto close_pipe; +#endif + + return cancel; + + close_pipe: +#ifndef WIN32 + close(cancel->ms_fds[0]); + close(cancel->ms_fds[1]); +#else + CloseHandle(ms_internal->event); +#endif + free_internal: + free(cancel->ms_internal); + free: + free(cancel); + err: + return NULL; +} + +void mailstream_cancel_free(struct mailstream_cancel * cancel) +{ + struct mailstream_cancel_internal * ms_internal; + + ms_internal = cancel->ms_internal; + + MUTEX_DESTROY(&ms_internal->ms_lock); + +#ifndef WIN32 + close(cancel->ms_fds[0]); + close(cancel->ms_fds[1]); +#else + CloseHandle(ms_internal->event); +#endif + free(cancel->ms_internal); + free(cancel); +} + +void mailstream_cancel_notify(struct mailstream_cancel * cancel) +{ + char ch; + struct mailstream_cancel_internal * ms_internal; + + ms_internal = cancel->ms_internal; + MUTEX_LOCK(&ms_internal->ms_lock); + + cancel->ms_cancelled = 1; + + MUTEX_UNLOCK(&ms_internal->ms_lock); + + ch = 0; +#ifndef WIN32 + write(cancel->ms_fds[1], &ch, 1); +#else + SetEvent(ms_internal->event); +#endif +} + +void mailstream_cancel_ack(struct mailstream_cancel * cancel) +{ +#ifndef WIN32 + char ch; + read(cancel->ms_fds[0], &ch, 1); +#endif +} + +int mailstream_cancel_cancelled(struct mailstream_cancel * cancel) +{ + int cancelled; + struct mailstream_cancel_internal * ms_internal; + + ms_internal = cancel->ms_internal; + + MUTEX_LOCK(&ms_internal->ms_lock); + + cancelled = cancel->ms_cancelled; + + MUTEX_UNLOCK(&ms_internal->ms_lock); + + + return cancelled; +} + +int mailstream_cancel_get_fd(struct mailstream_cancel * cancel) +{ +#ifndef WIN32 + return cancel->ms_fds[0]; +#else + struct mailstream_cancel_internal * ms_internal; + + ms_internal = cancel->ms_internal; + + return ms_internal->event; +#endif +} diff --git a/Sources/libetpan/data-types/mailstream_cancel.h b/Sources/libetpan/data-types/mailstream_cancel.h new file mode 100644 index 00000000..b492fb52 --- /dev/null +++ b/Sources/libetpan/data-types/mailstream_cancel.h @@ -0,0 +1,45 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILSTREAM_CANCEL_H + +#define MAILSTREAM_CANCEL_H + +#include "mailstream_cancel_types.h" + +struct mailstream_cancel * mailstream_cancel_new(void); +void mailstream_cancel_free(struct mailstream_cancel * cancel); + +int mailstream_cancel_cancelled(struct mailstream_cancel * cancel); +void mailstream_cancel_notify(struct mailstream_cancel * cancel); +void mailstream_cancel_ack(struct mailstream_cancel * cancel); +int mailstream_cancel_get_fd(struct mailstream_cancel * cancel); + +#endif diff --git a/Sources/libetpan/data-types/mailstream_cancel_types.h b/Sources/libetpan/data-types/mailstream_cancel_types.h new file mode 100644 index 00000000..723162e3 --- /dev/null +++ b/Sources/libetpan/data-types/mailstream_cancel_types.h @@ -0,0 +1,41 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILSTREAM_CANCEL_TYPES_H + +#define MAILSTREAM_CANCEL_TYPES_H + +struct mailstream_cancel { + int ms_cancelled; + int ms_fds[2]; + void * ms_internal; +}; + +#endif diff --git a/Sources/libetpan/data-types/mailstream_cfstream.c b/Sources/libetpan/data-types/mailstream_cfstream.c new file mode 100644 index 00000000..c473d5b9 --- /dev/null +++ b/Sources/libetpan/data-types/mailstream_cfstream.c @@ -0,0 +1,1276 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#define HAVE_CFNETWORK 1 +#define LIBETPAN_IOS_DISABLE_SSL 1 + +#include "mailstream_cfstream.h" + +#if HAVE_CFNETWORK +#include +#include +#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR || TARGET_OS_UIKITFORMAC || TARGET_OS_MACCATALYST +#include +#include +#else +#include +#endif +#endif + +#ifndef WIN32 +#include +#endif +//#define LIBETPAN_IOS_DISABLE_SSL 1 +#if LIBETPAN_IOS_DISABLE_SSL && HAVE_CFNETWORK +#define CFSTREAM_ENABLED_DEFAULT 1 +#else +#define CFSTREAM_ENABLED_DEFAULT 0 +#endif + +//#define HAVE_CFNETWORK 1 +//#define CFSTREAM_ENABLED_DEFAULT 1 + +LIBETPAN_EXPORT +int mailstream_cfstream_enabled = CFSTREAM_ENABLED_DEFAULT; + +LIBETPAN_EXPORT +int mailstream_cfstream_voip_enabled = 0; + +enum { + STATE_NONE, + STATE_WAIT_OPEN, + STATE_OPEN_READ_DONE, + STATE_OPEN_WRITE_DONE, + STATE_OPEN_READ_WRITE_DONE, + STATE_OPEN_WRITE_READ_DONE, + STATE_WAIT_READ, + STATE_READ_DONE, + STATE_WAIT_WRITE, + STATE_WRITE_DONE, + STATE_WAIT_IDLE, + STATE_IDLE_DONE, + STATE_WAIT_SSL, + STATE_SSL_READ_DONE, + STATE_SSL_WRITE_DONE, + STATE_SSL_READ_WRITE_DONE, + STATE_SSL_WRITE_READ_DONE +}; + +#if HAVE_CFNETWORK +struct mailstream_cfstream_data { + int state; + CFStreamClientContext streamContext; + + CFReadStreamRef readStream; + void * readBuffer; + size_t readBufferSize; + ssize_t readResult; + int readOpenResult; + int readSSLResult; + + CFWriteStreamRef writeStream; + const void * writeBuffer; + size_t writeBufferSize; + ssize_t writeResult; + int writeOpenResult; + int writeSSLResult; + + Boolean cancelled; + CFRunLoopSourceRef cancelSource; + CFRunLoopSourceContext cancelContext; + + Boolean idleInterrupted; + CFRunLoopSourceRef idleInterruptedSource; + CFRunLoopSourceContext idleInterruptedContext; + int idleMaxDelay; + + CFRunLoopRef runloop; + pthread_mutex_t runloop_lock; + + int ssl_enabled; + int ssl_level; + int ssl_is_server; + char * ssl_peer_name; + int ssl_certificate_verification_mask; +}; +#endif + +/* data */ + +#if HAVE_CFNETWORK +static int low_open(mailstream_low * s); +static void cfstream_data_close(struct mailstream_cfstream_data * socket_data); +#endif + +/* mailstream_low, socket */ + +static int mailstream_low_cfstream_close(mailstream_low * s); +static ssize_t mailstream_low_cfstream_read(mailstream_low * s, + void * buf, size_t count); +static ssize_t mailstream_low_cfstream_write(mailstream_low * s, + const void * buf, size_t count); +static void mailstream_low_cfstream_free(mailstream_low * s); +static int mailstream_low_cfstream_get_fd(mailstream_low * s); +static void mailstream_low_cfstream_cancel(mailstream_low * s); +static carray * mailstream_low_cfstream_get_certificate_chain(mailstream_low * s); + +static int mailstream_low_cfstream_setup_idle(mailstream_low * s); +static int mailstream_low_cfstream_unsetup_idle(mailstream_low * s); +static int mailstream_low_cfstream_interrupt_idle(mailstream_low * s); + +static mailstream_low_driver local_mailstream_cfstream_driver = { + /* mailstream_read */ mailstream_low_cfstream_read, + /* mailstream_write */ mailstream_low_cfstream_write, + /* mailstream_close */ mailstream_low_cfstream_close, + /* mailstream_get_fd */ mailstream_low_cfstream_get_fd, + /* mailstream_free */ mailstream_low_cfstream_free, + /* mailstream_cancel */ mailstream_low_cfstream_cancel, + /* mailstream_get_cancel */ NULL, + /* mailstream_get_certificate_chain */ mailstream_low_cfstream_get_certificate_chain, + /* mailstream_setup_idle */ mailstream_low_cfstream_setup_idle, + /* mailstream_unsetup_idle */ mailstream_low_cfstream_unsetup_idle, + /* mailstream_interrupt_idle */ mailstream_low_cfstream_interrupt_idle, +}; + +mailstream_low_driver * mailstream_cfstream_driver = +&local_mailstream_cfstream_driver; + +#if HAVE_CFNETWORK +static struct mailstream_cfstream_data * cfstream_data_new(CFReadStreamRef readStream, CFWriteStreamRef writeStream) +{ + struct mailstream_cfstream_data * cfstream_data; + + cfstream_data = (struct mailstream_cfstream_data * ) malloc(sizeof(* cfstream_data)); + memset(cfstream_data, 0, sizeof(* cfstream_data)); + cfstream_data->readStream = (CFReadStreamRef) CFRetain(readStream); + cfstream_data->writeStream = (CFWriteStreamRef) CFRetain(writeStream); + cfstream_data->ssl_level = MAILSTREAM_CFSTREAM_SSL_LEVEL_NEGOCIATED_SSL; + pthread_mutex_init(&cfstream_data->runloop_lock, NULL); + + return cfstream_data; +} + +static void cfstream_data_free(struct mailstream_cfstream_data * cfstream_data) +{ + cfstream_data_close(cfstream_data); + pthread_mutex_destroy(&cfstream_data->runloop_lock); + free(cfstream_data->ssl_peer_name); + free(cfstream_data); +} + +static void cfstream_data_close(struct mailstream_cfstream_data * cfstream_data) +{ + if (cfstream_data->writeStream != NULL) { + CFWriteStreamSetClient(cfstream_data->writeStream, kCFStreamEventNone, NULL, NULL); + CFWriteStreamClose(cfstream_data->writeStream); + CFRelease(cfstream_data->writeStream); + cfstream_data->writeStream = NULL; + } + if (cfstream_data->readStream != NULL) { + CFReadStreamSetClient(cfstream_data->readStream, kCFStreamEventNone, NULL, NULL); + CFReadStreamClose(cfstream_data->readStream); + CFRelease(cfstream_data->readStream); + cfstream_data->readStream = NULL; + } +} +#endif + +mailstream * mailstream_cfstream_open(const char * hostname, int16_t port) +{ + return mailstream_cfstream_open_voip_timeout(hostname, port, 0, 0); +} + +mailstream * mailstream_cfstream_open_timeout(const char * hostname, int16_t port, time_t timeout) +{ + return mailstream_cfstream_open_voip_timeout(hostname, port, 0, timeout); +} + +mailstream * mailstream_cfstream_open_voip(const char * hostname, int16_t port, int voip_enabled) +{ + return mailstream_cfstream_open_voip_timeout(hostname, port, voip_enabled, 0); +} + +mailstream * mailstream_cfstream_open_voip_timeout(const char * hostname, int16_t port, int voip_enabled, + time_t timeout) +{ +#if HAVE_CFNETWORK + mailstream_low * low; + mailstream * s; + + low = mailstream_low_cfstream_open_voip_timeout(hostname, port, voip_enabled, timeout); + if (low == NULL) { + return NULL; + } + s = mailstream_new(low, 8192); + return s; +#else + return NULL; +#endif +} + +#if HAVE_CFNETWORK +static void cancelPerform(void *info) +{ + struct mailstream_cfstream_data * cfstream_data; + mailstream_low * s; + + //fprintf(stderr, "cancelled\n"); + + s = info; + cfstream_data = (struct mailstream_cfstream_data *) s->data; + cfstream_data->cancelled = true; +} + +static void readDataFromStream(mailstream_low * s) +{ + struct mailstream_cfstream_data * cfstream_data; + + cfstream_data = (struct mailstream_cfstream_data *) s->data; + + cfstream_data->readResult = CFReadStreamRead(cfstream_data->readStream, + cfstream_data->readBuffer, + cfstream_data->readBufferSize); + //fprintf(stderr, "data read %i\n", (int) cfstream_data->readResult); +} + +static void writeDataToStream(mailstream_low * s) +{ + struct mailstream_cfstream_data * cfstream_data; + + cfstream_data = (struct mailstream_cfstream_data *) s->data; + + cfstream_data->writeResult = CFWriteStreamWrite(cfstream_data->writeStream, + cfstream_data->writeBuffer, + cfstream_data->writeBufferSize); + //fprintf(stderr, "data written %i\n", (int) cfstream_data->writeResult); +} + +static void readStreamCallback(CFReadStreamRef stream, CFStreamEventType eventType, void *clientCallBackInfo) +{ + mailstream_low * s; + struct mailstream_cfstream_data * cfstream_data; + + s = (mailstream_low *) clientCallBackInfo; + cfstream_data = (struct mailstream_cfstream_data *) s->data; + + switch (eventType) { + case kCFStreamEventNone: + break; + case kCFStreamEventOpenCompleted: + cfstream_data->readResult = 0; + cfstream_data->readOpenResult = 0; + switch (cfstream_data->state) { + case STATE_WAIT_OPEN: + cfstream_data->state = STATE_OPEN_READ_DONE; + break; + case STATE_OPEN_WRITE_DONE: + cfstream_data->state = STATE_OPEN_WRITE_READ_DONE; + break; + } + break; + case kCFStreamEventHasBytesAvailable: + cfstream_data->readSSLResult = 0; + switch (cfstream_data->state) { + case STATE_WAIT_READ: + //fprintf(stderr, "has data\n"); + readDataFromStream(s); + cfstream_data->state = STATE_READ_DONE; + break; + case STATE_WAIT_IDLE: + cfstream_data->state = STATE_IDLE_DONE; + break; + case STATE_WAIT_SSL: + cfstream_data->state = STATE_SSL_READ_DONE; + break; + case STATE_SSL_WRITE_DONE: + cfstream_data->state = STATE_SSL_WRITE_READ_DONE; + break; + } + break; + case kCFStreamEventCanAcceptBytes: + break; + case kCFStreamEventErrorOccurred: + cfstream_data->readResult = -1; + cfstream_data->readOpenResult = -1; + cfstream_data->readSSLResult = -1; + switch (cfstream_data->state) { + case STATE_WAIT_OPEN: + cfstream_data->state = STATE_OPEN_READ_DONE; + break; + case STATE_OPEN_WRITE_DONE: + cfstream_data->state = STATE_OPEN_WRITE_READ_DONE; + break; + case STATE_WAIT_READ: + //fprintf(stderr, "error read\n"); + cfstream_data->state = STATE_READ_DONE; + break; + case STATE_WAIT_IDLE: + cfstream_data->state = STATE_IDLE_DONE; + break; + case STATE_WAIT_SSL: + cfstream_data->state = STATE_SSL_READ_DONE; + break; + case STATE_SSL_WRITE_DONE: + cfstream_data->state = STATE_SSL_WRITE_READ_DONE; + break; + } + break; + case kCFStreamEventEndEncountered: + cfstream_data->readResult = 0; + cfstream_data->readOpenResult = 0; + cfstream_data->readSSLResult = 0; + switch (cfstream_data->state) { + case STATE_WAIT_OPEN: + cfstream_data->state = STATE_OPEN_READ_DONE; + break; + case STATE_OPEN_WRITE_DONE: + cfstream_data->state = STATE_OPEN_WRITE_READ_DONE; + break; + case STATE_WAIT_READ: + //fprintf(stderr, "end read\n"); + cfstream_data->state = STATE_READ_DONE; + break; + case STATE_WAIT_IDLE: + cfstream_data->state = STATE_IDLE_DONE; + break; + } + break; + } +} + +static void writeStreamCallback(CFWriteStreamRef stream, CFStreamEventType eventType, void *clientCallBackInfo) +{ + mailstream_low * s; + struct mailstream_cfstream_data * cfstream_data; + + s = (mailstream_low *) clientCallBackInfo; + cfstream_data = (struct mailstream_cfstream_data *) s->data; + + switch (eventType) { + case kCFStreamEventNone: + break; + case kCFStreamEventOpenCompleted: + cfstream_data->writeResult = 0; + cfstream_data->writeOpenResult = 0; + switch (cfstream_data->state) { + case STATE_WAIT_OPEN: + cfstream_data->state = STATE_OPEN_WRITE_DONE; + break; + case STATE_OPEN_READ_DONE: + cfstream_data->state = STATE_OPEN_READ_WRITE_DONE; + break; + } + break; + case kCFStreamEventHasBytesAvailable: + break; + case kCFStreamEventCanAcceptBytes: + //fprintf(stderr, "can accept\n"); + cfstream_data->writeSSLResult = 0; + switch (cfstream_data->state) { + case STATE_WAIT_WRITE: + writeDataToStream(s); + cfstream_data->state = STATE_WRITE_DONE; + break; + case STATE_WAIT_SSL: + cfstream_data->state = STATE_SSL_WRITE_DONE; + break; + case STATE_SSL_READ_DONE: + cfstream_data->state = STATE_SSL_READ_WRITE_DONE; + break; + } + break; + case kCFStreamEventErrorOccurred: + cfstream_data->writeResult = -1; + cfstream_data->writeOpenResult = -1; + cfstream_data->writeSSLResult = -1; + switch (cfstream_data->state) { + case STATE_WAIT_OPEN: + cfstream_data->state = STATE_OPEN_WRITE_DONE; + break; + case STATE_OPEN_READ_DONE: + cfstream_data->state = STATE_OPEN_READ_WRITE_DONE; + break; + case STATE_WAIT_WRITE: + cfstream_data->state = STATE_OPEN_WRITE_DONE; + break; + case STATE_WAIT_SSL: + cfstream_data->state = STATE_SSL_WRITE_DONE; + break; + case STATE_SSL_READ_DONE: + cfstream_data->state = STATE_SSL_READ_WRITE_DONE; + break; + } + break; + case kCFStreamEventEndEncountered: + cfstream_data->writeResult = -1; + cfstream_data->writeOpenResult = -1; + cfstream_data->writeSSLResult = -1; + switch (cfstream_data->state) { + case STATE_WAIT_OPEN: + cfstream_data->state = STATE_OPEN_WRITE_DONE; + break; + case STATE_OPEN_READ_DONE: + cfstream_data->state = STATE_OPEN_READ_WRITE_DONE; + break; + case STATE_WAIT_WRITE: + cfstream_data->state = STATE_OPEN_WRITE_DONE; + break; + } + break; + } +} +#endif + +mailstream_low * mailstream_low_cfstream_open(const char * hostname, int16_t port) +{ + return mailstream_low_cfstream_open_voip_timeout(hostname, port, mailstream_cfstream_voip_enabled, 0); +} + +mailstream_low * mailstream_low_cfstream_open_timeout(const char * hostname, int16_t port, + time_t timeout) +{ + return mailstream_low_cfstream_open_voip_timeout(hostname, port, + mailstream_cfstream_voip_enabled, timeout); +} + +mailstream_low * mailstream_low_cfstream_open_voip(const char * hostname, int16_t port, int voip_enabled) +{ + return mailstream_low_cfstream_open_voip_timeout(hostname, port, voip_enabled, 0); +} + +#if HAVE_CFNETWORK +static int numberIntValue(CFNumberRef nb) +{ + if (nb == NULL) { + return 0; + } + + int result; + CFNumberGetValue(nb, kCFNumberIntType, &result); + return result; +} +#endif + +mailstream_low * mailstream_low_cfstream_open_voip_timeout(const char * hostname, int16_t port, + int voip_enabled, time_t timeout) +{ +#if HAVE_CFNETWORK + mailstream_low * s; + struct mailstream_cfstream_data * cfstream_data; + CFReadStreamRef readStream; + CFWriteStreamRef writeStream; + CFStringRef hostString; + CFOptionFlags readFlags; + CFOptionFlags writeFlags; + int r; + + hostString = CFStringCreateWithCString(NULL, hostname, kCFStringEncodingUTF8); + CFStreamCreatePairWithSocketToHost(NULL, hostString, port, &readStream, &writeStream); + CFRelease(hostString); + +#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR + if (voip_enabled) { + CFReadStreamSetProperty(readStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP); + CFWriteStreamSetProperty(writeStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP); + } +#endif + +#if !TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR + CFDictionaryRef proxySettings = CFNetworkCopySystemProxySettings(); + CFNumberRef nbEnabled = CFDictionaryGetValue(proxySettings, kCFNetworkProxiesSOCKSEnable); + if (numberIntValue(nbEnabled)) { + CFReadStreamSetProperty(readStream, kCFStreamPropertySOCKSProxy, proxySettings); + CFWriteStreamSetProperty(writeStream, kCFStreamPropertySOCKSProxy, proxySettings); + } + CFRelease(proxySettings); +#endif + + cfstream_data = cfstream_data_new(readStream, writeStream); + s = mailstream_low_new(cfstream_data, mailstream_cfstream_driver); + mailstream_low_set_timeout(s, timeout); + + //fprintf(stderr, "open %s %i -> %p\n", hostname, port, s); + + /* setup streams */ + cfstream_data->streamContext.info = s; + + readFlags = kCFStreamEventOpenCompleted | + kCFStreamEventHasBytesAvailable | + kCFStreamEventErrorOccurred | + kCFStreamEventEndEncountered; + + writeFlags = kCFStreamEventOpenCompleted | + kCFStreamEventCanAcceptBytes | + kCFStreamEventErrorOccurred | + kCFStreamEventEndEncountered; + + CFReadStreamSetClient(cfstream_data->readStream, readFlags, readStreamCallback, &cfstream_data->streamContext); + CFWriteStreamSetClient(cfstream_data->writeStream, writeFlags, writeStreamCallback, &cfstream_data->streamContext); + + CFRelease(readStream); + CFRelease(writeStream); + readStream = NULL; + writeStream = NULL; + + /* setup cancel */ + cfstream_data->cancelContext.info = s; + cfstream_data->cancelContext.perform = cancelPerform; + cfstream_data->cancelSource = CFRunLoopSourceCreate(NULL, 0, &cfstream_data->cancelContext); + + r = low_open(s); + if (r < 0) { + mailstream_low_cfstream_close(s); + return NULL; + } + + return s; +#else + return NULL; +#endif +} + + +static int mailstream_low_cfstream_close(mailstream_low * s) +{ +#if HAVE_CFNETWORK + struct mailstream_cfstream_data * cfstream_data; + + cfstream_data = (struct mailstream_cfstream_data *) s->data; + + if (cfstream_data->cancelSource != NULL) { + CFRelease(cfstream_data->cancelSource); + cfstream_data->cancelSource = NULL; + } + + cfstream_data_close(cfstream_data); + + return 0; +#else + return 0; +#endif +} + +static void mailstream_low_cfstream_free(mailstream_low * s) +{ +#if HAVE_CFNETWORK + struct mailstream_cfstream_data * cfstream_data; + + cfstream_data = (struct mailstream_cfstream_data *) s->data; + cfstream_data_free(cfstream_data); + s->data = NULL; + + free(s); +#endif +} + +static int mailstream_low_cfstream_get_fd(mailstream_low * s) +{ +#if HAVE_CFNETWORK + struct mailstream_cfstream_data * cfstream_data = NULL; + CFDataRef native_handle_data = NULL; + CFSocketNativeHandle native_handle_value = -1; + CFIndex native_data_len = 0; + CFIndex native_value_len = 0; + + if (!s) + return -1; + + cfstream_data = (struct mailstream_cfstream_data *) s->data; + + if (!cfstream_data->readStream) + return -1; + + native_handle_data = (CFDataRef)CFReadStreamCopyProperty(cfstream_data->readStream, kCFStreamPropertySocketNativeHandle); + if (!native_handle_data) + return -1; + + native_data_len = CFDataGetLength(native_handle_data); + native_value_len = (CFIndex)sizeof(native_handle_value); + + if (native_data_len != native_value_len) { + CFRelease(native_handle_data); + return -1; + } + + CFDataGetBytes(native_handle_data, CFRangeMake(0, MIN(native_data_len, native_value_len)), (UInt8 *)&native_handle_value); + CFRelease(native_handle_data); + + return native_handle_value; +#else + return -1; +#endif +} + +#if HAVE_CFNETWORK +static void setup_runloop(mailstream_low * s) +{ + struct mailstream_cfstream_data * cfstream_data; + + cfstream_data = (struct mailstream_cfstream_data *) s->data; + + pthread_mutex_lock(&cfstream_data->runloop_lock); + + cfstream_data->runloop = (CFRunLoopRef) CFRetain(CFRunLoopGetCurrent()); + if (cfstream_data->cancelSource != NULL) { + CFRunLoopAddSource(cfstream_data->runloop, cfstream_data->cancelSource, kCFRunLoopDefaultMode); + //fprintf(stderr, "add cancel source %p\n", cfstream_data->cancelSource); + } + if (cfstream_data->idleInterruptedSource != NULL) { + CFRunLoopAddSource(cfstream_data->runloop, cfstream_data->idleInterruptedSource, kCFRunLoopDefaultMode); + //fprintf(stderr, "add idle source %p\n", cfstream_data->idleInterruptedSource); + } + + pthread_mutex_unlock(&cfstream_data->runloop_lock); +} + +static void unsetup_runloop(mailstream_low * s) +{ + struct mailstream_cfstream_data * cfstream_data; + + cfstream_data = (struct mailstream_cfstream_data *) s->data; + + pthread_mutex_lock(&cfstream_data->runloop_lock); + + if (cfstream_data->idleInterruptedSource != NULL) { + CFRunLoopRemoveSource(cfstream_data->runloop, cfstream_data->idleInterruptedSource, kCFRunLoopDefaultMode); + } + if (cfstream_data->cancelSource != NULL) { + CFRunLoopRemoveSource(cfstream_data->runloop, cfstream_data->cancelSource, kCFRunLoopDefaultMode); + } + if (cfstream_data->runloop != NULL) { + CFRelease(cfstream_data->runloop); + cfstream_data->runloop = NULL; + } + + + pthread_mutex_unlock(&cfstream_data->runloop_lock); +} + +enum { + WAIT_RUNLOOP_EXIT_NO_ERROR, + WAIT_RUNLOOP_EXIT_INTERRUPTED, + WAIT_RUNLOOP_EXIT_CANCELLED, + WAIT_RUNLOOP_EXIT_TIMEOUT, +}; + +static int wait_runloop(mailstream_low * s, int wait_state) +{ + struct mailstream_cfstream_data * cfstream_data; + int read_scheduled; + int write_scheduled; + int error; + + setup_runloop(s); + + cfstream_data = (struct mailstream_cfstream_data *) s->data; + cfstream_data->state = wait_state; + + read_scheduled = 0; + write_scheduled = 0; + error = WAIT_RUNLOOP_EXIT_NO_ERROR; + + switch (wait_state) { + case STATE_WAIT_OPEN: + //fprintf(stderr, "wait open\n"); + CFReadStreamScheduleWithRunLoop(cfstream_data->readStream, cfstream_data->runloop, kCFRunLoopDefaultMode); + CFWriteStreamScheduleWithRunLoop(cfstream_data->writeStream, cfstream_data->runloop, kCFRunLoopDefaultMode); + read_scheduled = 1; + write_scheduled = 1; + break; + case STATE_WAIT_READ: + //fprintf(stderr, "wait read\n"); + CFReadStreamScheduleWithRunLoop(cfstream_data->readStream, cfstream_data->runloop, kCFRunLoopDefaultMode); + read_scheduled = 1; + break; + case STATE_WAIT_WRITE: + //fprintf(stderr, "wait write\n"); + CFWriteStreamScheduleWithRunLoop(cfstream_data->writeStream, cfstream_data->runloop, kCFRunLoopDefaultMode); + write_scheduled = 1; + break; + case STATE_WAIT_IDLE: + //fprintf(stderr, "wait idle\n"); + CFReadStreamScheduleWithRunLoop(cfstream_data->readStream, cfstream_data->runloop, kCFRunLoopDefaultMode); + read_scheduled = 1; + break; + case STATE_WAIT_SSL: + //fprintf(stderr, "wait ssl\n"); + CFReadStreamScheduleWithRunLoop(cfstream_data->readStream, cfstream_data->runloop, kCFRunLoopDefaultMode); + CFWriteStreamScheduleWithRunLoop(cfstream_data->writeStream, cfstream_data->runloop, kCFRunLoopDefaultMode); + read_scheduled = 1; + write_scheduled = 1; + break; + } + + if (read_scheduled) { + if (CFReadStreamHasBytesAvailable(cfstream_data->readStream)) { + readStreamCallback(cfstream_data->readStream, kCFStreamEventHasBytesAvailable, s); + } + } + if (write_scheduled) { + if (CFWriteStreamCanAcceptBytes(cfstream_data->writeStream)) { + writeStreamCallback(cfstream_data->writeStream, kCFStreamEventCanAcceptBytes, s); + } + } + + while (1) { + struct timeval timeout; + CFTimeInterval delay; + int r; + int done; + + if (cfstream_data->cancelled) { + error = WAIT_RUNLOOP_EXIT_CANCELLED; + break; + } + if (cfstream_data->state == STATE_WAIT_IDLE) { + if (cfstream_data->idleInterrupted) { + error = WAIT_RUNLOOP_EXIT_INTERRUPTED; + break; + } + } + + done = 0; + switch (cfstream_data->state) { + case STATE_OPEN_READ_DONE: + CFReadStreamUnscheduleFromRunLoop(cfstream_data->readStream, cfstream_data->runloop, kCFRunLoopDefaultMode); + read_scheduled = 0; + break; + case STATE_OPEN_WRITE_DONE: + CFWriteStreamUnscheduleFromRunLoop(cfstream_data->writeStream, cfstream_data->runloop, kCFRunLoopDefaultMode); + write_scheduled = 0; + break; + case STATE_OPEN_READ_WRITE_DONE: + done = 1; + break; + case STATE_OPEN_WRITE_READ_DONE: + done = 1; + break; + case STATE_READ_DONE: + done = 1; + break; + case STATE_WRITE_DONE: + done = 1; + break; + case STATE_IDLE_DONE: + done = 1; + break; + case STATE_SSL_READ_DONE: + done = 1; + break; + case STATE_SSL_WRITE_DONE: + done = 1; + break; + case STATE_SSL_READ_WRITE_DONE: + done = 1; + break; + case STATE_SSL_WRITE_READ_DONE: + done = 1; + break; + } + + if (done) { + break; + } + + if (wait_state == STATE_WAIT_IDLE) { + timeout.tv_sec = cfstream_data->idleMaxDelay; + timeout.tv_usec = 0; + } + else { + if (s->timeout == 0) { + timeout = mailstream_network_delay; + } + else { + timeout.tv_sec = s->timeout; + timeout.tv_usec = 0; + } + } + delay = (CFTimeInterval) timeout.tv_sec + (CFTimeInterval) timeout.tv_usec / (CFTimeInterval) 1e6; + + r = CFRunLoopRunInMode(kCFRunLoopDefaultMode, delay, true); + if (r == kCFRunLoopRunTimedOut) { + error = WAIT_RUNLOOP_EXIT_TIMEOUT; + break; + } + } + + if (read_scheduled) { + CFReadStreamUnscheduleFromRunLoop(cfstream_data->readStream, cfstream_data->runloop, kCFRunLoopDefaultMode); + } + if (write_scheduled) { + CFWriteStreamUnscheduleFromRunLoop(cfstream_data->writeStream, cfstream_data->runloop, kCFRunLoopDefaultMode); + } + + unsetup_runloop(s); + + if (error != WAIT_RUNLOOP_EXIT_NO_ERROR) + return error; + + return WAIT_RUNLOOP_EXIT_NO_ERROR; +} +#endif + +static ssize_t mailstream_low_cfstream_read(mailstream_low * s, + void * buf, size_t count) +{ +#if HAVE_CFNETWORK + struct mailstream_cfstream_data * cfstream_data; + int r; + + cfstream_data = (struct mailstream_cfstream_data *) s->data; + cfstream_data->readBuffer = buf; + cfstream_data->readBufferSize = count; + + if (cfstream_data->cancelled) { + return -1; + } + + if (CFReadStreamGetStatus(cfstream_data->readStream) == kCFStreamStatusError) { + return -1; + } + + if (CFReadStreamHasBytesAvailable(cfstream_data->readStream)) { + readDataFromStream(s); + return cfstream_data->readResult; + } + + r = wait_runloop(s, STATE_WAIT_READ); + if (r != WAIT_RUNLOOP_EXIT_NO_ERROR) { + return -1; + } + + return cfstream_data->readResult; +#else + return -1; +#endif +} + +static ssize_t mailstream_low_cfstream_write(mailstream_low * s, + const void * buf, size_t count) +{ +#if HAVE_CFNETWORK + struct mailstream_cfstream_data * cfstream_data; + int r; + + cfstream_data = (struct mailstream_cfstream_data *) s->data; + cfstream_data->writeBuffer = buf; + cfstream_data->writeBufferSize = count; + + if (cfstream_data->cancelled) + return -1; + + if (CFWriteStreamGetStatus(cfstream_data->writeStream) == kCFStreamStatusError) { + return -1; + } + + if (CFWriteStreamCanAcceptBytes(cfstream_data->writeStream)) { + writeDataToStream(s); + return cfstream_data->writeResult; + } + + r = wait_runloop(s, STATE_WAIT_WRITE); + if (r != WAIT_RUNLOOP_EXIT_NO_ERROR) { + return -1; + } + + return cfstream_data->writeResult; +#else + return -1; +#endif +} + +#if HAVE_CFNETWORK +static int low_open(mailstream_low * s) +{ + struct mailstream_cfstream_data * cfstream_data; + int r; + + cfstream_data = (struct mailstream_cfstream_data *) s->data; + + CFReadStreamOpen(cfstream_data->readStream); + CFWriteStreamOpen(cfstream_data->writeStream); + + r = wait_runloop(s, STATE_WAIT_OPEN); + if (r != WAIT_RUNLOOP_EXIT_NO_ERROR) { + return -1; + } + + if (cfstream_data->writeOpenResult < 0) + return -1; + if (cfstream_data->readOpenResult < 0) + return -1; + + return 0; +} +#endif + +static void mailstream_low_cfstream_cancel(mailstream_low * s) +{ +#if HAVE_CFNETWORK + struct mailstream_cfstream_data * cfstream_data; + + cfstream_data = (struct mailstream_cfstream_data *) s->data; + + pthread_mutex_lock(&cfstream_data->runloop_lock); + + if (cfstream_data->cancelSource != NULL) { + CFRunLoopSourceSignal(cfstream_data->cancelSource); + } + if (cfstream_data->runloop != NULL) { + CFRunLoopWakeUp(cfstream_data->runloop); + } + + pthread_mutex_unlock(&cfstream_data->runloop_lock); +#endif +} + +int mailstream_cfstream_set_ssl_enabled(mailstream * s, int ssl_enabled) +{ +#if HAVE_CFNETWORK + struct mailstream_cfstream_data * cfstream_data; + int r; + CFIndex count; + + cfstream_data = (struct mailstream_cfstream_data *) s->low->data; + cfstream_data->ssl_enabled = ssl_enabled; + if (ssl_enabled) { + CFMutableDictionaryRef settings; + + settings = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + switch (cfstream_data->ssl_level) { + case MAILSTREAM_CFSTREAM_SSL_LEVEL_NONE: + CFDictionarySetValue(settings, kCFStreamSSLLevel, kCFStreamSocketSecurityLevelNone); + break; + case MAILSTREAM_CFSTREAM_SSL_LEVEL_SSLv2: + CFDictionarySetValue(settings, kCFStreamSSLLevel, kCFStreamSocketSecurityLevelSSLv2); + break; + case MAILSTREAM_CFSTREAM_SSL_LEVEL_SSLv3: + CFDictionarySetValue(settings, kCFStreamSSLLevel, kCFStreamSocketSecurityLevelSSLv3); + break; + case MAILSTREAM_CFSTREAM_SSL_LEVEL_TLSv1: + CFDictionarySetValue(settings, kCFStreamSSLLevel, kCFStreamSocketSecurityLevelTLSv1); + break; + case MAILSTREAM_CFSTREAM_SSL_LEVEL_NEGOCIATED_SSL: + CFDictionarySetValue(settings, kCFStreamSSLLevel, kCFStreamSocketSecurityLevelNegotiatedSSL); + break; + } + + if ((cfstream_data->ssl_certificate_verification_mask & MAILSTREAM_CFSTREAM_SSL_ALLOWS_EXPIRED_CERTIFICATES) != 0) { + CFDictionarySetValue(settings, kCFStreamSSLAllowsExpiredCertificates, kCFBooleanTrue); + } + if ((cfstream_data->ssl_certificate_verification_mask & MAILSTREAM_CFSTREAM_SSL_ALLOWS_EXPIRED_ROOTS) != 0) { + CFDictionarySetValue(settings, kCFStreamSSLAllowsExpiredRoots, kCFBooleanTrue); + } + if ((cfstream_data->ssl_certificate_verification_mask & MAILSTREAM_CFSTREAM_SSL_ALLOWS_ANY_ROOT) != 0) { + CFDictionarySetValue(settings, kCFStreamSSLAllowsAnyRoot, kCFBooleanTrue); + } + if ((cfstream_data->ssl_certificate_verification_mask & MAILSTREAM_CFSTREAM_SSL_DISABLE_VALIDATES_CERTIFICATE_CHAIN) != 0) { + CFDictionarySetValue(settings, kCFStreamSSLValidatesCertificateChain, kCFBooleanFalse); + } + + CFReadStreamSetProperty(cfstream_data->readStream, kCFStreamPropertySSLSettings, settings); + CFWriteStreamSetProperty(cfstream_data->writeStream, kCFStreamPropertySSLSettings, settings); + CFRelease(settings); + } + else { + CFMutableDictionaryRef settings; + + settings = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(settings, kCFStreamSSLLevel, kCFStreamSocketSecurityLevelNone); + CFReadStreamSetProperty(cfstream_data->readStream, kCFStreamPropertySSLSettings, settings); + CFWriteStreamSetProperty(cfstream_data->writeStream, kCFStreamPropertySSLSettings, settings); + CFRelease(settings); + } + + // We need to investigate more about how to establish a STARTTLS connection. + // For now, wait until we get the certificate chain. + + CFArrayRef certs; + SecTrustRef secTrust; + while (1) { + r = wait_runloop(s->low, STATE_WAIT_SSL); + if (r != WAIT_RUNLOOP_EXIT_NO_ERROR) { + return -1; + } + if (cfstream_data->writeSSLResult < 0) + return -1; + if (cfstream_data->readSSLResult < 0) + return -1; + + secTrust = (SecTrustRef)CFReadStreamCopyProperty(cfstream_data->readStream, kCFStreamPropertySSLPeerTrust); + if (secTrust) { + // SecTrustEvaluate() needs to be called before SecTrustGetCertificateCount() in Mac OS X <= 10.8 + SecTrustEvaluate(secTrust, NULL); + count = SecTrustGetCertificateCount(secTrust); + CFRelease(secTrust); + } + else { + certs = CFReadStreamCopyProperty(cfstream_data->readStream, kCFStreamPropertySSLPeerCertificates); + if (certs) { + count = CFArrayGetCount(certs); + CFRelease(certs); + } + else { + // No trust and no certs, wait more. + continue; + } + } + + if (count == 0) { + // No certificates, wait more. + continue; + } + + break; + } + + return 0; +#else + return -1; +#endif +} + +int mailstream_cfstream_is_ssl_enabled(mailstream * s) +{ +#if HAVE_CFNETWORK + struct mailstream_cfstream_data * cfstream_data; + cfstream_data = (struct mailstream_cfstream_data *) s->low->data; + return cfstream_data->ssl_enabled; +#else + return 0; +#endif +} + +void mailstream_cfstream_set_ssl_verification_mask(mailstream * s, int verification_mask) +{ +#if HAVE_CFNETWORK + struct mailstream_cfstream_data * cfstream_data; + cfstream_data = (struct mailstream_cfstream_data *) s->low->data; + cfstream_data->ssl_certificate_verification_mask = verification_mask; +#endif +} + +void mailstream_cfstream_set_ssl_peer_name(mailstream * s, const char * peer_name) +{ +#if HAVE_CFNETWORK + struct mailstream_cfstream_data * cfstream_data; + cfstream_data = (struct mailstream_cfstream_data *) s->low->data; + + if (cfstream_data->ssl_peer_name != peer_name) { + free(cfstream_data->ssl_peer_name); + cfstream_data->ssl_peer_name = NULL; + if (peer_name != NULL) { + cfstream_data->ssl_peer_name = strdup(peer_name); + } + } +#endif +} + +void mailstream_cfstream_set_ssl_is_server(mailstream * s, int is_server) +{ +#if HAVE_CFNETWORK + struct mailstream_cfstream_data * cfstream_data; + cfstream_data = (struct mailstream_cfstream_data *) s->low->data; + cfstream_data->ssl_is_server = is_server; +#endif +} + +void mailstream_cfstream_set_ssl_level(mailstream * s, int ssl_level) +{ +#if HAVE_CFNETWORK + struct mailstream_cfstream_data * cfstream_data; + cfstream_data = (struct mailstream_cfstream_data *) s->low->data; + cfstream_data->ssl_level = ssl_level; +#endif +} + +int mailstream_cfstream_wait_idle(mailstream * s, int max_idle_delay) +{ + return mailstream_low_cfstream_wait_idle(s->low, max_idle_delay); +} + +int mailstream_low_cfstream_wait_idle(mailstream_low * low, int max_idle_delay) +{ +#if HAVE_CFNETWORK + struct mailstream_cfstream_data * cfstream_data; + int r; + + cfstream_data = (struct mailstream_cfstream_data *) low->data; + cfstream_data->idleMaxDelay = max_idle_delay; + + r = wait_runloop(low, STATE_WAIT_IDLE); + switch (r) { + case WAIT_RUNLOOP_EXIT_TIMEOUT: + return MAILSTREAM_IDLE_TIMEOUT; + case WAIT_RUNLOOP_EXIT_INTERRUPTED: + return MAILSTREAM_IDLE_INTERRUPTED; + case WAIT_RUNLOOP_EXIT_CANCELLED: + return MAILSTREAM_IDLE_CANCELLED; + } + return MAILSTREAM_IDLE_HASDATA; +#else + return MAILSTREAM_IDLE_ERROR; +#endif +} + +#if HAVE_CFNETWORK +static void idleInterruptedPerform(void *info) +{ + struct mailstream_cfstream_data * cfstream_data; + mailstream_low * s; + + s = info; + + cfstream_data = (struct mailstream_cfstream_data *) s->data; + cfstream_data->idleInterrupted = true; +} +#endif + +static int mailstream_low_cfstream_setup_idle(mailstream_low * s) +{ +#if HAVE_CFNETWORK + struct mailstream_cfstream_data * cfstream_data; + + cfstream_data = (struct mailstream_cfstream_data *) s->data; + cfstream_data->idleInterrupted = false; + cfstream_data->idleInterruptedContext.info = s; + cfstream_data->idleInterruptedContext.perform = idleInterruptedPerform; + cfstream_data->idleInterruptedSource = CFRunLoopSourceCreate(NULL, 0, &cfstream_data->idleInterruptedContext); + return 0; +#else + return -1; +#endif +} + +static int mailstream_low_cfstream_unsetup_idle(mailstream_low * s) +{ +#if HAVE_CFNETWORK + struct mailstream_cfstream_data * cfstream_data; + + cfstream_data = (struct mailstream_cfstream_data *) s->data; + if (cfstream_data->idleInterruptedSource != NULL) { + CFRelease(cfstream_data->idleInterruptedSource); + cfstream_data->idleInterruptedSource = NULL; + } + return 0; +#else + return -1; +#endif +} + +static int mailstream_low_cfstream_interrupt_idle(mailstream_low * s) +{ +#if HAVE_CFNETWORK + struct mailstream_cfstream_data * cfstream_data; + + cfstream_data = (struct mailstream_cfstream_data *) s->data; + + pthread_mutex_lock(&cfstream_data->runloop_lock); + + if (cfstream_data->idleInterruptedSource != NULL) { + CFRunLoopSourceSignal(cfstream_data->idleInterruptedSource); + } + if (cfstream_data->runloop != NULL) { + CFRunLoopWakeUp(cfstream_data->runloop); + } + + pthread_mutex_unlock(&cfstream_data->runloop_lock); + return 0; +#else + return -1; +#endif +} + +static carray * mailstream_low_cfstream_get_certificate_chain(mailstream_low * s) +{ +#if HAVE_CFNETWORK + struct mailstream_cfstream_data * cfstream_data; + unsigned int i; + carray * result; + CFArrayRef certs; + CFIndex count; + + cfstream_data = (struct mailstream_cfstream_data *) s->data; + + SecTrustRef secTrust = (SecTrustRef)CFReadStreamCopyProperty(cfstream_data->readStream, kCFStreamPropertySSLPeerTrust); + if (secTrust) { + // SecTrustEvaluate() needs to be called before SecTrustGetCertificateCount() in Mac OS X <= 10.8 + SecTrustEvaluate(secTrust, NULL); + count = SecTrustGetCertificateCount(secTrust); + result = carray_new(4); + for(i = 0 ; i < count ; i ++) { + SecCertificateRef cert = (SecCertificateRef) SecTrustGetCertificateAtIndex(secTrust, i); + CFDataRef data = SecCertificateCopyData(cert); + if (data == NULL) { + carray_free(result); + CFRelease(secTrust); + return NULL; + } + CFIndex length = CFDataGetLength(data); + const UInt8 * bytes = CFDataGetBytePtr(data); + MMAPString * str = mmap_string_sized_new(length); + mmap_string_append_len(str, (char*) bytes, length); + carray_add(result, str, NULL); + CFRelease(data); + } + CFRelease(secTrust); + } + else { + certs = CFReadStreamCopyProperty(cfstream_data->readStream, kCFStreamPropertySSLPeerCertificates); + if (certs) { + count = CFArrayGetCount(certs); + result = carray_new(4); + for(i = 0 ; i < count ; i ++) { + SecCertificateRef cert = (SecCertificateRef) CFArrayGetValueAtIndex(certs, i); + CFDataRef data = SecCertificateCopyData(cert); + if (data == NULL) { + carray_free(result); + CFRelease(certs); + return NULL; + } + CFIndex length = CFDataGetLength(data); + const UInt8 * bytes = CFDataGetBytePtr(data); + MMAPString * str = mmap_string_sized_new(length); + mmap_string_append_len(str, (char*) bytes, length); + carray_add(result, str, NULL); + CFRelease(data); + } + CFRelease(certs); + } + else { + return NULL; + } + } + + return result; +#else + return NULL; +#endif +} diff --git a/Sources/libetpan/data-types/mailstream_cfstream.h b/Sources/libetpan/data-types/mailstream_cfstream.h new file mode 100644 index 00000000..c8c47de6 --- /dev/null +++ b/Sources/libetpan/data-types/mailstream_cfstream.h @@ -0,0 +1,114 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef MAILSTREAM_CFSTREAM_H + +#define MAILSTREAM_CFSTREAM_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + LIBETPAN_EXPORT + extern int mailstream_cfstream_enabled; + + LIBETPAN_EXPORT + extern int mailstream_cfstream_voip_enabled; + + enum { + MAILSTREAM_CFSTREAM_SSL_ALLOWS_EXPIRED_CERTIFICATES = 1 << 0, + MAILSTREAM_CFSTREAM_SSL_ALLOWS_EXPIRED_ROOTS = 1 << 1, + MAILSTREAM_CFSTREAM_SSL_ALLOWS_ANY_ROOT = 1 << 2, + MAILSTREAM_CFSTREAM_SSL_DISABLE_VALIDATES_CERTIFICATE_CHAIN = 1 << 3, + MAILSTREAM_CFSTREAM_SSL_NO_VERIFICATION = MAILSTREAM_CFSTREAM_SSL_ALLOWS_EXPIRED_CERTIFICATES | + MAILSTREAM_CFSTREAM_SSL_ALLOWS_EXPIRED_ROOTS | + MAILSTREAM_CFSTREAM_SSL_ALLOWS_ANY_ROOT | + MAILSTREAM_CFSTREAM_SSL_DISABLE_VALIDATES_CERTIFICATE_CHAIN + }; + + enum { + MAILSTREAM_CFSTREAM_SSL_LEVEL_NONE, + MAILSTREAM_CFSTREAM_SSL_LEVEL_SSLv2, + MAILSTREAM_CFSTREAM_SSL_LEVEL_SSLv3, + MAILSTREAM_CFSTREAM_SSL_LEVEL_TLSv1, + MAILSTREAM_CFSTREAM_SSL_LEVEL_NEGOCIATED_SSL + }; + + /* socket */ + + extern mailstream_low_driver * mailstream_cfstream_driver; + + mailstream * mailstream_cfstream_open(const char * hostname, int16_t port); + mailstream * mailstream_cfstream_open_timeout(const char * hostname, int16_t port, time_t timeout); + mailstream * mailstream_cfstream_open_voip(const char * hostname, int16_t port, int voip_enabled); + mailstream * mailstream_cfstream_open_voip_timeout(const char * hostname, int16_t port, int voip_enabled, + time_t timeout); + + mailstream_low * mailstream_low_cfstream_open(const char * hostname, int16_t port); + mailstream_low * mailstream_low_cfstream_open_timeout(const char * hostname, int16_t port, + time_t timeout); + mailstream_low * mailstream_low_cfstream_open_voip(const char * hostname, int16_t port, int voip_enabled); + mailstream_low * mailstream_low_cfstream_open_voip_timeout(const char * hostname, int16_t port, + int voip_enabled, time_t timeout); + + /* first, set these settings */ + void mailstream_cfstream_set_ssl_verification_mask(mailstream * s, int verification_mask); + void mailstream_cfstream_set_ssl_peer_name(mailstream * s, const char * peer_name); + void mailstream_cfstream_set_ssl_is_server(mailstream * s, int is_server); + void mailstream_cfstream_set_ssl_level(mailstream * s, int ssl_level); + /* missing setting certificate */ + + /* then, enable SSL */ + int mailstream_cfstream_set_ssl_enabled(mailstream * s, int ssl_enabled); + int mailstream_cfstream_is_ssl_enabled(mailstream * s); + + /* support for IMAP IDLE */ + + /* can be run in thread */ + int mailstream_cfstream_wait_idle(mailstream * s, int max_idle_delay); + int mailstream_low_cfstream_wait_idle(mailstream_low * low, int max_idle_delay); + + /* in main thread */ + /* + void mailstream_low_cfstream_setup_idle(mailstream_low * s); + void mailstream_low_cfstream_interrupt_idle(mailstream_low * s); + void mailstream_low_cfstream_unsetup_idle(mailstream_low * s); + */ + /* SSL certificate */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/data-types/mailstream_compress.c b/Sources/libetpan/data-types/mailstream_compress.c new file mode 100644 index 00000000..b29d0ab5 --- /dev/null +++ b/Sources/libetpan/data-types/mailstream_compress.c @@ -0,0 +1,357 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2013 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* Created by Ian Ragsdale on 3/8/13. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailstream_compress.h" + +#include + +#include +#include +#if HAVE_ZLIB +#include +#endif +#include + +#include "mailstream_low.h" +#include "mailstream_cancel.h" + +#define CHUNK_SIZE 1024 + +#ifndef MIN +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#endif + +static ssize_t mailstream_low_compress_read(mailstream_low * s, void * buf, size_t count); +static ssize_t mailstream_low_compress_write(mailstream_low * s, const void * buf, size_t count); +static int mailstream_low_compress_close(mailstream_low * s); +static int mailstream_low_compress_get_fd(mailstream_low * s); +static struct mailstream_cancel * mailstream_low_compress_get_cancel(mailstream_low * s); +static void mailstream_low_compress_free(mailstream_low * s); +static void mailstream_low_compress_cancel(mailstream_low * s); +static carray * mailstream_low_compress_get_certificate_chain(mailstream_low * s); +static int mailstream_low_compress_setup_idle(mailstream_low * low); +static int mailstream_low_compress_unsetup_idle(mailstream_low * low); +static int mailstream_low_compress_interrupt_idle(mailstream_low * low); + +#if HAVE_ZLIB +typedef struct mailstream_compress_data { + mailstream_low * ms; + z_stream *compress_stream; + z_stream *decompress_stream; + unsigned char input_buf[CHUNK_SIZE]; + unsigned char output_buf[CHUNK_SIZE]; +} compress_data; +#endif + +static mailstream_low_driver local_mailstream_compress_driver = { + /* mailstream_read */ mailstream_low_compress_read, + /* mailstream_write */ mailstream_low_compress_write, + /* mailstream_close */ mailstream_low_compress_close, + /* mailstream_get_fd */ mailstream_low_compress_get_fd, + /* mailstream_free */ mailstream_low_compress_free, + /* mailstream_cancel */ mailstream_low_compress_cancel, + /* mailstream_get_cancel */ mailstream_low_compress_get_cancel, + /* mailstream_get_certificate_chain */ mailstream_low_compress_get_certificate_chain, + /* mailstream_setup_idle */ mailstream_low_compress_setup_idle, + /* mailstream_unsetup_idle */ mailstream_low_compress_unsetup_idle, + /* mailstream_interrupt_idle */ mailstream_low_compress_interrupt_idle, +}; + +mailstream_low_driver * mailstream_compress_driver = &local_mailstream_compress_driver; + +mailstream_low * mailstream_low_compress_open(mailstream_low * ms) +{ +#if HAVE_ZLIB + mailstream_low * s; + + /* stores the original mailstream */ + struct mailstream_compress_data * compress_data = calloc(1, sizeof(* compress_data)); + if (compress_data == NULL) + goto err; + + /* allocate deflate state */ + compress_data->compress_stream = malloc(sizeof(z_stream)); + if (compress_data->compress_stream == NULL) { + goto free_compress_data; + } + compress_data->compress_stream->zalloc = Z_NULL; + compress_data->compress_stream->zfree = Z_NULL; + compress_data->compress_stream->opaque = Z_NULL; + /* these specific settings are very important - don't change without looking at the COMPRESS RFC */ + int ret = deflateInit2(compress_data->compress_stream, Z_BEST_SPEED, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); + if (ret != Z_OK) { + goto free_compress_data; + } + compress_data->compress_stream->avail_in = 0; + compress_data->compress_stream->avail_out = 0; + + /* allocate inflate state */ + compress_data->decompress_stream = malloc(sizeof(z_stream)); + if (compress_data->decompress_stream == NULL) { + goto free_compress_data; + } + compress_data->decompress_stream->zalloc = Z_NULL; + compress_data->decompress_stream->zfree = Z_NULL; + compress_data->decompress_stream->opaque = Z_NULL; + /* these specific settings are very important - don't change without looking at the COMPRESS RFC */ + ret = inflateInit2(compress_data->decompress_stream, -15); + if (ret != Z_OK) { + goto free_compress_data; + } + compress_data->decompress_stream->avail_in = 0; + compress_data->decompress_stream->avail_out = 0; + + compress_data->ms = ms; + + s = mailstream_low_new(compress_data, mailstream_compress_driver); + if (s == NULL) + goto free_compress_data; + + return s; + + free_compress_data: + if (compress_data->compress_stream) { + deflateEnd(compress_data->compress_stream); + free(compress_data->compress_stream); + } + if (compress_data->decompress_stream) { + inflateEnd(compress_data->decompress_stream); + free(compress_data->decompress_stream); + } + free(compress_data); + err: + return NULL; +#else + return NULL; +#endif +} + +static ssize_t mailstream_low_compress_read(mailstream_low * s, void * buf, size_t count) +{ +#if HAVE_ZLIB + compress_data * data = s->data; + data->ms->timeout = s->timeout; + z_stream * strm = data->decompress_stream; + + int zr; + + do { + /* if there is no compressed data, read more */ + if (strm->avail_in == 0) { + int read = (int) data->ms->driver->mailstream_read(data->ms, data->input_buf, CHUNK_SIZE); + if (read <= 0) { + return read; + } + strm->avail_in = read; + strm->next_in = data->input_buf; + } + + /* set the output buffer */ + strm->next_out = buf; + strm->avail_out = (int) count; + + /* uncompress any waiting data */ + zr = inflate(strm, Z_NO_FLUSH); + } + /* + it's possible that there was data in the stream, but not enough that zlib could figure + out what to do with it. in this case, read some more and try again. + */ + while (zr == Z_OK && strm->avail_in == 0 && strm->avail_out == count); + + /* if we got an error, return -1 to close the connection */ + if (zr < 0) { + return -1; + } + + /* let the client know how much data was read */ + return count - strm->avail_out; +#else + return -1; +#endif +} + +static ssize_t mailstream_low_compress_write(mailstream_low * s, const void * buf, size_t count) { +#if HAVE_ZLIB + int zr; + //int wr; + compress_data * data = s->data; + data->ms->timeout = s->timeout; + z_stream * strm = data->compress_stream; + + strm->next_in = (Bytef *)buf; + /* we won't try to compress more than CHUNK_SIZE at a time so we always have enough buffer space */ + int compress_len = MIN((int) count, CHUNK_SIZE); + strm->avail_in = compress_len; + strm->avail_out = CHUNK_SIZE; + strm->next_out = data->output_buf; + + zr = deflate(strm, Z_PARTIAL_FLUSH); + if (zr < 0) { + //STREAM_LOG(s, 1, "<<<<<<< Error deflating "); + //STREAM_LOG(s, 1, strm->msg); + //STREAM_LOG(s, 1, " <<<<<<<"); + //STREAM_LOG(s, 1, "\n"); + return -1; + } + + unsigned char * p = data->output_buf; + size_t remaining = CHUNK_SIZE - strm->avail_out; + while (remaining > 0) { + ssize_t wr = data->ms->driver->mailstream_write(data->ms, p, remaining); + if (wr < 0) { + return -1; + } + + p += wr; + remaining -= wr; + } + + /* let the caller know how much data we wrote */ + return compress_len - strm->avail_in; +#else + return -1; +#endif +} + +static int mailstream_low_compress_close(mailstream_low * s) +{ +#if HAVE_ZLIB + compress_data * data = s->data; + return mailstream_low_close(data->ms); +#else + return 0; +#endif +} + +static int mailstream_low_compress_get_fd(mailstream_low * s) +{ +#if HAVE_ZLIB + compress_data * data = s->data; + return data->ms->driver->mailstream_get_fd(data->ms); +#else + return -1; +#endif +} + +static struct mailstream_cancel * mailstream_low_compress_get_cancel(mailstream_low * s) +{ +#if HAVE_ZLIB + compress_data * data = s->data; + return data->ms->driver->mailstream_get_cancel(data->ms); +#else + return NULL; +#endif +} + +static void mailstream_low_compress_free(mailstream_low * s) +{ +#if HAVE_ZLIB + compress_data * data = s->data; + mailstream_low_free(data->ms); + if (data->compress_stream) { + deflateEnd(data->compress_stream); + free(data->compress_stream); + } + if (data->decompress_stream) { + inflateEnd(data->decompress_stream); + free(data->decompress_stream); + } + free(data); + free(s); +#endif +} + +static void mailstream_low_compress_cancel(mailstream_low * s) +{ +#if HAVE_ZLIB + compress_data * data = s->data; + data->ms->driver->mailstream_cancel(data->ms); +#endif +} + +static carray * mailstream_low_compress_get_certificate_chain(mailstream_low * s) +{ +#if HAVE_ZLIB + compress_data * data = s->data; + return data->ms->driver->mailstream_get_certificate_chain(data->ms); +#else + return NULL; +#endif +} + +int mailstream_low_compress_wait_idle(mailstream_low * low, + struct mailstream_cancel * idle, + int max_idle_delay) +{ +#if HAVE_ZLIB + compress_data * data = low->data; + return mailstream_low_wait_idle(data->ms, idle, max_idle_delay); +#else + return MAILSTREAM_IDLE_ERROR; +#endif +} + +static int mailstream_low_compress_setup_idle(mailstream_low * low) +{ +#if HAVE_ZLIB + compress_data * data = low->data; + return mailstream_low_setup_idle(data->ms); +#else + return -1; +#endif +} + +static int mailstream_low_compress_unsetup_idle(mailstream_low * low) +{ +#if HAVE_ZLIB + compress_data * data = low->data; + return mailstream_low_unsetup_idle(data->ms); +#else + return -1; +#endif +} + +static int mailstream_low_compress_interrupt_idle(mailstream_low * low) +{ +#if HAVE_ZLIB + compress_data * data = low->data; + return mailstream_low_interrupt_idle(data->ms); +#else + return -1; +#endif +} diff --git a/Sources/libetpan/data-types/mailstream_compress.h b/Sources/libetpan/data-types/mailstream_compress.h new file mode 100644 index 00000000..786e61a4 --- /dev/null +++ b/Sources/libetpan/data-types/mailstream_compress.h @@ -0,0 +1,72 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2013 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* Created by Ian Ragsdale on 3/8/13. */ + +#ifndef MAILSTREAM_COMPRESS_H +#define MAILSTREAM_COMPRESS_H + +#define USE_DEFLATE 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailstream_low_driver * mailstream_compress_driver; + +struct mailstream_compress_context; + +/* exported methods */ +LIBETPAN_EXPORT +mailstream_low * mailstream_low_compress_open(mailstream_low * ms); + +LIBETPAN_EXPORT +int mailstream_low_compress_wait_idle(mailstream_low * low, + struct mailstream_cancel * idle, + int max_idle_delay); + + /* +LIBETPAN_EXPORT +int mailstream_low_compress_setup_idle(mailstream_low * low); + +LIBETPAN_EXPORT +int mailstream_low_compress_unsetup_idle(mailstream_low * low); + +LIBETPAN_EXPORT +int mailstream_low_compress_interrupt_idle(mailstream_low * low); +*/ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Sources/libetpan/data-types/mailstream_helper.c b/Sources/libetpan/data-types/mailstream_helper.c new file mode 100644 index 00000000..291c2904 --- /dev/null +++ b/Sources/libetpan/data-types/mailstream_helper.c @@ -0,0 +1,578 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream_helper.c,v 1.19 2010/11/28 17:01:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailstream_helper.h" +#include +#include +#include "mail.h" + +static void remove_trailing_eol(MMAPString * mmapstr) +{ + if (mmapstr->str[mmapstr->len - 1] == '\n') { + mmapstr->len --; + mmapstr->str[mmapstr->len] = '\0'; + } + if (mmapstr->str[mmapstr->len - 1] == '\r') { + mmapstr->len --; + mmapstr->str[mmapstr->len] = '\0'; + } +} + +char * mailstream_read_line(mailstream * stream, MMAPString * line) +{ + if (mmap_string_assign(line, "") == NULL) + return NULL; + + return mailstream_read_line_append(stream, line); +} + +static char * mailstream_read_len_append(mailstream * stream, + MMAPString * line, + size_t i) +{ + size_t cur_size; + + cur_size = line->len; + if (mmap_string_set_size(line, line->len + i) == NULL) + return NULL; + if (mailstream_read(stream, line->str + cur_size, i) < 0) + return NULL; + return line->str; +} + +char * mailstream_read_line_append(mailstream * stream, MMAPString * line) +{ + if (stream == NULL) + return NULL; + + do { + if (stream->read_buffer_len > 0) { + size_t i; + + i = 0; + while (i < stream->read_buffer_len) { + if (stream->read_buffer[i] == '\n') + return mailstream_read_len_append(stream, line, i + 1); + i++; + } + if (mailstream_read_len_append(stream, line, + stream->read_buffer_len) == NULL) + return NULL; + } + else { + ssize_t r; + + r = mailstream_feed_read_buffer(stream); + if (r == -1) + return NULL; + + if (r == 0) + break; + } + } + while (1); + + return line->str; +} + +char * mailstream_read_line_remove_eol(mailstream * stream, MMAPString * line) +{ + if (!mailstream_read_line(stream, line)) + return NULL; + + remove_trailing_eol(line); + + return line->str; +} + +int mailstream_is_end_multiline(const char * line) +{ + if (line[0] != '.') + return FALSE; + if (line[1] != 0) + return FALSE; + return TRUE; +} + +#if 1 +char * mailstream_read_multiline(mailstream * s, size_t size, + MMAPString * stream_buffer, + MMAPString * multiline_buffer, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, void * context) +{ + size_t count; + char * line; + size_t last; + + if (mmap_string_assign(multiline_buffer, "") == NULL) + return NULL; + + count = 0; + last = 0; + + while ((line = mailstream_read_line_remove_eol(s, stream_buffer)) != NULL) { + if (mailstream_is_end_multiline(line)) + return multiline_buffer->str; + + if (line[0] == '.') { + if (mmap_string_append(multiline_buffer, line + 1) == NULL) + return NULL; + } + else { + if (mmap_string_append(multiline_buffer, line) == NULL) + return NULL; + } + if (mmap_string_append(multiline_buffer, "\r\n") == NULL) + return NULL; + + count += strlen(line); + if ((size != 0) && (progr_rate != 0) && (progr_fun != NULL)) + if (count - last >= progr_rate) { + if (progr_fun != NULL) { + (* progr_fun)(count, size); + } + if (body_progr_fun != NULL) { + body_progr_fun(count, size, context); + } + last = count; + } + } + + return NULL; +} + +#else + +/* + high speed but don't replace the line break with '\n' and neither + remove the '.' +*/ + +static gboolean end_of_multiline(const char * str, gint len) +{ + gint indx; + + indx = len - 1; + + if (str[indx] != '\n') + return FALSE; + if (indx == 0) + return FALSE; + + indx --; + + if (str[indx] == '\r') { + indx --; + if (indx == 0) + return FALSE; + } + + if (str[indx] != '.') + return FALSE; + if (indx == 0) + return FALSE; + + indx--; + + if (str[indx] != '\n') + return FALSE; + + return TRUE; +} + +char * mailstream_read_multiline(mailstream * stream, size_t size, + MMAPString * stream_buffer, + MMAPString * line, + size_t progr_rate, + progress_function * progr_fun) +{ + if (stream == NULL) + return NULL; + + mmap_string_assign(line, ""); + + do { + if (stream->read_buffer_len > 0) { + size_t i; + + i = 0; + while (i < stream->read_buffer_len) { + if (end_of_multiline(stream->read_buffer, i + 1)) + return mailstream_read_len_append(stream, line, i + 1); + i++; + } + if (mailstream_read_len_append(stream, line, + stream->read_buffer_len) == NULL) + return NULL; + if (end_of_multiline(line->str, line->len)) + return line->str; + } + else + if (mailstream_feed_read_buffer(stream) == -1) + return NULL; + } + while (1); + + return line->str; +} +#endif + + + +static inline ssize_t send_data_line(mailstream * s, + const char * line, size_t length) +{ + int fix_eol; + const char * start; + size_t count; + + start = line; + + fix_eol = 0; + count = 0; + + while (1) { + if (length == 0) + break; + + if (* line == '\r') { + line ++; + + count ++; + length --; + + if (length == 0) { + fix_eol = 1; + break; + } + + if (* line == '\n') { + line ++; + + count ++; + length --; + + break; + } + else { + fix_eol = 1; + break; + } + } + else if (* line == '\n') { + line ++; + + count ++; + length --; + + fix_eol = 1; + break; + } + + line ++; + length --; + count ++; + } + + if (fix_eol) { + if (mailstream_write(s, start, count - 1) == -1) + goto err; + if (mailstream_write(s, "\r\n", 2) == -1) + goto err; + } + else { + if (mailstream_write(s, start, count) == -1) + goto err; + } + + +#if 0 + while (* line != '\n') { + if (* line == '\r') + pos = line; + if (* line == '\0') + return line; + if (mailstream_write(s, line, 1) == -1) + goto err; + line ++; + } + if (pos + 1 == line) { + if (mailstream_write(s, line, 1) == -1) + goto err; + } + else { + if (mailstream_write(s, "\r\n", 2) == -1) + goto err; + } + line ++; +#endif + + return count; + + err: + return -1; +} + +static inline int send_data_crlf_progress(mailstream * s, const char * message, + size_t size, + int quoted, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * progr_context_fun, + void * context) +{ + const char * current; + size_t count; + size_t last; + size_t remaining; + + count = 0; + last = 0; + + current = message; + remaining = size; + + while (remaining > 0) { + ssize_t length; + + if (quoted) { + if (current[0] == '.') + if (mailstream_write(s, ".", 1) == -1) + goto err; + } + + length = send_data_line(s, current, remaining); + if (length < 0) + goto err; + + current += length; + + count += length; + if (progr_rate != 0) { + if (count - last >= progr_rate) { + if (progr_fun != NULL) { + (* progr_fun)(count, size); + } + if (progr_context_fun != NULL) { + (* progr_context_fun)(count, size, context); + } + last = count; + } + } + + remaining -= length; + } + + return 0; + + err: + return -1; +} + +static inline int send_data_crlf(mailstream * s, const char * message, + size_t size, + int quoted, + size_t progr_rate, + progress_function * progr_fun) +{ + return send_data_crlf_progress(s, message, size, quoted, + progr_rate, progr_fun, + NULL, NULL); +} + +static inline int send_data_crlf_with_context(mailstream * s, const char * message, + size_t size, + int quoted, + mailprogress_function * progr_fun, + void * context) +{ + return send_data_crlf_progress(s, message, size, quoted, + 4096, NULL, + progr_fun, context); +} + +int mailstream_send_data_crlf(mailstream * s, const char * message, + size_t size, + size_t progr_rate, + progress_function * progr_fun) +{ + return send_data_crlf(s, message, size, 0, progr_rate, progr_fun); +} + +int mailstream_send_data_crlf_with_context(mailstream * s, const char * message, + size_t size, + mailprogress_function * progr_fun, + void * context) +{ + return send_data_crlf_with_context(s, message, size, 0, progr_fun, context); +} + +static inline int mailstream_send_data_progress(mailstream * s, const char * message, + size_t size, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * progr_ctx_fun, + void * context) +{ + if (send_data_crlf_progress(s, message, size, 1, progr_rate, progr_fun, + progr_ctx_fun, context) == -1) + goto err; + + if (mailstream_write(s, "\r\n.\r\n", 5) == -1) + goto err; + + if (mailstream_flush(s) == -1) + goto err; + + return 0; + +err: + return -1; +} + +int mailstream_send_data(mailstream * s, const char * message, + size_t size, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailstream_send_data_progress(s, message, + size, + progr_rate, progr_fun, + NULL, NULL); +} + +int mailstream_send_data_with_context(mailstream * s, const char * message, + size_t size, + mailprogress_function * progr_fun, + void * context) +{ + return mailstream_send_data_progress(s, message, + size, + 4096, NULL, + progr_fun, context); +} + +static inline ssize_t get_data_size(const char * line, size_t length, + size_t * result) +{ + size_t count; + size_t fixed_count; + + count = 0; + fixed_count = 0; + + while (1) { + if (length == 0) + break; + + if (* line == '\r') { + line ++; + + count ++; + length --; + + if (length == 0) { + fixed_count ++; + break; + } + + if (* line == '\n') { + line ++; + + count ++; + length --; + + break; + } + else { + fixed_count ++; + break; + } + } + else if (* line == '\n') { + line ++; + + count ++; + length --; + + fixed_count ++; + break; + } + + line ++; + length --; + count ++; + } + + * result = count + fixed_count; + + return count; +} + +size_t mailstream_get_data_crlf_size(const char * message, size_t size) +{ + const char * current; + size_t count; + size_t remaining; + size_t fixed_count; + + count = 0; + fixed_count = 0; + + current = message; + remaining = size; + + while (remaining > 0) { + ssize_t length; + size_t line_count; + + length = get_data_size(current, remaining, &line_count); + + fixed_count += line_count; + current += length; + + count += length; + + remaining -= length; + } + + return fixed_count; +} diff --git a/Sources/libetpan/data-types/mailstream_helper.h b/Sources/libetpan/data-types/mailstream_helper.h new file mode 100644 index 00000000..3f431564 --- /dev/null +++ b/Sources/libetpan/data-types/mailstream_helper.h @@ -0,0 +1,88 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream_helper.h,v 1.13 2010/11/28 17:01:26 hoa Exp $ + */ + +#ifndef MAILSTREAM_HELPER_H + +#define MAILSTREAM_HELPER_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +char * mailstream_read_line(mailstream * stream, MMAPString * line); + +char * mailstream_read_line_append(mailstream * stream, MMAPString * line); + +char * mailstream_read_line_remove_eol(mailstream * stream, MMAPString * line); + +char * mailstream_read_multiline(mailstream * s, size_t size, + MMAPString * stream_buffer, + MMAPString * multiline_buffer, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, void * context); + +int mailstream_is_end_multiline(const char * line); + +int mailstream_send_data_crlf(mailstream * s, const char * message, + size_t size, + size_t progr_rate, + progress_function * progr_fun); + +int mailstream_send_data_crlf_with_context(mailstream * s, const char * message, + size_t size, + mailprogress_function * progr_fun, + void * context); + +int mailstream_send_data(mailstream * s, const char * message, + size_t size, + size_t progr_rate, + progress_function * progr_fun); + +int mailstream_send_data_with_context(mailstream * s, const char * message, + size_t size, + mailprogress_function * progr_fun, + void * context); + +size_t mailstream_get_data_crlf_size(const char * message, size_t size); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/data-types/mailstream_low.c b/Sources/libetpan/data-types/mailstream_low.c new file mode 100644 index 00000000..9f423547 --- /dev/null +++ b/Sources/libetpan/data-types/mailstream_low.c @@ -0,0 +1,591 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream_low.c,v 1.27 2011/05/04 16:09:54 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailstream_low.h" +#include + +#ifdef LIBETPAN_MAILSTREAM_DEBUG + +#define STREAM_DEBUG + +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include "maillock.h" +#ifdef WIN32 +# include "win_etpan.h" +#endif +#if defined(ANDROID) || defined(__ANDROID__) +#include +#endif + +#if USE_POLL && defined(HAVE_SYS_POLL_H) +#include +#endif + +#include "mailstream_cfstream.h" +#include "mailstream_compress.h" +#include "mailstream_cancel.h" + +#define LOG_FILE "libetpan-stream-debug.log" + +LIBETPAN_EXPORT +int mailstream_debug = 0; + +LIBETPAN_EXPORT +void (* mailstream_logger)(int direction, + const char * str, size_t size) = NULL; +LIBETPAN_EXPORT +void (* mailstream_logger_id)(mailstream_low * s, int is_stream_data, int direction, + const char * str, size_t size) = NULL; + +static inline void mailstream_logger_internal(mailstream_low * s, int is_stream_data, int direction, + const char * buffer, size_t size); + +// Will log a buffer. +#define STREAM_LOG_ERROR(low, direction, buf, size) \ + mailstream_logger_internal(low, 2, direction, buf, size); \ + if (mailstream_debug) { \ + if (mailstream_logger_id != NULL) { \ + mailstream_logger_id(low, 2, direction, buf, size); \ + } \ + else if (mailstream_logger != NULL) { \ + mailstream_logger(direction, buf, size); \ + } \ + else { \ + FILE * f; \ + mode_t old_mask; \ + \ + old_mask = umask(0077); \ + f = fopen(LOG_FILE, "a"); \ + umask(old_mask); \ + if (f != NULL) { \ + maillock_write_lock(LOG_FILE, fileno(f)); \ + fwrite((buf), 1, (size), f); \ + maillock_write_unlock(LOG_FILE, fileno(f)); \ + fclose(f); \ + } \ + } \ + } + +// Will log a buffer. +#define STREAM_LOG_BUF(low, direction, buf, size) \ + mailstream_logger_internal(low, 1, direction, buf, size); \ + if (mailstream_debug) { \ + if (mailstream_logger_id != NULL) { \ + mailstream_logger_id(low, 1, direction, buf, size); \ + } \ + else if (mailstream_logger != NULL) { \ + mailstream_logger(direction, buf, size); \ + } \ + else { \ + FILE * f; \ + mode_t old_mask; \ + \ + old_mask = umask(0077); \ + f = fopen(LOG_FILE, "a"); \ + umask(old_mask); \ + if (f != NULL) { \ + maillock_write_lock(LOG_FILE, fileno(f)); \ + fwrite((buf), 1, (size), f); \ + maillock_write_unlock(LOG_FILE, fileno(f)); \ + fclose(f); \ + } \ + } \ + } + +// Will log some log text string. +#define STREAM_LOG(low, direction, str) \ + mailstream_logger_internal(low, 0, direction, str, strlen(str)); \ + if (mailstream_debug) { \ + if (mailstream_logger_id != NULL) { \ + mailstream_logger_id(low, 0, direction, str, strlen(str)); \ + } \ + else if (mailstream_logger != NULL) { \ + mailstream_logger(direction, str, strlen(str)); \ + } \ + else { \ + FILE * f; \ + mode_t old_mask; \ + \ + old_mask = umask(0077); \ + f = fopen(LOG_FILE, "a"); \ + umask(old_mask); \ + if (f != NULL) { \ + maillock_write_lock(LOG_FILE, fileno(f)); \ + fputs((str), f); \ + maillock_write_unlock(LOG_FILE, fileno(f)); \ + fclose(f); \ + } \ + } \ + } + +#else + +#define STREAM_LOG_ERROR(low, direction, buf, size) do { } while (0) +#define STREAM_LOG_BUF(low, direction, buf, size) do { } while (0) +#define STREAM_LOG(low, direction, buf) do { } while (0) + +#endif + + +/* general functions */ + +mailstream_low * mailstream_low_new(void * data, + mailstream_low_driver * driver) +{ + mailstream_low * s; + + s = malloc(sizeof(* s)); + if (s == NULL) + return NULL; + + s->data = data; + s->driver = driver; + s->privacy = 1; + s->identifier = NULL; + s->timeout = 0; + s->logger = NULL; + s->logger_context = NULL; + + return s; +} + +int mailstream_low_close(mailstream_low * s) +{ + if (s == NULL) + return -1; + s->driver->mailstream_close(s); + + return 0; +} + +int mailstream_low_get_fd(mailstream_low * s) +{ + if (s == NULL) + return -1; + return s->driver->mailstream_get_fd(s); +} + +struct mailstream_cancel * mailstream_low_get_cancel(mailstream_low * s) +{ + if (s == NULL) + return NULL; + if (s->driver->mailstream_get_cancel == NULL) + return NULL; + return s->driver->mailstream_get_cancel(s); +} + +void mailstream_low_free(mailstream_low * s) +{ + free(s->identifier); + s->identifier = NULL; + s->driver->mailstream_free(s); +} + +ssize_t mailstream_low_read(mailstream_low * s, void * buf, size_t count) +{ + ssize_t r; + + if (s == NULL) + return -1; + r = s->driver->mailstream_read(s, buf, count); + +#ifdef STREAM_DEBUG + if (r > 0) { + STREAM_LOG(s, 0, "<<<<<<< read <<<<<<\n"); + STREAM_LOG_BUF(s, 0, buf, r); + STREAM_LOG(s, 0, "\n"); + STREAM_LOG(s, 0, "<<<<<<< end read <<<<<<\n"); + } +#endif + + if (r < 0) { + STREAM_LOG_ERROR(s, 4, buf, 0); + } + + return r; +} + +ssize_t mailstream_low_write(mailstream_low * s, + const void * buf, size_t count) +{ + ssize_t r; + + if (s == NULL) + return -1; + +#ifdef STREAM_DEBUG + STREAM_LOG(s, 1, ">>>>>>> send >>>>>>\n"); + if (s->privacy) { + STREAM_LOG_BUF(s, 1, buf, count); + } + else { + STREAM_LOG_BUF(s, 2, buf, count); + } + STREAM_LOG(s, 1, "\n"); + STREAM_LOG(s, 1, ">>>>>>> end send >>>>>>\n"); +#endif + + r = s->driver->mailstream_write(s, buf, count); + + if (r < 0) { + STREAM_LOG_ERROR(s, 4 | 1, buf, 0); + } + + return r; +} + +void mailstream_low_cancel(mailstream_low * s) +{ + if (s == NULL) + return; + + if (s->driver->mailstream_cancel == NULL) + return; + + s->driver->mailstream_cancel(s); +} + +void mailstream_low_log_error(mailstream_low * s, + const void * buf, size_t count) +{ + STREAM_LOG_ERROR(s, 0, buf, count); +} + +void mailstream_low_set_privacy(mailstream_low * s, int can_be_public) +{ + s->privacy = can_be_public; +} + +int mailstream_low_set_identifier(mailstream_low * s, + char * identifier) +{ + free(s->identifier); + s->identifier = NULL; + + if (identifier != NULL) { + s->identifier = identifier; + } + + return 0; +} + +const char * mailstream_low_get_identifier(mailstream_low * s) +{ + return s->identifier; +} + +void mailstream_low_set_timeout(mailstream_low * s, + time_t timeout) +{ + s->timeout = timeout; +} + +time_t mailstream_low_get_timeout(mailstream_low * s) +{ + return s->timeout; +} + +void mailstream_low_set_logger(mailstream_low * s, void (* logger)(mailstream_low * s, int log_type, + const char * str, size_t size, void * context), void * logger_context) +{ + s->logger = logger; + s->logger_context = logger_context; +} + +static inline void mailstream_logger_internal(mailstream_low * s, int is_stream_data, int direction, + const char * buffer, size_t size) +{ + int log_type = -1; + + if (s->logger == NULL) + return; + + /* + stream data: + 0: log + 1: buffer + 2: error + + direction: + 4|1: send error + 4: receive error + 2: sent private data + 1: sent data + 0: received data + */ + + switch (is_stream_data) { + case 0: { + switch (direction) { + case 1: + case 2: + case 4|1: + log_type = MAILSTREAM_LOG_TYPE_INFO_SENT; + break; + case 0: + case 4: + log_type = MAILSTREAM_LOG_TYPE_INFO_RECEIVED; + break; + } + break; + } + case 1: { + switch (direction) { + case 2: + log_type = MAILSTREAM_LOG_TYPE_DATA_SENT_PRIVATE; + break; + case 1: + case 4|1: + log_type = MAILSTREAM_LOG_TYPE_DATA_SENT; + break; + case 0: + case 4: + default: + log_type = MAILSTREAM_LOG_TYPE_DATA_RECEIVED; + break; + } + break; + } + case 2: { + switch (direction) { + case 2: + case 1: + case 4|1: + log_type = MAILSTREAM_LOG_TYPE_ERROR_SENT; + break; + case 4: + log_type = MAILSTREAM_LOG_TYPE_ERROR_RECEIVED; + break; + case 0: + log_type = MAILSTREAM_LOG_TYPE_ERROR_PARSE; + break; + } + break; + } + } + + if (log_type == -1) + return; + + s->logger(s, log_type, buffer, size, s->logger_context); +} + +carray * mailstream_low_get_certificate_chain(mailstream_low * s) +{ + if (s == NULL) + return NULL; + + if (s->driver->mailstream_get_certificate_chain == NULL) + return NULL; + + return s->driver->mailstream_get_certificate_chain(s); +} + +int mailstream_low_wait_idle(mailstream_low * low, struct mailstream_cancel * idle, + int max_idle_delay) +{ + int fd; + int idle_fd; + int cancel_fd; + int r; +#if defined(WIN32) + fd_set readfds; +#elif USE_POLL + struct pollfd pfd[3]; +#else + int maxfd; + fd_set readfds; +#endif + + if (low->driver == mailstream_cfstream_driver) { + return mailstream_low_cfstream_wait_idle(low, max_idle_delay); + } + else if (low->driver == mailstream_compress_driver) { + return mailstream_low_compress_wait_idle(low, idle, max_idle_delay); + } + + if (idle == NULL) { + return MAILSTREAM_IDLE_ERROR; + } + if (mailstream_low_get_cancel(low) == NULL) { + return MAILSTREAM_IDLE_ERROR; + } + fd = mailstream_low_get_fd(low); + idle_fd = mailstream_cancel_get_fd(idle); + cancel_fd = mailstream_cancel_get_fd(mailstream_low_get_cancel(low)); + +#if defined(WIN32) + FD_ZERO(&readfds); + HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL); + WSAEventSelect(fd, event, FD_READ | FD_CLOSE); + FD_SET(event, &readfds); + FD_SET(idle_fd, &readfds); + FD_SET(cancel_fd, &readfds); + r = WaitForMultipleObjects(readfds.fd_count, readfds.fd_array, FALSE, max_idle_delay * 1000); + WSAEventSelect(fd, event, 0); + CloseHandle(event); + if (r == WAIT_TIMEOUT) { + return MAILSTREAM_IDLE_TIMEOUT; + } + else if (r == WAIT_OBJECT_0){ + return MAILSTREAM_IDLE_HASDATA; + } + else if (r == WAIT_OBJECT_0 + 1){ + return MAILSTREAM_IDLE_INTERRUPTED; + } + else if (r == WAIT_OBJECT_0 + 2){ + return MAILSTREAM_IDLE_CANCELLED; + } + DWORD i = GetLastError(); + return MAILSTREAM_IDLE_ERROR; +#elif USE_POLL + pfd[0].fd = fd; + pfd[0].events = POLLIN; + pfd[0].revents = 0; + + pfd[1].fd = idle_fd; + pfd[1].events = POLLIN; + pfd[1].revents = 0; + + pfd[2].fd = cancel_fd; + pfd[2].events = POLLIN; + pfd[2].revents = 0; + + r = poll(&pfd[0], 3, max_idle_delay * 1000); + + if (r == 0){ + // timeout + return MAILSTREAM_IDLE_TIMEOUT; + } + else if (r == -1) { + // do nothing + return MAILSTREAM_IDLE_ERROR; + } + else { + if (pfd[0].revents & POLLIN) { + // has something on socket + return MAILSTREAM_IDLE_HASDATA; + } + if (pfd[1].revents & POLLIN) { + // idle interrupted + mailstream_cancel_ack(idle); + return MAILSTREAM_IDLE_INTERRUPTED; + } + if (pfd[2].revents & POLLIN) { + // idle cancelled + mailstream_cancel_ack(mailstream_low_get_cancel(low)); + return MAILSTREAM_IDLE_CANCELLED; + } + return MAILSTREAM_IDLE_ERROR; + } +#else + FD_ZERO(&readfds); + FD_SET(fd, &readfds); + FD_SET(idle_fd, &readfds); + FD_SET(cancel_fd, &readfds); + maxfd = fd; + if (idle_fd > maxfd) { + maxfd = idle_fd; + } + if (cancel_fd > maxfd) { + maxfd = cancel_fd; + } + struct timeval delay; + delay.tv_sec = max_idle_delay; + delay.tv_usec = 0; + + r = select(maxfd + 1, &readfds, NULL, NULL, &delay); + if (r == 0) { + // timeout + return MAILSTREAM_IDLE_TIMEOUT; + } + else if (r == -1) { + // do nothing + return MAILSTREAM_IDLE_ERROR; + } + else { + if (FD_ISSET(fd, &readfds)) { + // has something on socket + return MAILSTREAM_IDLE_HASDATA; + } + if (FD_ISSET(idle_fd, &readfds)) { + // idle interrupted + mailstream_cancel_ack(idle); + return MAILSTREAM_IDLE_INTERRUPTED; + } + if (FD_ISSET(cancel_fd, &readfds)) { + // idle cancelled + mailstream_cancel_ack(mailstream_low_get_cancel(low)); + return MAILSTREAM_IDLE_CANCELLED; + } + return MAILSTREAM_IDLE_ERROR; + } +#endif +} + +int mailstream_low_setup_idle(mailstream_low * low) +{ + if (low->driver->mailstream_setup_idle == NULL) + return -1; + + return low->driver->mailstream_setup_idle(low); +} + +int mailstream_low_unsetup_idle(mailstream_low * low) +{ + if (low->driver->mailstream_unsetup_idle == NULL) + return -1; + + return low->driver->mailstream_unsetup_idle(low); +} + +int mailstream_low_interrupt_idle(mailstream_low * low) +{ + if (low->driver->mailstream_interrupt_idle == NULL) + return -1; + + return low->driver->mailstream_interrupt_idle(low); +} + diff --git a/Sources/libetpan/data-types/mailstream_low.h b/Sources/libetpan/data-types/mailstream_low.h new file mode 100644 index 00000000..e8adcaf3 --- /dev/null +++ b/Sources/libetpan/data-types/mailstream_low.h @@ -0,0 +1,123 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream_low.h,v 1.15 2011/05/04 16:01:10 hoa Exp $ + */ + +#ifndef MAILSTREAM_LOW_H + +#define MAILSTREAM_LOW_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* general functions */ + +LIBETPAN_EXPORT +mailstream_low * mailstream_low_new(void * data, + mailstream_low_driver * driver); + +ssize_t mailstream_low_write(mailstream_low * s, + const void * buf, size_t count); + +ssize_t mailstream_low_read(mailstream_low * s, void * buf, size_t count); + +LIBETPAN_EXPORT +int mailstream_low_close(mailstream_low * s); + +LIBETPAN_EXPORT +int mailstream_low_get_fd(mailstream_low * s); + +LIBETPAN_EXPORT +struct mailstream_cancel * mailstream_low_get_cancel(mailstream_low * s); + +LIBETPAN_EXPORT +void mailstream_low_free(mailstream_low * s); + +LIBETPAN_EXPORT +void mailstream_low_cancel(mailstream_low * s); + +LIBETPAN_EXPORT +void mailstream_low_log_error(mailstream_low * s, + const void * buf, size_t count); + +LIBETPAN_EXPORT +void mailstream_low_set_privacy(mailstream_low * s, int can_be_public); + +LIBETPAN_EXPORT +int mailstream_low_set_identifier(mailstream_low * s, + char * identifier); + +LIBETPAN_EXPORT +const char * mailstream_low_get_identifier(mailstream_low * s); + +LIBETPAN_EXPORT +void mailstream_low_set_timeout(mailstream_low * s, + time_t timeout); + +LIBETPAN_EXPORT +time_t mailstream_low_get_timeout(mailstream_low * s); + +LIBETPAN_EXPORT +void mailstream_low_set_logger(mailstream_low * s, void (* logger)(mailstream_low * s, int log_type, + const char * str, size_t size, void * context), void * logger_context); + +/* Get certificate chain. Returns an array of MMAPString containing DER data or NULL if it's not a SSL connection */ +LIBETPAN_EXPORT +carray * mailstream_low_get_certificate_chain(mailstream_low * s); + +LIBETPAN_EXPORT +int mailstream_low_wait_idle(mailstream_low * low, struct mailstream_cancel * cancel, + int max_idle_delay); + +/* + All those functions returns -1 if interrupt idle is not implemented and + should be based on select(). +*/ +LIBETPAN_EXPORT +int mailstream_low_setup_idle(mailstream_low * low); + +LIBETPAN_EXPORT +int mailstream_low_unsetup_idle(mailstream_low * low); + +LIBETPAN_EXPORT +int mailstream_low_interrupt_idle(mailstream_low * low); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/data-types/mailstream_socket.c b/Sources/libetpan/data-types/mailstream_socket.c new file mode 100644 index 00000000..8b606971 --- /dev/null +++ b/Sources/libetpan/data-types/mailstream_socket.c @@ -0,0 +1,482 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream_socket.c,v 1.33 2011/04/15 10:43:31 hoa Exp $ + */ +#define HAVE_CONFIG_H 1 + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailstream_socket.h" + +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#ifdef HAVE_SYS_SOCKET_H +# include +#endif + +#ifdef HAVE_STRING_H +# include +#endif + +/* + these 3 headers MUST be included before + to insure compatibility with Mac OS X (this is true for 10.2) +*/ + +#ifdef WIN32 +# include +#else +# include +# include +# if USE_POLL +# ifdef HAVE_SYS_POLL_H +# include +# endif +# else +# ifdef HAVE_SYS_SELECT_H +# include +# endif +# endif +#endif + +#include "mailstream_cancel.h" + +struct mailstream_socket_data { + int fd; + struct mailstream_cancel * cancel; + int use_read; +}; + +/* mailstream_low, socket */ + +static int mailstream_low_socket_close(mailstream_low * s); +static ssize_t mailstream_low_socket_read(mailstream_low * s, + void * buf, size_t count); +static ssize_t mailstream_low_socket_write(mailstream_low * s, + const void * buf, size_t count); +static void mailstream_low_socket_free(mailstream_low * s); +static int mailstream_low_socket_get_fd(mailstream_low * s); +static void mailstream_low_socket_cancel(mailstream_low * s); +static struct mailstream_cancel * mailstream_low_socket_get_cancel(mailstream_low * s); + +static mailstream_low_driver local_mailstream_socket_driver = { + /* mailstream_read */ mailstream_low_socket_read, + /* mailstream_write */ mailstream_low_socket_write, + /* mailstream_close */ mailstream_low_socket_close, + /* mailstream_get_fd */ mailstream_low_socket_get_fd, + /* mailstream_free */ mailstream_low_socket_free, + /* mailstream_cancel */ mailstream_low_socket_cancel, + /* mailstream_get_cancel */ mailstream_low_socket_get_cancel, + /* mailstream_get_certificate_chain */ NULL, + /* mailstream_setup_idle */ NULL, + /* mailstream_unsetup_idle */ NULL, + /* mailstream_interrupt_idle */ NULL, +}; + +mailstream_low_driver * mailstream_socket_driver = +&local_mailstream_socket_driver; + +/* file descriptor must be given in (default) blocking-mode */ + +static struct mailstream_socket_data * socket_data_new(int fd) +{ + struct mailstream_socket_data * socket_data; + + socket_data = (struct mailstream_socket_data * ) malloc(sizeof(* socket_data)); + if (socket_data == NULL) + goto err; + + socket_data->fd = fd; + socket_data->use_read = 0; + socket_data->cancel = mailstream_cancel_new(); + if (socket_data->cancel == NULL) + goto free; + + return socket_data; + + free: + free(socket_data); + err: + return NULL; +} + +static void socket_data_free(struct mailstream_socket_data * socket_data) +{ + mailstream_cancel_free(socket_data->cancel); + free(socket_data); +} + +static void socket_data_close(struct mailstream_socket_data * socket_data) +{ +#ifdef WIN32 +/* SEB */ + closesocket(socket_data->fd); +#else + close(socket_data->fd); +#endif + socket_data->fd = -1; +} + +mailstream_low * mailstream_low_socket_open(int fd) +{ + mailstream_low * s; + struct mailstream_socket_data * socket_data; + + socket_data = socket_data_new(fd); + if (socket_data == NULL) + goto err; + + s = mailstream_low_new(socket_data, mailstream_socket_driver); + if (s == NULL) + goto free_socket_data; + + return s; + + free_socket_data: + socket_data_free(socket_data); + err: + return NULL; +} + +static int mailstream_low_socket_close(mailstream_low * s) +{ + struct mailstream_socket_data * socket_data; + + socket_data = (struct mailstream_socket_data *) s->data; + socket_data_close(socket_data); + + return 0; +} + +static void mailstream_low_socket_free(mailstream_low * s) +{ + struct mailstream_socket_data * socket_data; + + socket_data = (struct mailstream_socket_data *) s->data; + socket_data_free(socket_data); + s->data = NULL; + + free(s); +} + +static int mailstream_low_socket_get_fd(mailstream_low * s) +{ + struct mailstream_socket_data * socket_data; + + socket_data = (struct mailstream_socket_data *) s->data; + return socket_data->fd; +} + + +static ssize_t mailstream_low_socket_read(mailstream_low * s, + void * buf, size_t count) +{ + int r; + struct mailstream_socket_data * socket_data; + + socket_data = (struct mailstream_socket_data *) s->data; + + if (mailstream_cancel_cancelled(socket_data->cancel)) + return -1; + + /* timeout */ + { + struct timeval timeout; + int cancellation_fd; + int cancelled; + int got_data; +#if defined(WIN32) + fd_set fds_read; + HANDLE event; +#elif USE_POLL + struct pollfd pfd[2]; +#else + fd_set fds_read; + int max_fd; +#endif + + if (s->timeout == 0) { + timeout = mailstream_network_delay; + } + else { + timeout.tv_sec = s->timeout; + timeout.tv_usec = 0; + } + + cancellation_fd = mailstream_cancel_get_fd(socket_data->cancel); + +#if defined(WIN32) + FD_ZERO(&fds_read); + FD_SET(cancellation_fd, &fds_read); + + event = CreateEvent(NULL, TRUE, FALSE, NULL); + WSAEventSelect(socket_data->fd, event, FD_READ | FD_CLOSE); + FD_SET(event, &fds_read); + r = WaitForMultipleObjects(fds_read.fd_count, fds_read.fd_array, FALSE, timeout.tv_sec * 1000 + timeout.tv_usec / 1000); + if (WAIT_TIMEOUT == r) { + WSAEventSelect(socket_data->fd, event, 0); + CloseHandle(event); + return -1; + } + + cancelled = (fds_read.fd_array[r - WAIT_OBJECT_0] == cancellation_fd); + got_data = (fds_read.fd_array[r - WAIT_OBJECT_0] == event); + WSAEventSelect(socket_data->fd, event, 0); + CloseHandle(event); +#elif USE_POLL + pfd[0].fd = socket_data->fd; + pfd[0].events = POLLIN; + pfd[0].revents = 0; + + pfd[1].fd = cancellation_fd; + pfd[1].events = POLLIN; + pfd[1].revents = 0; + + r = poll(&pfd[0], 2, timeout.tv_sec * 1000 + timeout.tv_usec / 1000); + if (r <= 0) + return -1; + + cancelled = pfd[1].revents & POLLIN; + got_data = pfd[0].revents & POLLIN; +#else + FD_ZERO(&fds_read); + FD_SET(cancellation_fd, &fds_read); + FD_SET(socket_data->fd, &fds_read); + max_fd = cancellation_fd > socket_data->fd ? cancellation_fd : socket_data->fd; + r = select(max_fd + 1, &fds_read, NULL,/* &fds_excp*/ NULL, &timeout); + if (r <= 0) + return -1; + + cancelled = FD_ISSET(cancellation_fd, &fds_read); + got_data = FD_ISSET(socket_data->fd, &fds_read); +#endif + + if (cancelled) { + /* cancelled */ + mailstream_cancel_ack(socket_data->cancel); + return -1; + } + + if (!got_data) + return 0; + } + + if (socket_data->use_read) { + r = read(socket_data->fd, buf, count); + } + else { + r = recv(socket_data->fd, buf, count, 0); +#ifdef WIN32 + if (SOCKET_ERROR == r) { + if (WSAEWOULDBLOCK == WSAGetLastError()) { + r = 0; + } + } else if (r == 0 && count > 0) { + /* The socket is gracefully closed */ + r = SOCKET_ERROR; + } +#endif + } + + return r; +} + +static ssize_t mailstream_low_socket_write(mailstream_low * s, + const void * buf, size_t count) +{ + int r; + struct mailstream_socket_data * socket_data; + + socket_data = (struct mailstream_socket_data *) s->data; + + if (mailstream_cancel_cancelled(socket_data->cancel)) + return -1; + + /* timeout */ + { + struct timeval timeout; + int cancellation_fd; + int cancelled; + int write_enabled; +#if defined(WIN32) + fd_set fds_read; + fd_set fds_write; + HANDLE event; +#elif USE_POLL + struct pollfd pfd[2]; +#else + fd_set fds_read; + fd_set fds_write; + int max_fd; +#endif + + if (s->timeout == 0) { + timeout = mailstream_network_delay; + } + else { + timeout.tv_sec = s->timeout; + timeout.tv_usec = 0; + } + + cancellation_fd = mailstream_cancel_get_fd(socket_data->cancel); +#if defined(WIN32) + FD_ZERO(&fds_read); + FD_SET(cancellation_fd, &fds_read); + FD_ZERO(&fds_write); + + event = CreateEvent(NULL, TRUE, FALSE, NULL); + WSAEventSelect(socket_data->fd, event, FD_WRITE | FD_CLOSE); + FD_SET(event, &fds_read); + r = WaitForMultipleObjects(fds_read.fd_count, fds_read.fd_array, FALSE, timeout.tv_sec * 1000 + timeout.tv_usec / 1000); + if (r < 0) { + WSAEventSelect(socket_data->fd, event, 0); + CloseHandle(event); + return -1; + } + + cancelled = (fds_read.fd_array[r - WAIT_OBJECT_0] == cancellation_fd); + write_enabled = (fds_read.fd_array[r - WAIT_OBJECT_0] == event); + WSAEventSelect(socket_data->fd, event, 0); + CloseHandle(event); +#elif USE_POLL + pfd[0].fd = socket_data->fd; + pfd[0].events = POLLOUT; + pfd[0].revents = 0; + + pfd[1].fd = cancellation_fd; + pfd[1].events = POLLIN; + pfd[1].revents = 0; + + r = poll(&pfd[0], 2, timeout.tv_sec * 1000 + timeout.tv_usec / 1000); + if (r <= 0) + return -1; + + cancelled = pfd[1].revents & POLLIN; + write_enabled = pfd[0].revents & POLLOUT; +#else + FD_ZERO(&fds_read); + FD_SET(cancellation_fd, &fds_read); + FD_ZERO(&fds_write); + FD_SET(socket_data->fd, &fds_write); + max_fd = cancellation_fd > socket_data->fd ? cancellation_fd : socket_data->fd; + r = select(max_fd + 1, &fds_read, &fds_write, /*&fds_excp */ NULL, &timeout); + if (r <= 0) + return -1; + + cancelled = FD_ISSET(cancellation_fd, &fds_read); + write_enabled = FD_ISSET(socket_data->fd, &fds_write); +#endif + + if (cancelled) { + /* cancelled */ + mailstream_cancel_ack(socket_data->cancel); + return -1; + } + + if (!write_enabled) + return 0; + } + + r = send(socket_data->fd, buf, count, 0); + +#ifdef WIN32 + if (SOCKET_ERROR == r) { + if (WSAEWOULDBLOCK == WSAGetLastError()) { + r = 0; + } + } +#endif + + return r; +} + + +/* mailstream */ + +mailstream * mailstream_socket_open(int fd) +{ + return mailstream_socket_open_timeout(fd, 0); +} + +mailstream * mailstream_socket_open_timeout(int fd, time_t timeout) +{ + mailstream_low * low; + mailstream * s; + + low = mailstream_low_socket_open(fd); + if (low == NULL) + goto err; + mailstream_low_set_timeout(low, timeout); + + s = mailstream_new(low, 8192); + if (s == NULL) + goto free_low; + + return s; + + free_low: + mailstream_low_close(low); + err: + return NULL; +} + +static void mailstream_low_socket_cancel(mailstream_low * s) +{ + struct mailstream_socket_data * socket_data; + + socket_data = (struct mailstream_socket_data *) s->data; + mailstream_cancel_notify(socket_data->cancel); +} + +void mailstream_socket_set_use_read(mailstream * stream, int use_read) +{ + struct mailstream_socket_data * socket_data; + mailstream_low * low; + + low = mailstream_get_low(stream); + socket_data = (struct mailstream_socket_data *) low->data; + socket_data->use_read = use_read; +} + +static struct mailstream_cancel * mailstream_low_socket_get_cancel(mailstream_low * s) +{ + struct mailstream_socket_data * socket_data; + + socket_data = (struct mailstream_socket_data *) s->data; + return socket_data->cancel; +} diff --git a/Sources/libetpan/data-types/mailstream_socket.h b/Sources/libetpan/data-types/mailstream_socket.h new file mode 100644 index 00000000..46a24813 --- /dev/null +++ b/Sources/libetpan/data-types/mailstream_socket.h @@ -0,0 +1,59 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream_socket.h,v 1.12 2011/04/15 10:43:31 hoa Exp $ + */ + +#ifndef MAILSTREAM_SOCKET_H + +#define MAILSTREAM_SOCKET_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* socket */ + +extern mailstream_low_driver * mailstream_socket_driver; + +mailstream_low * mailstream_low_socket_open(int fd); +void mailstream_socket_set_use_read(mailstream * stream, int use_read); +mailstream * mailstream_socket_open(int fd); +mailstream * mailstream_socket_open_timeout(int fd, time_t timeout); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/data-types/mailstream_ssl.c b/Sources/libetpan/data-types/mailstream_ssl.c new file mode 100644 index 00000000..bd680ae5 --- /dev/null +++ b/Sources/libetpan/data-types/mailstream_ssl.c @@ -0,0 +1,1576 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream_ssl.c,v 1.77 2011/08/30 19:42:16 colinleroy Exp $ + */ + +/* + NOTE : + + The user has to call himself SSL_library_init() if he wants to + use SSL. +*/ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailstream_ssl.h" +#include "mailstream_ssl_private.h" + +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_STDLIB_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif +#include + +/* + these 3 headers MUST be included before + to insure compatibility with Mac OS X (this is true for 10.2) +*/ +#ifdef WIN32 +# include +#else +# include +# include +# if USE_POLL +# ifdef HAVE_SYS_POLL_H +# include +# endif +# else +# ifdef HAVE_SELECT_H +# include +# endif +# endif +#endif + +#if LIBETPAN_IOS_DISABLE_SSL +#undef USE_SSL +#endif + +/* mailstream_low, ssl */ + +#ifdef USE_SSL +# ifndef USE_GNUTLS +# include +# else +# include +# include +# include +# endif +# ifdef LIBETPAN_REENTRANT +# if HAVE_PTHREAD_H +# include +# elif defined(WIN32) + void mailprivacy_gnupg_init_lock(); + void mailprivacy_smime_init_lock(); +# endif +# endif +#endif + +#include "mmapstring.h" +#include "mailstream_cancel.h" + +struct mailstream_ssl_context +{ + int fd; +#ifdef USE_SSL +#ifndef USE_GNUTLS + SSL_CTX * openssl_ssl_ctx; + X509* client_x509; + EVP_PKEY *client_pkey; +# if (OPENSSL_VERSION_NUMBER >= 0x10000000L) + char * server_name; +# endif /* (OPENSSL_VERSION_NUMBER >= 0x10000000L) */ +#else + gnutls_session session; + gnutls_x509_crt client_x509; + gnutls_x509_privkey client_pkey; + gnutls_certificate_credentials_t gnutls_credentials; +#endif +#endif +}; + +#ifdef USE_SSL +#ifndef USE_GNUTLS +struct mailstream_ssl_data { + int fd; + SSL * ssl_conn; + SSL_CTX * ssl_ctx; + struct mailstream_cancel * cancel; +}; + +#else +struct mailstream_ssl_data { + int fd; + gnutls_session session; + gnutls_certificate_credentials_t xcred; + struct mailstream_cancel * cancel; +}; +#endif +#endif + +#ifdef USE_SSL +#ifdef LIBETPAN_REENTRANT +# if HAVE_PTHREAD_H +# define MUTEX_LOCK(x) pthread_mutex_lock(x) +# define MUTEX_UNLOCK(x) pthread_mutex_unlock(x) + static pthread_mutex_t ssl_lock = PTHREAD_MUTEX_INITIALIZER; +# elif (defined WIN32) +# define MUTEX_LOCK(x) EnterCriticalSection(x); +# define MUTEX_UNLOCK(x) LeaveCriticalSection(x); + static CRITICAL_SECTION ssl_lock; +# else +# error "What are your threads?" +# endif +#else +# define MUTEX_LOCK(x) +# define MUTEX_UNLOCK(x) +#endif +static int openssl_init_done = 0; +#endif + +// Used to make OpenSSL thread safe +#ifndef USE_GNUTLS +#if defined (HAVE_PTHREAD_H) && !defined (WIN32) && defined (USE_SSL) && defined (LIBETPAN_REENTRANT) + struct CRYPTO_dynlock_value + { + pthread_mutex_t mutex; + }; + + static pthread_mutex_t * s_mutex_buf = NULL; + + static void locking_function(int mode, int n, const char * file, int line) + { + if (mode & CRYPTO_LOCK) + MUTEX_LOCK(&s_mutex_buf[n]); + else + MUTEX_UNLOCK(&s_mutex_buf[n]); + } + + static unsigned long id_function(void) + { + return ((unsigned long) pthread_self()); + } + + static struct CRYPTO_dynlock_value *dyn_create_function(const char *file, int line) + { + struct CRYPTO_dynlock_value *value; + + value = (struct CRYPTO_dynlock_value *) malloc(sizeof(struct CRYPTO_dynlock_value)); + if (!value) { + goto err; + } + pthread_mutex_init(&value->mutex, NULL); + + return value; + + err: + return (NULL); + } + + static void dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l, const char *file, int line) + { + if (mode & CRYPTO_LOCK) { + MUTEX_LOCK(&l->mutex); + } + else { + MUTEX_UNLOCK(&l->mutex); + } + } + + static void dyn_destroy_function(struct CRYPTO_dynlock_value *l,const char *file, int line) + { + pthread_mutex_destroy(&l->mutex); + free(l); + } + + static void mailstream_openssl_reentrant_setup(void) + { + int i; + + s_mutex_buf = (pthread_mutex_t *) malloc(CRYPTO_num_locks() * sizeof(* s_mutex_buf)); + if(s_mutex_buf == NULL) + return; + + for(i = 0 ; i < CRYPTO_num_locks() ; i++) + pthread_mutex_init(&s_mutex_buf[i], NULL); + CRYPTO_set_id_callback(id_function); + CRYPTO_set_locking_callback(locking_function); + CRYPTO_set_dynlock_create_callback(dyn_create_function); + CRYPTO_set_dynlock_lock_callback(dyn_lock_function); + CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function); + } +#endif +#endif + +void mailstream_ssl_init_lock(void) +{ +#if !defined (HAVE_PTHREAD_H) && defined (WIN32) && defined (USE_SSL) + static long volatile mailstream_ssl_init_lock_done = 0; + if (InterlockedExchange(&mailstream_ssl_init_lock_done, 1) == 0) { + InitializeCriticalSection(&ssl_lock); + } +#endif +} + +void mailstream_ssl_uninit_lock(void) +{ +#if !defined (HAVE_PTHREAD_H) && defined (WIN32) && defined (USE_SSL) + static long volatile mailstream_ssl_init_lock_done = 0; + if (InterlockedExchange(&mailstream_ssl_init_lock_done, 1) == 0) { + DeleteCriticalSection(&ssl_lock); + } +#endif +} + +void mailstream_gnutls_init_not_required(void) +{ +} + +void mailstream_openssl_init_not_required(void) +{ +#ifdef USE_SSL + mailstream_ssl_init_lock(); + MUTEX_LOCK(&ssl_lock); + openssl_init_done = 1; + MUTEX_UNLOCK(&ssl_lock); +#endif +} + +void mailstream_ssl_init_not_required(void) +{ + mailstream_gnutls_init_not_required(); + mailstream_openssl_init_not_required(); +} + +static inline void mailstream_ssl_init(void) +{ +#ifdef USE_SSL + mailstream_ssl_init_lock(); + MUTEX_LOCK(&ssl_lock); +#ifndef USE_GNUTLS + if (!openssl_init_done) { + #if defined (HAVE_PTHREAD_H) && !defined (WIN32) && defined (USE_SSL) && defined (LIBETPAN_REENTRANT) + mailstream_openssl_reentrant_setup(); + #endif + + SSL_load_error_strings(); + SSL_library_init(); + OpenSSL_add_all_algorithms(); + + openssl_init_done = 1; + } +#else + gnutls_global_init(); +#endif + MUTEX_UNLOCK(&ssl_lock); +#endif +} + +#ifdef USE_SSL +static inline int mailstream_prepare_fd(int fd) +{ +#ifndef WIN32 + int fd_flags; + int r; + + fd_flags = fcntl(fd, F_GETFL, 0); + fd_flags |= O_NDELAY; + r = fcntl(fd, F_SETFL, fd_flags); + if (r < 0) + return -1; +#endif + + return 0; +} +#endif + +static int wait_SSL_connect(int s, int want_read, time_t timeout_seconds) +{ + struct timeval timeout; + int r; +#if defined(WIN32) || !USE_POLL + fd_set fds; +#else + struct pollfd pfd; +#endif // WIN32 + + if (timeout_seconds == 0) { + timeout = mailstream_network_delay; + } + else { + timeout.tv_sec = timeout_seconds; + timeout.tv_usec = 0; + } +#if defined(WIN32) || !USE_POLL + FD_ZERO(&fds); + FD_SET(s, &fds); + /* TODO: how to cancel this ? */ + if (want_read) + r = select(s + 1, &fds, NULL, NULL, &timeout); + else + r = select(s + 1, NULL, &fds, NULL, &timeout); + if (r <= 0) { + return -1; + } + if (!FD_ISSET(s, &fds)) { + /* though, it's strange */ + return -1; + } +#else + pfd.fd = s; + if (want_read) { + pfd.events = POLLIN; + } + else { + pfd.events = POLLOUT; + } + r = poll(&pfd, 1, timeout.tv_sec * 1000 + timeout.tv_usec / 1000); + if (r <= 0) { + return -1; + } + + if (pfd.revents & pfd.events != pfd.events) { + return -1; + } +#endif + + return 0; +} + +#ifdef USE_SSL +static int mailstream_low_ssl_close(mailstream_low * s); +static ssize_t mailstream_low_ssl_read(mailstream_low * s, + void * buf, size_t count); +static ssize_t mailstream_low_ssl_write(mailstream_low * s, + const void * buf, size_t count); +static void mailstream_low_ssl_free(mailstream_low * s); +static int mailstream_low_ssl_get_fd(mailstream_low * s); +static void mailstream_low_ssl_cancel(mailstream_low * s); +static struct mailstream_cancel * mailstream_low_ssl_get_cancel(mailstream_low * s); +static carray * mailstream_low_ssl_get_certificate_chain(mailstream_low * s); + +static mailstream_low_driver local_mailstream_ssl_driver = { + /* mailstream_read */ mailstream_low_ssl_read, + /* mailstream_write */ mailstream_low_ssl_write, + /* mailstream_close */ mailstream_low_ssl_close, + /* mailstream_get_fd */ mailstream_low_ssl_get_fd, + /* mailstream_free */ mailstream_low_ssl_free, + /* mailstream_cancel */ mailstream_low_ssl_cancel, + /* mailstream_get_cancel */ mailstream_low_ssl_get_cancel, + /* mailstream_get_certificate_chain */ mailstream_low_ssl_get_certificate_chain, + /* mailstream_setup_idle */ NULL, + /* mailstream_unsetup_idle */ NULL, + /* mailstream_interrupt_idle */ NULL, +}; + +mailstream_low_driver * mailstream_ssl_driver = &local_mailstream_ssl_driver; +#endif + +/* file descriptor must be given in (default) blocking-mode */ + +#ifdef USE_SSL +#ifndef USE_GNUTLS + +static struct mailstream_ssl_context * mailstream_ssl_context_new(SSL_CTX * open_ssl_ctx, int fd); +static void mailstream_ssl_context_free(struct mailstream_ssl_context * ssl_ctx); + +static int mailstream_openssl_client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey) +{ + struct mailstream_ssl_context * ssl_context = (struct mailstream_ssl_context *)SSL_CTX_get_app_data(SSL_get_SSL_CTX(ssl)); + + if (x509 == NULL || pkey == NULL) { + return 0; + } + + if (ssl_context == NULL) + return 0; + + *x509 = ssl_context->client_x509; + *pkey = ssl_context->client_pkey; + + if (*x509 && *pkey) + return 1; + else + return 0; +} + +static struct mailstream_ssl_data * ssl_data_new_full(int fd, time_t timeout, + const SSL_METHOD * method, void (* callback)(struct mailstream_ssl_context * ssl_context, void * cb_data), + void * cb_data) +{ + struct mailstream_ssl_data * ssl_data; + SSL * ssl_conn; + int r; + SSL_CTX * tmp_ctx; + struct mailstream_cancel * cancel; + struct mailstream_ssl_context * ssl_context = NULL; +#if SSL_MODE_RELEASE_BUFFERS + long mode = 0; +#endif + + mailstream_ssl_init(); + + tmp_ctx = SSL_CTX_new(method); + if (tmp_ctx == NULL) + goto err; + + if (callback != NULL) { + ssl_context = mailstream_ssl_context_new(tmp_ctx, fd); + callback(ssl_context, cb_data); + } + + SSL_CTX_set_app_data(tmp_ctx, ssl_context); + SSL_CTX_set_client_cert_cb(tmp_ctx, mailstream_openssl_client_cert_cb); + ssl_conn = (SSL *) SSL_new(tmp_ctx); + if (ssl_conn == NULL) + goto free_ctx; + +#if SSL_MODE_RELEASE_BUFFERS + mode = SSL_get_mode(ssl_conn); + SSL_set_mode(ssl_conn, mode | SSL_MODE_RELEASE_BUFFERS); +#endif + +#if (OPENSSL_VERSION_NUMBER >= 0x10000000L) + if (ssl_context != NULL && ssl_context->server_name != NULL) { + SSL_set_tlsext_host_name(ssl_conn, ssl_context->server_name); + free(ssl_context->server_name); + ssl_context->server_name = NULL; + } +#endif /* (OPENSSL_VERSION_NUMBER >= 0x10000000L) */ + + if (SSL_set_fd(ssl_conn, fd) == 0) + goto free_ssl_conn; + +again: + r = SSL_connect(ssl_conn); + + switch(SSL_get_error(ssl_conn, r)) { + case SSL_ERROR_WANT_READ: + r = wait_SSL_connect(fd, 1, timeout); + if (r < 0) + goto free_ssl_conn; + else + goto again; + break; + case SSL_ERROR_WANT_WRITE: + r = wait_SSL_connect(fd, 0, timeout); + if (r < 0) + goto free_ssl_conn; + else + goto again; + break; + } + if (r <= 0) + goto free_ssl_conn; + + cancel = mailstream_cancel_new(); + if (cancel == NULL) + goto free_ssl_conn; + + r = mailstream_prepare_fd(fd); + if (r < 0) + goto free_cancel; + + ssl_data = malloc(sizeof(* ssl_data)); + if (ssl_data == NULL) + goto free_cancel; + + ssl_data->fd = fd; + ssl_data->ssl_conn = ssl_conn; + ssl_data->ssl_ctx = tmp_ctx; + ssl_data->cancel = cancel; + mailstream_ssl_context_free(ssl_context); + + return ssl_data; + + free_cancel: + mailstream_cancel_free(cancel); + free_ssl_conn: + SSL_free(ssl_conn); + free_ctx: + SSL_CTX_free(tmp_ctx); + mailstream_ssl_context_free(ssl_context); + err: + return NULL; +} + +static struct mailstream_ssl_data * ssl_data_new(int fd, time_t timeout, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * cb_data), void * cb_data) +{ + return ssl_data_new_full(fd, timeout, +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) + TLS_client_method(), +#else + /* Despite their name the SSLv23_*method() functions have nothing to do + * with the availability of SSLv2 or SSLv3. What these functions do is + * negotiate with the peer the highest available SSL/TLS protocol version + * available. The name is as it is for historic reasons. This is a very + * common confusion and is the main reason why these names have been + * deprecated in the latest dev version of OpenSSL. */ + SSLv23_client_method(), +#endif + callback, cb_data); +} + +#else + +static struct mailstream_ssl_context * mailstream_ssl_context_new(gnutls_session session, int fd); +static void mailstream_ssl_context_free(struct mailstream_ssl_context * ssl_ctx); + +#if GNUTLS_VERSION_NUMBER <= 0x020c00 +static int mailstream_gnutls_client_cert_cb(gnutls_session session, + const gnutls_datum *req_ca_rdn, int nreqs, + const gnutls_pk_algorithm *sign_algos, + int sign_algos_length, gnutls_retr_st *st) +#else +static int mailstream_gnutls_client_cert_cb(gnutls_session session, + const gnutls_datum *req_ca_rdn, int nreqs, + const gnutls_pk_algorithm *sign_algos, + int sign_algos_length, gnutls_retr2_st *st) +#endif +{ + struct mailstream_ssl_context * ssl_context = (struct mailstream_ssl_context *)gnutls_session_get_ptr(session); + gnutls_certificate_type type = gnutls_certificate_type_get(session); + + st->ncerts = 0; + + if (ssl_context == NULL) + return 0; + + if (type == GNUTLS_CRT_X509 && ssl_context->client_x509 && ssl_context->client_pkey) { + st->ncerts = 1; +#if GNUTLS_VERSION_NUMBER <= 0x020c00 + st->type = type; +#else + st->cert_type = type; + st->key_type = GNUTLS_PRIVKEY_X509; +#endif + st->cert.x509 = &(ssl_context->client_x509); + st->key.x509 = ssl_context->client_pkey; + st->deinit_all = 0; + } + return 0; +} + +static struct mailstream_ssl_data * ssl_data_new(int fd, time_t timeout, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * cb_data), void * cb_data) +{ + struct mailstream_ssl_data * ssl_data; + gnutls_session session; + struct mailstream_cancel * cancel; + gnutls_certificate_credentials_t xcred; + int r; + struct mailstream_ssl_context * ssl_context = NULL; + unsigned int timeout_value; + + mailstream_ssl_init(); + + if (gnutls_certificate_allocate_credentials (&xcred) != 0) + return NULL; + + r = gnutls_init(&session, GNUTLS_CLIENT); + if (session == NULL || r != 0) + return NULL; + + if (callback != NULL) { + ssl_context = mailstream_ssl_context_new(session, fd); + callback(ssl_context, cb_data); + } + + gnutls_session_set_ptr(session, ssl_context); + gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred); +#if GNUTLS_VERSION_NUMBER <= 0x020c00 + gnutls_certificate_client_set_retrieve_function(xcred, mailstream_gnutls_client_cert_cb); +#else + gnutls_certificate_set_retrieve_function(xcred, mailstream_gnutls_client_cert_cb); +#endif + gnutls_set_default_priority(session); + gnutls_priority_set_direct(session, "NORMAL", NULL); + + gnutls_record_disable_padding(session); + gnutls_dh_set_prime_bits(session, 512); + + gnutls_transport_set_ptr(session, (gnutls_transport_ptr) fd); + + /* lower limits on server key length restriction */ + gnutls_dh_set_prime_bits(session, 512); + + if (timeout == 0) { + timeout_value = mailstream_network_delay.tv_sec * 1000 + mailstream_network_delay.tv_usec / 1000; + } + else { + timeout_value = timeout * 1000; + } +#if GNUTLS_VERSION_NUMBER >= 0x030100 + gnutls_handshake_set_timeout(session, timeout_value); +#endif + + do { + r = gnutls_handshake(session); + } while (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED); + + if (r < 0) { + gnutls_perror(r); + goto free_ssl_conn; + } + + cancel = mailstream_cancel_new(); + if (cancel == NULL) + goto free_ssl_conn; + + r = mailstream_prepare_fd(fd); + if (r < 0) + goto free_cancel; + + ssl_data = malloc(sizeof(* ssl_data)); + if (ssl_data == NULL) + goto err; + + ssl_data->fd = fd; + ssl_data->session = session; + ssl_data->xcred = xcred; + ssl_data->cancel = cancel; + + mailstream_ssl_context_free(ssl_context); + + return ssl_data; + + free_cancel: + mailstream_cancel_free(cancel); + free_ssl_conn: + gnutls_certificate_free_credentials(xcred); + mailstream_ssl_context_free(ssl_context); + gnutls_deinit(session); + err: + return NULL; +} +#endif + +static void ssl_data_free(struct mailstream_ssl_data * ssl_data) +{ + mailstream_cancel_free(ssl_data->cancel); + free(ssl_data); +} + +#ifndef USE_GNUTLS +static void ssl_data_close(struct mailstream_ssl_data * ssl_data) +{ + SSL_free(ssl_data->ssl_conn); + ssl_data->ssl_conn = NULL; + SSL_CTX_free(ssl_data->ssl_ctx); + ssl_data->ssl_ctx = NULL; +#ifdef WIN32 + closesocket(ssl_data->fd); +#else + close(ssl_data->fd); +#endif + ssl_data->fd = -1; +} +#else +static void ssl_data_close(struct mailstream_ssl_data * ssl_data) +{ + gnutls_certificate_free_credentials(ssl_data->xcred); + gnutls_deinit(ssl_data->session); + + MUTEX_LOCK(&ssl_lock); + gnutls_global_deinit(); + MUTEX_UNLOCK(&ssl_lock); + + ssl_data->session = NULL; +#ifdef WIN32 + closesocket(ssl_data->fd); +#else + close(ssl_data->fd); +#endif + ssl_data->fd = -1; +} +#endif + +#endif + +static mailstream_low * mailstream_low_ssl_open_full(int fd, int starttls, time_t timeout, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * cb_data), void * cb_data) +{ +#ifdef USE_SSL + mailstream_low * s; + struct mailstream_ssl_data * ssl_data; + + ssl_data = ssl_data_new(fd, timeout, callback, cb_data); + + if (ssl_data == NULL) + goto err; + + s = mailstream_low_new(ssl_data, mailstream_ssl_driver); + if (s == NULL) + goto free_ssl_data; + mailstream_low_set_timeout(s, timeout); + + return s; + + free_ssl_data: + ssl_data_free(ssl_data); + err: + return NULL; +#else + return NULL; +#endif +} + +mailstream_low * mailstream_low_ssl_open(int fd) +{ + return mailstream_low_ssl_open_timeout(fd, 0); +} + +mailstream_low * mailstream_low_tls_open(int fd) +{ + return mailstream_low_tls_open_timeout(fd, 0); +} + +mailstream_low * mailstream_low_ssl_open_timeout(int fd, time_t timeout) +{ + return mailstream_low_ssl_open_full(fd, 0, timeout, NULL, NULL); +} + +mailstream_low * mailstream_low_tls_open_timeout(int fd, time_t timeout) +{ + return mailstream_low_ssl_open_full(fd, 1, timeout, NULL, NULL); +} + +#ifdef USE_SSL +static int mailstream_low_ssl_close(mailstream_low * s) +{ + struct mailstream_ssl_data * ssl_data; + + ssl_data = (struct mailstream_ssl_data *) s->data; + ssl_data_close(ssl_data); + + return 0; +} + +static void mailstream_low_ssl_free(mailstream_low * s) +{ + struct mailstream_ssl_data * ssl_data; + + ssl_data = (struct mailstream_ssl_data *) s->data; + ssl_data_free(ssl_data); + s->data = NULL; + + free(s); +} + +static int mailstream_low_ssl_get_fd(mailstream_low * s) +{ + struct mailstream_ssl_data * ssl_data; + + ssl_data = (struct mailstream_ssl_data *) s->data; + return ssl_data->fd; +} + +static int wait_read(mailstream_low * s) +{ + struct timeval timeout; + int cancellation_fd; + struct mailstream_ssl_data * ssl_data; + int r; + int cancelled; +#if defined(WIN32) + fd_set fds_read; + HANDLE event; +#elif USE_POLL + struct pollfd pfd[2]; +#else + fd_set fds_read; + int max_fd; +#endif + + ssl_data = (struct mailstream_ssl_data *) s->data; + if (s->timeout == 0) { + timeout = mailstream_network_delay; + } + else { + timeout.tv_sec = s->timeout; + timeout.tv_usec = 0; + } + +#ifdef USE_GNUTLS + if (gnutls_record_check_pending(ssl_data->session) != 0) + return 0; +#endif + + cancellation_fd = mailstream_cancel_get_fd(ssl_data->cancel); +#if defined(WIN32) + FD_ZERO(&fds_read); + FD_SET(cancellation_fd, &fds_read); + event = CreateEvent(NULL, TRUE, FALSE, NULL); + WSAEventSelect(ssl_data->fd, event, FD_READ | FD_CLOSE); + FD_SET(event, &fds_read); + r = WaitForMultipleObjects(fds_read.fd_count, fds_read.fd_array, FALSE, timeout.tv_sec * 1000 + timeout.tv_usec / 1000); + if (WAIT_TIMEOUT == r) { + WSAEventSelect(ssl_data->fd, event, 0); + CloseHandle(event); + return -1; + } + + cancelled = (fds_read.fd_array[r - WAIT_OBJECT_0] == cancellation_fd); + WSAEventSelect(ssl_data->fd, event, 0); + CloseHandle(event); +#elif USE_POLL + pfd[0].fd = ssl_data->fd; + pfd[0].events = POLLIN; + pfd[0].revents = 0; + + pfd[1].fd = cancellation_fd; + pfd[1].events = POLLIN; + pfd[1].revents = 0; + + r = poll(&pfd[0], 2, timeout.tv_sec * 1000 + timeout.tv_usec / 1000); + if (r <= 0) + return -1; + + cancelled = pfd[1].revents & POLLIN; +#else + FD_ZERO(&fds_read); + FD_SET(cancellation_fd, &fds_read); + FD_SET(ssl_data->fd, &fds_read); + max_fd = cancellation_fd > ssl_data->fd ? cancellation_fd : ssl_data->fd; + r = select(max_fd + 1, &fds_read, NULL, NULL, &timeout); + if (r <= 0) + return -1; + cancelled = FD_ISSET(cancellation_fd, &fds_read); +#endif + if (cancelled) { + /* cancelled */ + mailstream_cancel_ack(ssl_data->cancel); + return -1; + } + + return 0; +} + +#ifndef USE_GNUTLS +static ssize_t mailstream_low_ssl_read(mailstream_low * s, + void * buf, size_t count) +{ + struct mailstream_ssl_data * ssl_data; + int r; + + ssl_data = (struct mailstream_ssl_data *) s->data; + + if (mailstream_cancel_cancelled(ssl_data->cancel)) + return -1; + + while (1) { + int ssl_r; + + r = SSL_read(ssl_data->ssl_conn, buf, (int) count); + if (r > 0) + return r; + + ssl_r = SSL_get_error(ssl_data->ssl_conn, r); + switch (ssl_r) { + case SSL_ERROR_NONE: + return r; + + case SSL_ERROR_ZERO_RETURN: + return r; + + case SSL_ERROR_WANT_READ: + r = wait_read(s); + if (r < 0) + return r; + break; + + default: + return -1; + } + } +} +#else +static ssize_t mailstream_low_ssl_read(mailstream_low * s, + void * buf, size_t count) +{ + struct mailstream_ssl_data * ssl_data; + int r; + + ssl_data = (struct mailstream_ssl_data *) s->data; + if (mailstream_cancel_cancelled(ssl_data->cancel)) + return -1; + + while (1) { + r = gnutls_record_recv(ssl_data->session, buf, count); + if (r > 0) + return r; + + switch (r) { + case 0: /* closed connection */ + return -1; + + case GNUTLS_E_REHANDSHAKE: + do { + r = gnutls_handshake(ssl_data->session); + } while (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED); + break; /* re-receive */ + case GNUTLS_E_AGAIN: + case GNUTLS_E_INTERRUPTED: + r = wait_read(s); + if (r < 0) + return r; + break; + + default: + return -1; + } + } +} +#endif + +static int wait_write(mailstream_low * s) +{ + struct timeval timeout; + int r; + int cancellation_fd; + struct mailstream_ssl_data * ssl_data; + int cancelled; + int write_enabled; +#if defined(WIN32) + fd_set fds_read; + fd_set fds_write; + HANDLE event; +#elif USE_POLL + struct pollfd pfd[2]; +#else + fd_set fds_read; + fd_set fds_write; + int max_fd; +#endif + + ssl_data = (struct mailstream_ssl_data *) s->data; + if (mailstream_cancel_cancelled(ssl_data->cancel)) + return -1; + + if (s->timeout == 0) { + timeout = mailstream_network_delay; + } + else { + timeout.tv_sec = s->timeout; + timeout.tv_usec = 0; + } + + cancellation_fd = mailstream_cancel_get_fd(ssl_data->cancel); +#if defined(WIN32) + FD_ZERO(&fds_read); + FD_ZERO(&fds_write); + FD_SET(cancellation_fd, &fds_read); + event = CreateEvent(NULL, TRUE, FALSE, NULL); + WSAEventSelect(ssl_data->fd, event, FD_WRITE | FD_CLOSE); + FD_SET(event, &fds_read); + r = WaitForMultipleObjects(fds_read.fd_count, fds_read.fd_array, FALSE, timeout.tv_sec * 1000 + timeout.tv_usec / 1000); + if (r < 0) { + WSAEventSelect(ssl_data->fd, event, 0); + CloseHandle(event); + return -1; + } + + cancelled = (fds_read.fd_array[r - WAIT_OBJECT_0] == cancellation_fd) /* SEB 20070709 */; + write_enabled = (fds_read.fd_array[r - WAIT_OBJECT_0] == event); + WSAEventSelect(ssl_data->fd, event, 0); + CloseHandle(event); +#elif USE_POLL + pfd[0].fd = ssl_data->fd; + pfd[0].events = POLLOUT; + pfd[0].revents = 0; + + pfd[1].fd = cancellation_fd; + pfd[1].events = POLLIN; + pfd[1].revents = 0; + + r = poll(&pfd[0], 2, timeout.tv_sec * 1000 + timeout.tv_usec / 1000); + if (r <= 0) + return -1; + + cancelled = pfd[1].revents & POLLIN; + write_enabled = pfd[0].revents & POLLOUT; +#else + FD_ZERO(&fds_read); + FD_ZERO(&fds_write); + FD_SET(cancellation_fd, &fds_read); + FD_SET(ssl_data->fd, &fds_write); + + max_fd = cancellation_fd > ssl_data->fd ? cancellation_fd : ssl_data->fd; + r = select(max_fd + 1, &fds_read, &fds_write, NULL, &timeout); + if (r <= 0) + return -1; + + cancelled = FD_ISSET(cancellation_fd, &fds_read); + write_enabled = FD_ISSET(ssl_data->fd, &fds_write); +#endif + + if (cancelled) { + /* cancelled */ + mailstream_cancel_ack(ssl_data->cancel); + return -1; + } + + if (!write_enabled) + return 0; + + return 1; +} + +#ifndef USE_GNUTLS +static ssize_t mailstream_low_ssl_write(mailstream_low * s, + const void * buf, size_t count) +{ + struct mailstream_ssl_data * ssl_data; + int ssl_r; + int r; + + ssl_data = (struct mailstream_ssl_data *) s->data; + r = wait_write(s); + if (r <= 0) + return r; + + r = SSL_write(ssl_data->ssl_conn, buf, (int) count); + if (r > 0) + return r; + + ssl_r = SSL_get_error(ssl_data->ssl_conn, r); + switch (ssl_r) { + case SSL_ERROR_NONE: + return r; + + case SSL_ERROR_ZERO_RETURN: + return -1; + + case SSL_ERROR_WANT_WRITE: + return 0; + + default: + return r; + } +} +#else +static ssize_t mailstream_low_ssl_write(mailstream_low * s, + const void * buf, size_t count) +{ + struct mailstream_ssl_data * ssl_data; + int r; + + ssl_data = (struct mailstream_ssl_data *) s->data; + r = wait_write(s); + if (r <= 0) + return r; + + r = gnutls_record_send(ssl_data->session, buf, count); + if (r > 0) + return r; + + switch (r) { + case 0: + return -1; + + case GNUTLS_E_AGAIN: + case GNUTLS_E_INTERRUPTED: + return 0; + + default: + return r; + } +} +#endif +#endif + +/* mailstream */ + +mailstream * mailstream_ssl_open(int fd) +{ + return mailstream_ssl_open_timeout(fd, 0); +} + +mailstream * mailstream_ssl_open_timeout(int fd, time_t timeout) +{ + return mailstream_ssl_open_with_callback_timeout(fd, timeout, NULL, NULL); +} + +mailstream * mailstream_ssl_open_with_callback(int fd, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data) +{ + return mailstream_ssl_open_with_callback_timeout(fd, 0, callback, data); +} + +mailstream * mailstream_ssl_open_with_callback_timeout(int fd, time_t timeout, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data) +{ +#ifdef USE_SSL + mailstream_low * low; + mailstream * s; + + low = mailstream_low_ssl_open_with_callback_timeout(fd, timeout, callback, data); + if (low == NULL) + goto err; + + s = mailstream_new(low, 8192); + if (s == NULL) + goto free_low; + + return s; + + free_low: + mailstream_low_close(low); + err: + return NULL; +#else + return NULL; +#endif +} + +ssize_t mailstream_ssl_get_certificate(mailstream *stream, unsigned char **cert_DER) +{ +#ifdef USE_SSL + struct mailstream_ssl_data *data = NULL; + ssize_t len = 0; +#ifndef USE_GNUTLS + SSL *ssl_conn = NULL; + X509 *cert = NULL; +#else + gnutls_session session = NULL; + const gnutls_datum *raw_cert_list; + unsigned int raw_cert_list_length; + gnutls_x509_crt cert = NULL; + size_t cert_size; +#endif + + if (cert_DER == NULL || stream == NULL || stream->low == NULL) + return -1; + + data = stream->low->data; + if (data == NULL) + return -1; + +#ifndef USE_GNUTLS + ssl_conn = data->ssl_conn; + if (ssl_conn == NULL) + return -1; + + cert = SSL_get_peer_certificate(ssl_conn); + if (cert == NULL) + return -1; + + len = i2d_X509(cert, NULL); + * cert_DER = malloc(len); + if (* cert_DER == NULL) + return -1; + + i2d_X509(cert, cert_DER); + + X509_free(cert); + + return len; +#else + session = data->session; + raw_cert_list = gnutls_certificate_get_peers(session, &raw_cert_list_length); + + if (raw_cert_list + && gnutls_certificate_type_get(session) == GNUTLS_CRT_X509 + && gnutls_x509_crt_init(&cert) >= 0 + && gnutls_x509_crt_import(cert, &raw_cert_list[0], GNUTLS_X509_FMT_DER) >= 0) { + cert_size = 0; + if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, NULL, &cert_size) + != GNUTLS_E_SHORT_MEMORY_BUFFER) + return -1; + + *cert_DER = malloc (cert_size); + if (*cert_DER == NULL) + return -1; + + if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, *cert_DER, &cert_size) < 0) + return -1; + + len = (ssize_t)cert_size; + gnutls_x509_crt_deinit(cert); + + return len; + } +#endif +#endif + return -1; +} + +static void mailstream_low_ssl_cancel(mailstream_low * s) +{ +#ifdef USE_SSL + struct mailstream_ssl_data * data; + + data = s->data; + mailstream_cancel_notify(data->cancel); +#endif +} + +mailstream_low * mailstream_low_ssl_open_with_callback(int fd, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data) +{ + return mailstream_low_ssl_open_with_callback_timeout(fd, 0, callback, data); +} + +mailstream_low * mailstream_low_ssl_open_with_callback_timeout(int fd, time_t timeout, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data) +{ + return mailstream_low_ssl_open_full(fd, 0, timeout, callback, data); +} + +mailstream_low * mailstream_low_tls_open_with_callback(int fd, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data) +{ + return mailstream_low_tls_open_with_callback_timeout(fd, 0, callback, data); +} + +mailstream_low * mailstream_low_tls_open_with_callback_timeout(int fd, time_t timeout, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data) +{ + return mailstream_low_ssl_open_full(fd, 1, timeout, callback, data); +} + +int mailstream_ssl_set_client_certicate(struct mailstream_ssl_context * ssl_context, + char * filename) +{ +#ifdef USE_SSL +#ifdef USE_GNUTLS + /* not implemented */ + return -1; +#else + SSL_CTX * ctx = (SSL_CTX *)ssl_context->openssl_ssl_ctx; + STACK_OF(X509_NAME) *cert_names; + + cert_names = SSL_load_client_CA_file(filename); + if (cert_names != NULL) { + SSL_CTX_set_client_CA_list(ctx, cert_names); + return 0; + } + else { + return -1; + } +#endif /* USE_GNUTLS */ +#else + return -1; +#endif /* USE_SSL */ +} + +LIBETPAN_EXPORT +int mailstream_ssl_set_client_certificate_data(struct mailstream_ssl_context * ssl_context, + unsigned char *x509_der, size_t len) +{ +#ifdef USE_SSL +#ifndef USE_GNUTLS + X509 *x509 = NULL; + if (x509_der != NULL && len > 0) + x509 = d2i_X509(NULL, (const unsigned char **)&x509_der, len); + ssl_context->client_x509 = (X509 *)x509; + return 0; +#else + gnutls_datum tmp; + int r; + ssl_context->client_x509 = NULL; + if (len == 0) + return 0; + gnutls_x509_crt_init(&(ssl_context->client_x509)); + tmp.data = x509_der; + tmp.size = len; + if ((r = gnutls_x509_crt_import(ssl_context->client_x509, &tmp, GNUTLS_X509_FMT_DER)) < 0) { + gnutls_x509_crt_deinit(ssl_context->client_x509); + ssl_context->client_x509 = NULL; + return -1; + } + return 0; +#endif +#endif + return -1; +} +int mailstream_ssl_set_client_private_key_data(struct mailstream_ssl_context * ssl_context, + unsigned char *pkey_der, size_t len) +{ +#ifdef USE_SSL +#ifndef USE_GNUTLS + EVP_PKEY *pkey = NULL; + if (pkey_der != NULL && len > 0) + pkey = d2i_AutoPrivateKey(NULL, (const unsigned char **)&pkey_der, len); + ssl_context->client_pkey = (EVP_PKEY *)pkey; + return 0; +#else + gnutls_datum tmp; + int r; + ssl_context->client_pkey = NULL; + if (len == 0) + return 0; + gnutls_x509_privkey_init(&(ssl_context->client_pkey)); + tmp.data = pkey_der; + tmp.size = len; + if ((r = gnutls_x509_privkey_import(ssl_context->client_pkey, &tmp, GNUTLS_X509_FMT_DER)) < 0) { + gnutls_x509_privkey_deinit(ssl_context->client_pkey); + ssl_context->client_pkey = NULL; + return -1; + } + return 0; +#endif +#endif + return -1; +} + +int mailstream_ssl_set_server_certicate(struct mailstream_ssl_context * ssl_context, + char * CAfile, char * CApath) +{ +#ifdef USE_SSL +#ifdef USE_GNUTLS + /* not implemented */ + return -1; +#else + SSL_CTX * ctx = (SSL_CTX *)ssl_context->openssl_ssl_ctx; + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, 0); + if (!SSL_CTX_load_verify_locations(ctx, CAfile, CApath)) + return -1; + else + return 0; +#endif /* USE_GNUTLS */ +#else + return -1; +#endif /* USE_SSL */ +} + +LIBETPAN_EXPORT +int mailstream_ssl_set_server_name(struct mailstream_ssl_context * ssl_context, + char * hostname) +{ + int r = -1; + +#ifdef USE_SSL +# ifdef USE_GNUTLS + if (hostname != NULL) { + r = gnutls_server_name_set(ssl_context->session, GNUTLS_NAME_DNS, hostname, strlen(hostname)); + } + else { + r = gnutls_server_name_set(ssl_context->session, GNUTLS_NAME_DNS, "", 0U); + } +# else /* !USE_GNUTLS */ +# if (OPENSSL_VERSION_NUMBER >= 0x10000000L) + if (hostname != NULL) { + /* Unfortunately we can't set this in the openssl session yet since it + * hasn't been created yet; we only have the openssl context at this point. + * We will set it in the openssl session when we create it, soon after the + * client callback that we expect to be calling us (since it is the way the + * client gets our mailstream_ssl_context) returns (see + * ssl_data_new_full()) but we cannot rely on the client persisting it. We + * must therefore take a temporary copy here, which we free once we've set + * it in the openssl session. */ + ssl_context->server_name = strdup(hostname); + } + else { + if (ssl_context->server_name != NULL) { + free(ssl_context->server_name); + } + ssl_context->server_name = NULL; + } + r = 0; +# endif /* (OPENSSL_VERSION_NUMBER >= 0x10000000L) */ +# endif /* !USE_GNUTLS */ +#endif /* USE_SSL */ + + return r; +} + +#ifdef USE_SSL +#ifndef USE_GNUTLS +static struct mailstream_ssl_context * mailstream_ssl_context_new(SSL_CTX * open_ssl_ctx, int fd) +{ + struct mailstream_ssl_context * ssl_ctx; + + ssl_ctx = malloc(sizeof(* ssl_ctx)); + if (ssl_ctx == NULL) + return NULL; + + ssl_ctx->openssl_ssl_ctx = open_ssl_ctx; + ssl_ctx->client_x509 = NULL; + ssl_ctx->client_pkey = NULL; +#if (OPENSSL_VERSION_NUMBER >= 0x10000000L) + ssl_ctx->server_name = NULL; +#endif /* (OPENSSL_VERSION_NUMBER >= 0x10000000L) */ + ssl_ctx->fd = fd; + + return ssl_ctx; +} + +static void mailstream_ssl_context_free(struct mailstream_ssl_context * ssl_ctx) +{ + if (ssl_ctx != NULL) { +#if (OPENSSL_VERSION_NUMBER >= 0x10000000L) + if (ssl_ctx->server_name != NULL) { + free(ssl_ctx->server_name); + } +#endif /* (OPENSSL_VERSION_NUMBER >= 0x10000000L) */ + free(ssl_ctx); + } +} +#else +static struct mailstream_ssl_context * mailstream_ssl_context_new(gnutls_session session, int fd) +{ + struct mailstream_ssl_context * ssl_ctx; + + ssl_ctx = malloc(sizeof(* ssl_ctx)); + if (ssl_ctx == NULL) + return NULL; + + ssl_ctx->session = session; + ssl_ctx->client_x509 = NULL; + ssl_ctx->client_pkey = NULL; + ssl_ctx->fd = fd; + + return ssl_ctx; +} + +static void mailstream_ssl_context_free(struct mailstream_ssl_context * ssl_ctx) +{ + if (ssl_ctx) { + if (ssl_ctx->client_x509) + gnutls_x509_crt_deinit(ssl_ctx->client_x509); + if (ssl_ctx->client_pkey) + gnutls_x509_privkey_deinit(ssl_ctx->client_pkey); + free(ssl_ctx); + } +} +#endif +#endif + +void * mailstream_ssl_get_openssl_ssl_ctx(struct mailstream_ssl_context * ssl_context) +{ +#ifdef USE_SSL +#ifndef USE_GNUTLS + return ssl_context->openssl_ssl_ctx; +#endif +#endif /* USE_SSL */ + return 0; +} + +int mailstream_ssl_get_fd(struct mailstream_ssl_context * ssl_context) +{ + return ssl_context->fd; +} + +static struct mailstream_cancel * mailstream_low_ssl_get_cancel(mailstream_low * s) +{ +#ifdef USE_SSL + struct mailstream_ssl_data * data; + + data = s->data; + return data->cancel; +#else + return NULL; +#endif +} + +carray * mailstream_low_ssl_get_certificate_chain(mailstream_low * s) +{ +#ifdef USE_SSL + struct mailstream_ssl_data * ssl_data; + carray * result; + int skpos; +#ifndef USE_GNUTLS + STACK_OF(X509) * skx; + + ssl_data = (struct mailstream_ssl_data *) s->data; + if (!(skx = SSL_get_peer_cert_chain(ssl_data->ssl_conn))) { + return NULL; + } + + result = carray_new(4); + for(skpos = 0 ; skpos < sk_num((_STACK *) skx) ; skpos ++) { + X509 * x = (X509 *) sk_value((_STACK *) skx, skpos); + unsigned char * p; + MMAPString * str; + int length = i2d_X509(x, NULL); + str = mmap_string_sized_new(length); + p = (unsigned char *) str->str; + str->len = length; + i2d_X509(x, &p); + carray_add(result, str, NULL); + } + + return result; +#else + gnutls_session session = NULL; + const gnutls_datum *raw_cert_list; + unsigned int raw_cert_list_length; + + ssl_data = (struct mailstream_ssl_data *) s->data; + + session = ssl_data->session; + raw_cert_list = gnutls_certificate_get_peers(session, &raw_cert_list_length); + + if (raw_cert_list && gnutls_certificate_type_get(session) == GNUTLS_CRT_X509) { + result = carray_new(4); + for(skpos = 0 ; skpos < raw_cert_list_length ; skpos ++) { + gnutls_x509_crt cert = NULL; + if (gnutls_x509_crt_init(&cert) >= 0 + && gnutls_x509_crt_import(cert, &raw_cert_list[skpos], GNUTLS_X509_FMT_DER) >= 0) { + size_t cert_size = 0; + MMAPString * str = NULL; + unsigned char * p; + + if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, NULL, &cert_size) + == GNUTLS_E_SHORT_MEMORY_BUFFER) { + str = mmap_string_sized_new(cert_size); + p = (unsigned char *) str->str; + str->len = cert_size; + } + if (str != NULL && + gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, p, &cert_size) >= 0) { + carray_add(result, str, NULL); + } else { + return NULL; + } + gnutls_x509_crt_deinit(cert); + } + } + } + + return result; + + return NULL; +#endif +#else + return NULL; +#endif +} diff --git a/Sources/libetpan/data-types/mailstream_ssl.h b/Sources/libetpan/data-types/mailstream_ssl.h new file mode 100644 index 00000000..2ebab4c0 --- /dev/null +++ b/Sources/libetpan/data-types/mailstream_ssl.h @@ -0,0 +1,140 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream_ssl.h,v 1.18 2008/07/03 19:42:27 colinleroy Exp $ + */ + +#ifndef MAILSTREAM_SSL_H + +#define MAILSTREAM_SSL_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* socket */ + +#ifdef LIBETPAN_IOS_DISABLE_SSL +#undef USE_SSL +#endif + +#ifdef USE_SSL +extern mailstream_low_driver * mailstream_ssl_driver; +#endif + +struct mailstream_ssl_context; + +LIBETPAN_EXPORT +mailstream_low * mailstream_low_ssl_open(int fd); + +LIBETPAN_EXPORT +mailstream_low * mailstream_low_ssl_open_timeout(int fd, time_t timeout); + +LIBETPAN_EXPORT +mailstream_low * mailstream_low_tls_open(int fd); + +LIBETPAN_EXPORT +mailstream_low * mailstream_low_tls_open_timeout(int fd, time_t timeout); + +LIBETPAN_EXPORT +mailstream * mailstream_ssl_open(int fd); + +LIBETPAN_EXPORT +mailstream * mailstream_ssl_open_timeout(int fd, time_t timeout); + +LIBETPAN_EXPORT +mailstream * mailstream_ssl_open_with_callback(int fd, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +LIBETPAN_EXPORT +mailstream * mailstream_ssl_open_with_callback_timeout(int fd, time_t timeout, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +LIBETPAN_EXPORT +void mailstream_gnutls_init_not_required(void); + +LIBETPAN_EXPORT +void mailstream_openssl_init_not_required(void); + +LIBETPAN_EXPORT +void mailstream_ssl_init_not_required(void); + +LIBETPAN_EXPORT +ssize_t mailstream_ssl_get_certificate(mailstream *stream, unsigned char **cert_DER); + +LIBETPAN_EXPORT +mailstream_low * mailstream_low_ssl_open_with_callback(int fd, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +LIBETPAN_EXPORT +mailstream_low * mailstream_low_ssl_open_with_callback_timeout(int fd, time_t timeout, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +LIBETPAN_EXPORT +mailstream_low * mailstream_low_tls_open_with_callback(int fd, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +LIBETPAN_EXPORT +mailstream_low * mailstream_low_tls_open_with_callback_timeout(int fd, time_t timeout, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +LIBETPAN_EXPORT +int mailstream_ssl_set_client_certicate(struct mailstream_ssl_context * ssl_context, + char * file_name); + +LIBETPAN_EXPORT +int mailstream_ssl_set_client_certificate_data(struct mailstream_ssl_context * ssl_context, + unsigned char *x509_der, size_t len); +int mailstream_ssl_set_client_private_key_data(struct mailstream_ssl_context * ssl_context, + unsigned char *pkey_der, size_t len); + +LIBETPAN_EXPORT +int mailstream_ssl_set_server_certicate(struct mailstream_ssl_context * ssl_context, + char * CAfile, char * CApath); + +LIBETPAN_EXPORT +int mailstream_ssl_set_server_name(struct mailstream_ssl_context * ssl_context, + char * hostname); + +LIBETPAN_EXPORT +void * mailstream_ssl_get_openssl_ssl_ctx(struct mailstream_ssl_context * ssl_context); + +LIBETPAN_EXPORT +int mailstream_ssl_get_fd(struct mailstream_ssl_context * ssl_context); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/data-types/mailstream_ssl_private.h b/Sources/libetpan/data-types/mailstream_ssl_private.h new file mode 100644 index 00000000..a0d2df9c --- /dev/null +++ b/Sources/libetpan/data-types/mailstream_ssl_private.h @@ -0,0 +1,48 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILSTREAM_SSL_PRIVATE_H + +#define MAILSTREAM_SSL_PRIVATE_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern void mailstream_ssl_init_lock(void); + +extern void mailstream_ssl_uninit_lock(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/data-types/mailstream_types.h b/Sources/libetpan/data-types/mailstream_types.h new file mode 100644 index 00000000..bb437934 --- /dev/null +++ b/Sources/libetpan/data-types/mailstream_types.h @@ -0,0 +1,137 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream_types.h,v 1.17 2011/04/19 12:22:17 hoa Exp $ + */ + +#ifndef MAILSTREAM_TYPES_H + +#define MAILSTREAM_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define LIBETPAN_MAILSTREAM_DEBUG +#ifndef LIBETPAN_CONFIG_H +# include +#endif +#include + +struct _mailstream; + +typedef struct _mailstream mailstream; + +struct _mailstream_low; + +typedef struct _mailstream_low mailstream_low; + +enum { + /* Buffer is a log text string. */ + MAILSTREAM_LOG_TYPE_INFO_RECEIVED, + MAILSTREAM_LOG_TYPE_INFO_SENT, + + /* Buffer is data sent over the network. */ + MAILSTREAM_LOG_TYPE_ERROR_PARSE, + MAILSTREAM_LOG_TYPE_ERROR_RECEIVED, /* no data */ + MAILSTREAM_LOG_TYPE_ERROR_SENT, /* no data */ + + /* Buffer is data sent over the network. */ + MAILSTREAM_LOG_TYPE_DATA_RECEIVED, + MAILSTREAM_LOG_TYPE_DATA_SENT, + MAILSTREAM_LOG_TYPE_DATA_SENT_PRIVATE, /* data is private, for example a password. */ +}; + +struct _mailstream { + size_t buffer_max_size; + + char * write_buffer; + size_t write_buffer_len; + + char * read_buffer; + size_t read_buffer_len; + + mailstream_low * low; + + struct mailstream_cancel * idle; + int idling; + void (* logger)(mailstream * s, int log_type, + const char * str, size_t size, void * logger_context); + void * logger_context; +}; + +struct mailstream_low_driver { + ssize_t (* mailstream_read)(mailstream_low *, void *, size_t); + ssize_t (* mailstream_write)(mailstream_low *, const void *, size_t); + int (* mailstream_close)(mailstream_low *); + int (* mailstream_get_fd)(mailstream_low *); + void (* mailstream_free)(mailstream_low *); + void (* mailstream_cancel)(mailstream_low *); + struct mailstream_cancel * (* mailstream_get_cancel)(mailstream_low *); + /* Returns an array of MMAPString containing DER data or NULL if it's not a SSL connection */ + carray * (* mailstream_get_certificate_chain)(mailstream_low *); + /* Will be called from the main thread */ + int (* mailstream_setup_idle)(mailstream_low *); + int (* mailstream_unsetup_idle)(mailstream_low *); + int (* mailstream_interrupt_idle)(mailstream_low *); +}; + +typedef struct mailstream_low_driver mailstream_low_driver; + +struct _mailstream_low { + void * data; + mailstream_low_driver * driver; + int privacy; + char * identifier; + unsigned long timeout; /* in seconds, 0 will use the global value */ + void (* logger)(mailstream_low * s, int log_type, + const char * str, size_t size, void * logger_context); + void * logger_context; +}; + +typedef void progress_function(size_t current, size_t maximum); + +typedef void mailprogress_function(size_t current, size_t maximum, void * context); + +enum { + MAILSTREAM_IDLE_ERROR, + MAILSTREAM_IDLE_INTERRUPTED, + MAILSTREAM_IDLE_HASDATA, + MAILSTREAM_IDLE_TIMEOUT, + MAILSTREAM_IDLE_CANCELLED +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/data-types/md5.c b/Sources/libetpan/data-types/md5.c new file mode 100644 index 00000000..952b5656 --- /dev/null +++ b/Sources/libetpan/data-types/md5.c @@ -0,0 +1,578 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +/* + * $Id: md5.c,v 1.11 2008/02/20 22:15:50 hoa Exp $ + */ + +/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm +*/ + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. +*/ + +/* do i need all of this just for htonl()? damn. */ +#include +#ifdef WIN32 +# include +#else +# include +# include +# include +#endif + +#include "md5global.h" +#include "md5.h" +#include "hmac-md5.h" + +/* Constants for MD5Transform routine. +*/ + +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +static void MD5Transform PROTO_LIST ((UINT4 [4], const unsigned char [64])); +static void Encode PROTO_LIST + ((unsigned char *, UINT4 *, unsigned int)); +static void Decode PROTO_LIST + ((UINT4 *, const unsigned char *, unsigned int)); +static void MD5_memcpy PROTO_LIST ((POINTER, CONST_POINTER, unsigned int)); +static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int)); + +static unsigned char PADDING[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* F, G, H and I are basic MD5 functions. + + */ +#ifdef I +/* This might be defined via NANA */ +#undef I +#endif + +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits. + + */ + +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. +Rotation is separate from addition to prevent recomputation. +*/ + +#define FF(a, b, c, d, x, s, ac) { (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } +#define GG(a, b, c, d, x, s, ac) { (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } +#define HH(a, b, c, d, x, s, ac) { (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } +#define II(a, b, c, d, x, s, ac) { (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } + +/* MD5 initialization. Begins an MD5 operation, writing a new context. +*/ + +void MD5Init (context) +MD5_CTX *context; /* context */ +{ + context->count[0] = context->count[1] = 0; + + /* Load magic initialization constants. + +*/ + context->state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; +} + +/* MD5 block update operation. Continues an MD5 message-digest + operation, processing another message block, and updating the context. +*/ + +void MD5Update (context, input, inputLen) +MD5_CTX *context; /* context */ +const unsigned char *input; /* input block */ +unsigned int inputLen; /* length of input block */ +{ + unsigned int i, indx, partLen; + + /* Compute number of bytes mod 64 */ + indx = (unsigned int)((context->count[0] >> 3) & 0x3F); + + /* Update number of bits */ + if ((context->count[0] += ((UINT4)inputLen << 3)) + < ((UINT4)inputLen << 3)) + context->count[1]++; + context->count[1] += ((UINT4)inputLen >> 29); + + partLen = 64 - indx; + + /* Transform as many times as possible. + +*/ + if (inputLen >= partLen) { + MD5_memcpy + ((POINTER)&context->buffer[indx], (POINTER)input, partLen); MD5Transform + (context->state, context->buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) + MD5Transform (context->state, &input[i]); + + indx = 0; + } + else + i = 0; + + /* Buffer remaining input */ + MD5_memcpy + ((POINTER)&context->buffer[indx], (POINTER)&input[i], + inputLen-i); + +} + +/* MD5 finalization. Ends an MD5 message-digest operation, writing the + the message digest and zeroizing the context. + + */ + +void MD5Final (digest, context) +unsigned char digest[16]; /* message digest */ +MD5_CTX *context; /* context */ +{ + unsigned char bits[8]; + unsigned int indx, padLen; + + /* Save number of bits */ + Encode (bits, context->count, 8); + + /* Pad out to 56 mod 64. + +*/ + indx = (unsigned int)((context->count[0] >> 3) & 0x3f); + padLen = (indx < 56) ? (56 - indx) : (120 - indx); + MD5Update (context, PADDING, padLen); + + /* Append length (before padding) */ + MD5Update (context, bits, 8); + + /* Store state in digest */ + Encode (digest, context->state, 16); + + /* Zeroize sensitive information. + +*/ + MD5_memset ((POINTER)context, 0, sizeof (*context)); +} + +/* MD5 basic transformation. Transforms state based on block. + + */ + +static void MD5Transform (state, block) +UINT4 state[4]; +const unsigned char block[64]; +{ + UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + Decode (x, block, 64); + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + /* Zeroize sensitive information. + */ + MD5_memset ((POINTER)x, 0, sizeof (x)); +} + +/* Encodes input (UINT4) into output (unsigned char). Assumes len is + a multiple of 4. + + */ + +static void Encode (output, input, len) +unsigned char *output; +UINT4 *input; +unsigned int len; +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) { + output[j] = (unsigned char)(input[i] & 0xff); + output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); + output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); + output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); + } +} + +/* Decodes input (unsigned char) into output (UINT4). Assumes len is + a multiple of 4. + + */ + +static void Decode (output, input, len) +UINT4 *output; +const unsigned char *input; +unsigned int len; +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) + | (((UINT4)input[j+3]) << 24); +} + +/* Note: Replace "for loop" with standard memcpy if possible. + + */ + +static void MD5_memcpy (output, input, len) +POINTER output; +CONST_POINTER input; +unsigned int len; +{ + unsigned int i; + + for (i = 0; i < len; i++) + output[i] = input[i]; +} + +/* Note: Replace "for loop" with standard memset if possible. +*/ + +static void MD5_memset (output, value, len) +POINTER output; +int value; +unsigned int len; +{ + unsigned int i; + + for (i = 0; i < len; i++) + ((char *)output)[i] = (char)value; +} + +void hmac_md5_init(HMAC_MD5_CTX *hmac, + const unsigned char *key, + int key_len) +{ + unsigned char k_ipad[65]; /* inner padding - + * key XORd with ipad + */ + unsigned char k_opad[65]; /* outer padding - + * key XORd with opad + */ + unsigned char tk[16]; + int i; + /* if key is longer than 64 bytes reset it to key=MD5(key) */ + if (key_len > 64) { + + MD5_CTX tctx; + + MD5Init(&tctx); + MD5Update(&tctx, key, key_len); + MD5Final(tk, &tctx); + + key = tk; + key_len = 16; + } + + /* + * the HMAC_MD5 transform looks like: + * + * MD5(K XOR opad, MD5(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + * opad is the byte 0x5c repeated 64 times + * and text is the data being protected + */ + + /* start out by storing key in pads */ + MD5_memset(k_ipad, '\0', sizeof k_ipad); + MD5_memset(k_opad, '\0', sizeof k_opad); + MD5_memcpy( k_ipad, key, key_len); + MD5_memcpy( k_opad, key, key_len); + + /* XOR key with ipad and opad values */ + for (i=0; i<64; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + + MD5Init(&hmac->ictx); /* init inner context */ + MD5Update(&hmac->ictx, k_ipad, 64); /* apply inner pad */ + + MD5Init(&hmac->octx); /* init outer context */ + MD5Update(&hmac->octx, k_opad, 64); /* apply outer pad */ + + /* scrub the pads and key context (if used) */ + MD5_memset(&k_ipad[0], 0, sizeof(k_ipad)); + MD5_memset(&k_opad[0], 0, sizeof(k_opad)); + MD5_memset(&tk[0], 0, sizeof(tk)); + + /* and we're done. */ +} + +/* The precalc and import routines here rely on the fact that we pad + * the key out to 64 bytes and use that to initialize the md5 + * contexts, and that updating an md5 context with 64 bytes of data + * leaves nothing left over; all of the interesting state is contained + * in the state field, and none of it is left over in the count and + * buffer fields. So all we have to do is save the state field; we + * can zero the others when we reload it. Which is why the decision + * was made to pad the key out to 64 bytes in the first place. */ +void hmac_md5_precalc(HMAC_MD5_STATE *state, + const unsigned char *key, + int key_len) +{ + HMAC_MD5_CTX hmac; + unsigned lupe; + + hmac_md5_init(&hmac, key, key_len); + for (lupe = 0; lupe < 4; lupe++) { + state->istate[lupe] = htonl(hmac.ictx.state[lupe]); + state->ostate[lupe] = htonl(hmac.octx.state[lupe]); + } + MD5_memset((POINTER) &hmac, 0, sizeof(hmac)); +} + + +void hmac_md5_import(HMAC_MD5_CTX *hmac, + HMAC_MD5_STATE *state) +{ + unsigned lupe; + MD5_memset((POINTER) hmac, 0, sizeof(HMAC_MD5_CTX)); + for (lupe = 0; lupe < 4; lupe++) { + hmac->ictx.state[lupe] = ntohl(state->istate[lupe]); + hmac->octx.state[lupe] = ntohl(state->ostate[lupe]); + } + /* Init the counts to account for our having applied + * 64 bytes of key; this works out to 0x200 (64 << 3; see + * MD5Update above...) */ + hmac->ictx.count[0] = hmac->octx.count[0] = 0x200; +} + +void hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE], + HMAC_MD5_CTX *hmac) +{ + MD5Final(digest, &hmac->ictx); /* Finalize inner md5 */ + MD5Update(&hmac->octx, digest, 16); /* Update outer ctx */ + MD5Final(digest, &hmac->octx); /* Finalize outer md5 */ +} + + +void hmac_md5(text, text_len, key, key_len, digest) +const unsigned char* text; /* pointer to data stream */ +int text_len; /* length of data stream */ +const unsigned char* key; /* pointer to authentication key */ +int key_len; /* length of authentication key */ +unsigned char *digest; /* caller digest to be filled in */ +{ + MD5_CTX context; + + unsigned char k_ipad[65]; /* inner padding - + * key XORd with ipad + */ + unsigned char k_opad[65]; /* outer padding - + * key XORd with opad + */ + unsigned char tk[16]; + int i; + /* if key is longer than 64 bytes reset it to key=MD5(key) */ + if (key_len > 64) { + + MD5_CTX tctx; + + MD5Init(&tctx); + MD5Update(&tctx, key, key_len); + MD5Final(tk, &tctx); + + key = tk; + key_len = 16; + } + + /* + * the HMAC_MD5 transform looks like: + * + * MD5(K XOR opad, MD5(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + * opad is the byte 0x5c repeated 64 times + * and text is the data being protected + */ + + /* start out by storing key in pads */ + MD5_memset(k_ipad, '\0', sizeof k_ipad); + MD5_memset(k_opad, '\0', sizeof k_opad); + MD5_memcpy( k_ipad, key, key_len); + MD5_memcpy( k_opad, key, key_len); + + /* XOR key with ipad and opad values */ + for (i=0; i<64; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + /* + * perform inner MD5 + */ + + MD5Init(&context); /* init context for 1st + * pass */ + MD5Update(&context, k_ipad, 64); /* start with inner pad */ + MD5Update(&context, text, text_len); /* then text of datagram */ + MD5Final(digest, &context); /* finish up 1st pass */ + + /* + * perform outer MD5 + */ + MD5Init(&context); /* init context for 2nd + * pass */ + MD5Update(&context, k_opad, 64); /* start with outer pad */ + MD5Update(&context, digest, 16); /* then results of 1st + * hash */ + MD5Final(digest, &context); /* finish up 2nd pass */ + +} diff --git a/Sources/libetpan/data-types/md5.h b/Sources/libetpan/data-types/md5.h new file mode 100644 index 00000000..219b7712 --- /dev/null +++ b/Sources/libetpan/data-types/md5.h @@ -0,0 +1,88 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: md5.h,v 1.11 2006/06/02 15:44:29 smarinier Exp $ + */ + +/* MD5.H - header file for MD5C.C + */ + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. +These notices must be retained in any copies of any part of this +documentation and/or software. + */ + +#include "md5global.h" + +#ifndef MD5_H + +#define MD5_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* MD5 context. */ +typedef struct { + UINT4 state[4]; /* state (ABCD) */ + UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ + unsigned char buffer[64]; /* input buffer */ +} MD5_CTX; + +void MD5Init PROTO_LIST ((MD5_CTX *)); +void MD5Update PROTO_LIST + ((MD5_CTX *, const unsigned char *, unsigned int)); +void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *)); + +void hmac_md5 PROTO_LIST ((const unsigned char *, int, const unsigned char *, int, unsigned char *)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/data-types/md5global.h b/Sources/libetpan/data-types/md5global.h new file mode 100644 index 00000000..aed23d2b --- /dev/null +++ b/Sources/libetpan/data-types/md5global.h @@ -0,0 +1,82 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: md5global.h,v 1.7 2006/06/02 15:44:29 smarinier Exp $ + */ + +/* GLOBAL.H - RSAREF types and constants + */ + +#ifndef MD5GLOBAL_H + +#define MD5GLOBAL_H + +#include "md5namespace.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* PROTOTYPES should be set to one if and only if the compiler supports + function argument prototyping. +The following makes PROTOTYPES default to 0 if it has not already + been defined with C compiler flags. + */ +#ifndef PROTOTYPES +#define PROTOTYPES 1 +#endif + +/* POINTER defines a generic pointer type */ +typedef unsigned char *POINTER; +typedef const unsigned char *CONST_POINTER; + +/* UINT2 defines a two byte word */ +typedef unsigned short int UINT2; + +/* UINT4 defines a four byte word */ +typedef unsigned long int UINT4; + +/* PROTO_LIST is defined depending on how PROTOTYPES is defined above. +If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it + returns an empty list. + */ +#if PROTOTYPES +#define PROTO_LIST(list) list +#else +#define PROTO_LIST(list) () +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/data-types/md5namespace.h b/Sources/libetpan/data-types/md5namespace.h new file mode 100644 index 00000000..633fbdc8 --- /dev/null +++ b/Sources/libetpan/data-types/md5namespace.h @@ -0,0 +1,45 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2015 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef MD5NAMESPACE_H + +#define MD5NAMESPACE_H + +#define MD5Init lep_MD5Init +#define MD5Update lep_MD5Update +#define MD5Final lep_MD5Final +#define hmac_md5 lep_hmac_md5 +#define hmac_md5_init lep_hmac_md5_init +#define hmac_md5_precalc lep_hmac_md5_precalc +#define hmac_md5_import lep_hmac_md5_import +#define hmac_md5_final lep_hmac_md5_final + +#endif diff --git a/Sources/libetpan/data-types/mmapstring.c b/Sources/libetpan/data-types/mmapstring.c new file mode 100644 index 00000000..31dd368e --- /dev/null +++ b/Sources/libetpan/data-types/mmapstring.c @@ -0,0 +1,591 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mmapstring.c,v 1.26 2011/03/14 22:49:16 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mmapstring.h" +#include "mmapstring_private.h" + +#include "chash.h" + +#include +#ifdef WIN32 +# include "win_etpan.h" +#else +# include +# include +#endif +#include +#include "libetpan-config.h" +#ifdef LIBETPAN_REENTRANT +#ifdef HAVE_PTHREAD_H +#include +#endif +#endif + +#define MMAPSTRING_MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MMAPSTRING_MIN(a, b) ((a) < (b) ? (a) : (b)) + +#define MMAP_STRING_DEFAULT_CEIL (8 * 1024 * 1024) + +#ifndef MMAP_UNAVAILABLE +#define MMAP_UNAVAILABLE 1 +#endif + +#define DEFAULT_TMP_PATH "/tmp" + +static char tmpdir[PATH_MAX] = DEFAULT_TMP_PATH; + +static size_t mmap_string_ceil = MMAP_STRING_DEFAULT_CEIL; + +/* MMAPString references */ +#ifdef LIBETPAN_REENTRANT +# if HAVE_PTHREAD_H + static pthread_mutex_t mmapstring_lock = PTHREAD_MUTEX_INITIALIZER; +# define MUTEX_LOCK(x) pthread_mutex_lock(x) +# define MUTEX_UNLOCK(x) pthread_mutex_unlock(x) +# elif (defined WIN32) + static CRITICAL_SECTION mmapstring_lock ; +# define MUTEX_LOCK(x) EnterCriticalSection(x) +# define MUTEX_UNLOCK(x) LeaveCriticalSection(x) +# else +# error "What are your threads?" +# endif +#else +# define MUTEX_LOCK(x) +# define MUTEX_UNLOCK(x) +#endif +static chash * mmapstring_hashtable = NULL; + +void mmapstring_init_lock(void) +{ +#if !defined (HAVE_PTHREAD_H) && defined (WIN32) + InitializeCriticalSection(&mmapstring_lock); +#endif +} + +void mmapstring_uninit_lock(void) +{ +#if !defined (HAVE_PTHREAD_H) && defined (WIN32) + DeleteCriticalSection(&mmapstring_lock); +#endif +} + +static void mmapstring_hashtable_init(void) +{ + mmapstring_hashtable = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); +} + +void mmap_string_set_tmpdir(const char * directory) +{ + strncpy(tmpdir, directory, PATH_MAX); + tmpdir[PATH_MAX - 1] = 0; +} + + +int mmap_string_ref(MMAPString * string) +{ + chash * ht; + int r; + chashdatum key; + chashdatum data; + + MUTEX_LOCK(&mmapstring_lock); + + if (mmapstring_hashtable == NULL) { + mmapstring_hashtable_init(); + } + ht = mmapstring_hashtable; + + if (ht == NULL) { + + MUTEX_UNLOCK(&mmapstring_lock); + return -1; + } + + key.data = &string->str; + key.len = sizeof(string->str); + data.data = string; + data.len = 0; + + r = chash_set(mmapstring_hashtable, &key, &data, NULL); + + MUTEX_UNLOCK(&mmapstring_lock); + + if (r < 0) + return r; + + return 0; +} + +int mmap_string_unref(char * str) +{ + MMAPString * string; + chash * ht; + chashdatum key; + chashdatum data; + int r; + + if (str == NULL) + return -1; + + MUTEX_LOCK(&mmapstring_lock); + + ht = mmapstring_hashtable; + + if (ht == NULL) { + + MUTEX_UNLOCK(&mmapstring_lock); + return -1; + } + + key.data = &str; + key.len = sizeof(str); + + r = chash_get(ht, &key, &data); + if (r < 0) + string = NULL; + else + string = data.data; + + if (string != NULL) { + chash_delete(ht, &key, NULL); + if (chash_count(ht) == 0) { + chash_free(ht); + mmapstring_hashtable = NULL; + } + } + + MUTEX_UNLOCK(&mmapstring_lock); + + if (string != NULL) { + mmap_string_free(string); + return 0; + } + else + return -1; +} + + + +/* MMAPString */ + +#define MY_MAXSIZE ((size_t) -1) + +static inline size_t +nearest_power (size_t base, size_t num) +{ + if (num > MY_MAXSIZE / 2) { + return MY_MAXSIZE; + } + else { + size_t n = base; + + while (n < num) + n <<= 1; + + return n; + } +} + +void mmap_string_set_ceil(size_t ceil) +{ + mmap_string_ceil = ceil; +} + +/* Strings. + */ + +/* SEB */ +#ifndef MMAP_UNAVAILABLE +static MMAPString * mmap_string_realloc_file(MMAPString * string) +{ + char * data; + + if (string->fd == -1) { + char tmpfilename[PATH_MAX]; + int fd; + + * tmpfilename = 0; + strcat(tmpfilename, tmpdir); + strcat(tmpfilename, "/libetpan-mmapstring-XXXXXX"); + + fd = mkstemp(tmpfilename); + if (fd == -1) + return NULL; + + if (unlink(tmpfilename) == -1) { + close(fd); + return NULL; + } + + if (ftruncate(fd, string->allocated_len) == -1) { + close(fd); + return NULL; + } + + data = mmap(NULL, string->allocated_len, PROT_WRITE | PROT_READ, + MAP_SHARED, fd, 0); + + if (data == (char *)MAP_FAILED) { + close(fd); + return NULL; + } + + if (string->str != NULL) + memcpy(data, string->str, string->len + 1); + + string->fd = fd; + string->mmapped_size = string->allocated_len; + free(string->str); + string->str = data; + } + else { + if (munmap(string->str, string->mmapped_size) == -1) + return NULL; + + if (ftruncate(string->fd, string->allocated_len) == -1) + return NULL; + + data = mmap(NULL, string->allocated_len, PROT_WRITE | PROT_READ, + MAP_SHARED, string->fd, 0); + + if (data == (char *)MAP_FAILED) + return NULL; + + string->mmapped_size = string->allocated_len; + string->str = data; + } + + return string; +} +#endif + +static MMAPString * mmap_string_realloc_memory(MMAPString * string) +{ + char * tmp; + + tmp = realloc (string->str, string->allocated_len); + + if (tmp == NULL) + string = NULL; + else + string->str = tmp; + + return string; +} + +static MMAPString * +mmap_string_maybe_expand (MMAPString* string, + size_t len) +{ + if (string->len + len >= string->allocated_len) + { + size_t old_size; + MMAPString * newstring; + + old_size = string->allocated_len; + + string->allocated_len = nearest_power (1, string->len + len + 1); + +#ifndef MMAP_UNAVAILABLE + if (string->allocated_len > mmap_string_ceil) + newstring = mmap_string_realloc_file(string); + else { +#endif + newstring = mmap_string_realloc_memory(string); +#ifndef MMAP_UNAVAILABLE + if (newstring == NULL) + newstring = mmap_string_realloc_file(string); + } +#endif + + if (newstring == NULL) + string->allocated_len = old_size; + + return newstring; + } + + return string; +} + +MMAPString* +mmap_string_sized_new (size_t dfl_size) +{ + MMAPString *string; + + string = malloc(sizeof(* string)); + if (string == NULL) + return NULL; + + string->allocated_len = 0; + string->len = 0; + string->str = NULL; + string->fd = -1; + string->mmapped_size = 0; + + if (mmap_string_maybe_expand (string, MMAPSTRING_MAX (dfl_size, 2)) == NULL) { + free(string); + return NULL; + } + + string->str[0] = 0; + + return string; +} + +MMAPString* +mmap_string_new (const char *init) +{ + MMAPString *string; + + string = mmap_string_sized_new (init ? strlen (init) + 2 : 2); + if (string == NULL) + return NULL; + + if (init) + mmap_string_append (string, init); + + return string; +} + +MMAPString* +mmap_string_new_len (const char *init, + size_t len) +{ + MMAPString *string; + + if (len <= 0) + return mmap_string_new (""); + else + { + string = mmap_string_sized_new (len); + if (string == NULL) + return string; + + if (init) + mmap_string_append_len (string, init, len); + + return string; + } +} + +void +mmap_string_free (MMAPString *string) +{ + if (string == NULL) + return; + +/* SEB */ +#ifndef MMAP_UNAVAILABLE + if (string->fd != -1) { + munmap(string->str, string->mmapped_size); + close(string->fd); + } + else +#endif + { + free (string->str); + } + free(string); +} + +MMAPString* +mmap_string_assign (MMAPString *string, + const char *rval) +{ + mmap_string_truncate (string, 0); + if (mmap_string_append (string, rval) == NULL) + return NULL; + + return string; +} + +MMAPString* +mmap_string_truncate (MMAPString *string, + size_t len) +{ + string->len = MMAPSTRING_MIN (len, string->len); + string->str[string->len] = 0; + + return string; +} + +/** + * mmap_string_set_size: + * @string: a #MMAPString + * @len: the new length + * + * Sets the length of a #MMAPString. If the length is less than + * the current length, the string will be truncated. If the + * length is greater than the current length, the contents + * of the newly added area are undefined. (However, as + * always, string->str[string->len] will be a nul byte.) + * + * Return value: @string + **/ +MMAPString* +mmap_string_set_size (MMAPString *string, + size_t len) +{ + if (len >= string->allocated_len) + if (mmap_string_maybe_expand (string, len - string->len) == NULL) + return NULL; + + string->len = len; + string->str[len] = 0; + + return string; +} + +/* +static int in_mapped_zone(MMAPString * string, char * val) +{ + return (val >= string->str) && (val < string->str + string->mmapped_size); +} +*/ + +MMAPString* +mmap_string_insert_len (MMAPString *string, + size_t pos, + const char *val, + size_t len) +{ + if (mmap_string_maybe_expand (string, len) == NULL) + return NULL; + + if (pos < string->len) + memmove (string->str + pos + len, string->str + pos, string->len - pos); + + /* insert the new string */ + memmove (string->str + pos, val, len); + + string->len += len; + + string->str[string->len] = 0; + + return string; +} + +MMAPString* +mmap_string_append (MMAPString *string, + const char *val) +{ + return mmap_string_insert_len (string, string->len, val, strlen(val)); +} + +MMAPString* +mmap_string_append_len (MMAPString *string, + const char *val, + size_t len) +{ + return mmap_string_insert_len (string, string->len, val, len); +} + +MMAPString* +mmap_string_append_c (MMAPString *string, + char c) +{ + return mmap_string_insert_c (string, string->len, c); +} + +MMAPString* +mmap_string_prepend (MMAPString *string, + const char *val) +{ + return mmap_string_insert_len (string, 0, val, strlen(val)); +} + +MMAPString* +mmap_string_prepend_len (MMAPString *string, + const char *val, + size_t len) +{ + return mmap_string_insert_len (string, 0, val, len); +} + +MMAPString* +mmap_string_prepend_c (MMAPString *string, + char c) +{ + return mmap_string_insert_c (string, 0, c); +} + +MMAPString* +mmap_string_insert (MMAPString *string, + size_t pos, + const char *val) +{ + return mmap_string_insert_len (string, pos, val, strlen(val)); +} + +MMAPString* +mmap_string_insert_c (MMAPString *string, + size_t pos, + char c) +{ + if (mmap_string_maybe_expand (string, 1) == NULL) + return NULL; + + /* If not just an append, move the old stuff */ + if (pos < string->len) + memmove (string->str + pos + 1, string->str + pos, string->len - pos); + + string->str[pos] = c; + + string->len += 1; + + string->str[string->len] = 0; + + return string; +} + +MMAPString* +mmap_string_erase (MMAPString *string, + size_t pos, + size_t len) +{ + if ((pos + len) < string->len) + memmove (string->str + pos, string->str + pos + len, + string->len - (pos + len)); + + string->len -= len; + + string->str[string->len] = 0; + + return string; +} diff --git a/Sources/libetpan/data-types/mmapstring.h b/Sources/libetpan/data-types/mmapstring.h new file mode 100644 index 00000000..634e92ad --- /dev/null +++ b/Sources/libetpan/data-types/mmapstring.h @@ -0,0 +1,161 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mmapstring.h,v 1.14 2008/02/28 14:06:27 colinleroy Exp $ + */ + +#ifndef __MMAP_STRING_H__ + +#define __MMAP_STRING_H__ + +#include + +#ifndef LIBETPAN_CONFIG_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* +#define TMPDIR "/tmp" +*/ + +typedef struct _MMAPString MMAPString; + +struct _MMAPString +{ + char * str; + size_t len; + size_t allocated_len; + int fd; + size_t mmapped_size; + /* + char * old_non_mmapped_str; + */ +}; + +/* configure location of mmaped files */ + +LIBETPAN_EXPORT +void mmap_string_set_tmpdir(const char * directory); + +/* Strings + */ +LIBETPAN_EXPORT +MMAPString * mmap_string_new (const char * init); + +LIBETPAN_EXPORT +MMAPString * mmap_string_new_len (const char * init, + size_t len); + +LIBETPAN_EXPORT +MMAPString * mmap_string_sized_new (size_t dfl_size); + +LIBETPAN_EXPORT +void mmap_string_free (MMAPString * string); + +LIBETPAN_EXPORT +MMAPString * mmap_string_assign (MMAPString * string, + const char * rval); + +LIBETPAN_EXPORT +MMAPString * mmap_string_truncate (MMAPString *string, + size_t len); + +LIBETPAN_EXPORT +MMAPString * mmap_string_set_size (MMAPString * string, + size_t len); + +LIBETPAN_EXPORT +MMAPString * mmap_string_insert_len (MMAPString * string, + size_t pos, + const char * val, + size_t len); + +LIBETPAN_EXPORT +MMAPString * mmap_string_append (MMAPString * string, + const char * val); + +LIBETPAN_EXPORT +MMAPString * mmap_string_append_len (MMAPString * string, + const char * val, + size_t len); + +LIBETPAN_EXPORT +MMAPString * mmap_string_append_c (MMAPString * string, + char c); + +LIBETPAN_EXPORT +MMAPString * mmap_string_prepend (MMAPString * string, + const char * val); + +LIBETPAN_EXPORT +MMAPString * mmap_string_prepend_c (MMAPString * string, + char c); + +LIBETPAN_EXPORT +MMAPString * mmap_string_prepend_len (MMAPString * string, + const char * val, + size_t len); + +LIBETPAN_EXPORT +MMAPString * mmap_string_insert (MMAPString * string, + size_t pos, + const char * val); + +LIBETPAN_EXPORT +MMAPString * mmap_string_insert_c (MMAPString *string, + size_t pos, + char c); + +LIBETPAN_EXPORT +MMAPString * mmap_string_erase(MMAPString * string, + size_t pos, + size_t len); + +LIBETPAN_EXPORT +void mmap_string_set_ceil(size_t ceil); + +LIBETPAN_EXPORT +int mmap_string_ref(MMAPString * string); + +LIBETPAN_EXPORT +int mmap_string_unref(char * str); + +#ifdef __cplusplus +} +#endif + + +#endif /* __MMAP_STRING_H__ */ diff --git a/Sources/libetpan/data-types/mmapstring_private.h b/Sources/libetpan/data-types/mmapstring_private.h new file mode 100644 index 00000000..1dd6c207 --- /dev/null +++ b/Sources/libetpan/data-types/mmapstring_private.h @@ -0,0 +1,48 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MMAPSTRING_PRIVATE_H + +#define MMAPSTRING_PRIVATE_H + +#ifdef __cplusplus +extern "C" +{ +#endif + + extern void mmapstring_init_lock(void); + + extern void mmapstring_uninit_lock(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/data-types/timeutils.c b/Sources/libetpan/data-types/timeutils.c new file mode 100644 index 00000000..c25e9f47 --- /dev/null +++ b/Sources/libetpan/data-types/timeutils.c @@ -0,0 +1,162 @@ +#include "timeutils.h" + +/* mkgmtime.c - make time corresponding to a GMT timeval struct + $Id: timeutils.c,v 1.2 2006/12/29 10:35:25 hoa Exp $ + + * Copyright (c) 1998-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any other legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + */ +/* + * Copyright (c) 1987, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Arthur David Olson of the National Cancer Institute. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* +** Adapted from code provided by Robert Elz, who writes: +** The "best" way to do mktime I think is based on an idea of Bob +** Kridle's (so its said...) from a long time ago. (mtxinu!kridle now). +** It does a binary search of the time_t space. Since time_t's are +** just 32 bits, its a max of 32 iterations (even at 64 bits it +** would still be very reasonable). +*/ + +/* + adapted for libEtPan! by DINH V. Hoa +*/ + +#ifndef WRONG +#define WRONG (-1) +#endif /* !defined WRONG */ + +static int tmcomp(struct tm * atmp, struct tm * btmp) +{ + register int result; + + if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && + (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && + (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && + (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && + (result = (atmp->tm_min - btmp->tm_min)) == 0) + result = atmp->tm_sec - btmp->tm_sec; + return result; +} + +time_t mail_mkgmtime(struct tm * tmp) +{ + register int dir; + register int bits; + register int saved_seconds; + time_t t; + struct tm yourtm, *mytm; + + yourtm = *tmp; + saved_seconds = yourtm.tm_sec; + yourtm.tm_sec = 0; + /* + ** Calculate the number of magnitude bits in a time_t + ** (this works regardless of whether time_t is + ** signed or unsigned, though lint complains if unsigned). + */ + for (bits = 0, t = 1; t > 0; ++bits, t <<= 1) + ; + /* + ** If time_t is signed, then 0 is the median value, + ** if time_t is unsigned, then 1 << bits is median. + */ + t = (t < 0) ? 0 : ((time_t) 1 << bits); + + /* Some gmtime() implementations are broken and will return + * NULL for time_ts larger than 40 bits even on 64-bit platforms + * so we'll just cap it at 40 bits */ + if(bits > 40) bits = 40; + + for ( ; ; ) { + mytm = gmtime(&t); + + if(!mytm) return WRONG; + + dir = tmcomp(mytm, &yourtm); + if (dir != 0) { + if (bits-- < 0) + return WRONG; + if (bits < 0) + --t; + else if (dir > 0) + t -= (time_t) 1 << bits; + else + t += (time_t) 1 << bits; + continue; + } + break; + } + t += saved_seconds; + return t; +} diff --git a/Sources/libetpan/data-types/timeutils.h b/Sources/libetpan/data-types/timeutils.h new file mode 100644 index 00000000..10f0a9f5 --- /dev/null +++ b/Sources/libetpan/data-types/timeutils.h @@ -0,0 +1,39 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef TIMEUTILS_H + +#define TIMEUTILS_H + +#include + +time_t mail_mkgmtime(struct tm * tmp); + +#endif diff --git a/Sources/libetpan/driver/Makefile.am b/Sources/libetpan/driver/Makefile.am new file mode 100644 index 00000000..0af0a25f --- /dev/null +++ b/Sources/libetpan/driver/Makefile.am @@ -0,0 +1,43 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +EXTRA_DIST = TODO + +SUBDIRS = implementation interface tools + +noinst_LTLIBRARIES = libdriver.la +libdriver_la_SOURCES = +libdriver_la_LIBADD = \ + implementation/libimplementation.la \ + interface/libinterface.la \ + tools/libtools.la + + diff --git a/Sources/libetpan/driver/TODO b/Sources/libetpan/driver/TODO new file mode 100644 index 00000000..4ba2c46d --- /dev/null +++ b/Sources/libetpan/driver/TODO @@ -0,0 +1,9 @@ +- get_message_list() will disconnect and reconnect POP3 box +- add UID to non-cached drivers, help clients to recognize messages +- move IMAP UID cache to non-cached driver +- fix message size (put it in cache) +- XXX : fetch body in nntp do not use generic_fetch_body +- add flags prototype to add or remove flags +- cache bodystructures +- search is not implemented +- list of folder new implementation diff --git a/Sources/libetpan/driver/implementation/Makefile.am b/Sources/libetpan/driver/implementation/Makefile.am new file mode 100644 index 00000000..a1fb3a15 --- /dev/null +++ b/Sources/libetpan/driver/implementation/Makefile.am @@ -0,0 +1,57 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +SUBDIRS = data-message \ + imap \ + maildir \ + mbox \ + mh \ + mime-message \ + nntp \ + pop3 \ + hotmail \ + db \ + feed + +noinst_LTLIBRARIES = libimplementation.la +libimplementation_la_SOURCES = +libimplementation_la_LIBADD = \ + data-message/libdata-message.la \ + imap/libimap.la \ + maildir/libmaildir.la \ + mbox/libmbox.la \ + mh/libmh.la \ + mime-message/libmime-message.la \ + nntp/libnntp.la \ + pop3/libpop3.la \ + hotmail/libhotmail.la \ + db/libdb.la \ + feed/libfeed.la diff --git a/Sources/libetpan/driver/implementation/data-message/Makefile.am b/Sources/libetpan/driver/implementation/data-message/Makefile.am new file mode 100644 index 00000000..5c7991d9 --- /dev/null +++ b/Sources/libetpan/driver/implementation/data-message/Makefile.am @@ -0,0 +1,41 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +etpaninclude_HEADERS = \ + data_message_driver.h + +AM_CPPFLAGS = -I$(top_builddir)/include \ + -I$(top_srcdir)/src/driver/interface + +noinst_LTLIBRARIES = libdata-message.la + +libdata_message_la_SOURCES = \ + data_message_driver.c diff --git a/Sources/libetpan/driver/implementation/data-message/data_message_driver.c b/Sources/libetpan/driver/implementation/data-message/data_message_driver.c new file mode 100644 index 00000000..fce81fe2 --- /dev/null +++ b/Sources/libetpan/driver/implementation/data-message/data_message_driver.c @@ -0,0 +1,134 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: data_message_driver.c,v 1.12 2008/02/17 13:13:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "data_message_driver.h" + +#include "mailmessage.h" +#include "mailmessage_tools.h" + +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_SYS_MMAN_H +# include +#endif +#include +#include +#include +#include +#include + +static int fetch_size(mailmessage * msg, size_t * result) +{ + struct generic_message_t * msg_data; + + msg_data = msg->msg_data; + * result = msg_data->msg_length; + + return MAIL_NO_ERROR; +} + + +static mailmessage_driver local_data_message_driver = { + /* msg_name */ "data", + + /* msg_initialize */ mailmessage_generic_initialize, + /* msg_uninitialize */ mailmessage_generic_uninitialize, + + /* msg_flush */ mailmessage_generic_flush, + /* msg_check */ NULL, + + /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free, + + /* msg_fetch */ mailmessage_generic_fetch, + /* msg_fetch_header */ mailmessage_generic_fetch_header, + /* msg_fetch_body */ mailmessage_generic_fetch_body, + /* msg_fetch_size */ fetch_size, + /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure, + /* msg_fetch_section */ mailmessage_generic_fetch_section, + /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header, + /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime, + /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body, + /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope, + + /* msg_get_flags */ NULL +}; + +mailmessage_driver * data_message_driver = &local_data_message_driver; + + + +mailmessage * data_message_init(char * data, size_t len) +{ + struct generic_message_t * msg_data; + mailmessage * msg; + int r; + struct mailimf_fields * fields; + + msg = mailmessage_new(); + if (msg == NULL) + goto err; + + r = mailmessage_init(msg, NULL, data_message_driver, 0, len); + if (r < 0) + goto free; + + msg_data = msg->msg_data; + msg_data->msg_fetched = 1; + msg_data->msg_message = data; + msg_data->msg_length = len; + + r = mailmessage_generic_fetch_envelope(msg, &fields); + if (r != MAIL_NO_ERROR) + goto free; + + msg->msg_fields = fields; + + return msg; + + free: + mailmessage_free(msg); + err: + return NULL; +} + +void data_message_detach_mime(mailmessage * msg) +{ + msg->msg_mime = NULL; +} diff --git a/Sources/libetpan/driver/implementation/data-message/data_message_driver.h b/Sources/libetpan/driver/implementation/data-message/data_message_driver.h new file mode 100644 index 00000000..095159de --- /dev/null +++ b/Sources/libetpan/driver/implementation/data-message/data_message_driver.h @@ -0,0 +1,60 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: data_message_driver.h,v 1.5 2007/12/10 21:32:58 hoa Exp $ + */ + +#ifndef DATA_MESSAGE_DRIVER_H + +#define DATA_MESSAGE_DRIVER_H + +#include + +#define LIBETPAN_DATA_MESSAGE + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * data_message_driver; + +LIBETPAN_EXPORT +mailmessage * data_message_init(char * data, size_t len); + +LIBETPAN_EXPORT +void data_message_detach_mime(mailmessage * msg); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/db/Makefile.am b/Sources/libetpan/driver/implementation/db/Makefile.am new file mode 100644 index 00000000..31498b7f --- /dev/null +++ b/Sources/libetpan/driver/implementation/db/Makefile.am @@ -0,0 +1,50 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +etpaninclude_HEADERS = \ + dbdriver.h \ + dbdriver_message.h \ + dbdriver_types.h \ + dbstorage.h + +AM_CPPFLAGS = -I$(top_builddir)/include \ + -I$(top_srcdir)/src/driver/interface \ + -I$(top_srcdir)/src/driver/tools \ + -I$(top_srcdir)/src/low-level/mime \ + -I$(top_srcdir)/src/low-level/imf \ + -I$(top_srcdir)/src/data-types + +noinst_LTLIBRARIES = libdb.la + +libdb_la_SOURCES = \ + dbdriver.c \ + dbdriver_message.c \ + dbstorage.c diff --git a/Sources/libetpan/driver/implementation/db/dbdriver.c b/Sources/libetpan/driver/implementation/db/dbdriver.c new file mode 100644 index 00000000..86691966 --- /dev/null +++ b/Sources/libetpan/driver/implementation/db/dbdriver.c @@ -0,0 +1,1071 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: dbdriver.c,v 1.14 2010/04/05 14:21:35 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "dbdriver.h" +#include "imfcache.h" +#include "generic_cache.h" +#include "libetpan-config.h" +#include "dbdriver_message.h" +#include "mail_cache_db.h" +#include +#include +#include "mailmessage.h" + +static int initialize(mailsession * session); + +static void uninitialize(mailsession * session); + +static int connect_path(mailsession * session, const char * path); + +static int logout(mailsession * session); + +static int expunge_folder(mailsession * session); + +static int status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int recent_number(mailsession * session, const char * mb, + uint32_t * result); + +static int unseen_number(mailsession * session, const char * mb, + uint32_t * result); + +static int messages_number(mailsession * session, const char * mb, + uint32_t * result); + +static int append_message(mailsession * session, + const char * message, size_t size); + +static int append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); + +static int get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +static int check_folder(mailsession * session); + +static int get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result); + +static mailsession_driver local_db_session_driver = { + /* sess_name */ "db", + + /* sess_initialize */ initialize, + /* sess_uninitialize */ uninitialize, + + /* sess_parameters */ NULL, + + /* sess_connect_stream */ NULL, + /* sess_connect_path */ connect_path, + /* sess_starttls */ NULL, + /* sess_login */ NULL, + /* sess_logout */ logout, + /* sess_noop */ NULL, + + /* sess_build_folder_name */ NULL, + /* sess_create_folder */ NULL, + /* sess_delete_folder */ NULL, + /* sess_rename_folder */ NULL, + /* sess_check_folder */ check_folder, + /* sess_examine_folder */ NULL, + /* sess_select_folder */ NULL, + /* sess_expunge_folder */ expunge_folder, + /* sess_status_folder */ status_folder, + /* sess_messages_number */ messages_number, + /* sess_recent_number */ recent_number, + /* sess_unseen_number */ unseen_number, + /* sess_list_folders */ NULL, + /* sess_lsub_folders */ NULL, + /* sess_subscribe_folder */ NULL, + /* sess_unsubscribe_folder */ NULL, + + /* sess_append_message */ append_message, + /* sess_append_message_flags */ append_message_flags, + /* sess_copy_message */ NULL, + /* sess_move_message */ NULL, + + /* sess_get_message */ get_message, + /* sess_get_message_by_uid */ get_message_by_uid, + + /* sess_get_messages_list */ get_messages_list, + /* sess_get_envelopes_list */ get_envelopes_list, + /* sess_remove_message */ NULL, + /* sess_login_sasl */ NULL +}; + +mailsession_driver * db_session_driver = &local_db_session_driver; + +static inline struct db_session_state_data * get_data(mailsession * session) +{ + return session->sess_data; +} + +static int flags_store_process(mailsession * session) +{ + unsigned int i; + MMAPString * mmapstr; + int r; + int res; + struct mail_cache_db * maildb; + struct db_session_state_data * data; + struct mail_flags_store * flags_store; + + data = get_data(session); + + flags_store = data->db_flags_store; + + if (carray_count(flags_store->fls_tab) == 0) + return MAIL_NO_ERROR; + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mail_cache_db_open_lock(data->db_filename, &maildb); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto free_mmapstr; + } + + for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { + mailmessage * msg; + char key[PATH_MAX]; + + msg = carray_get(flags_store->fls_tab, i); + + snprintf(key, sizeof(key), "%lu-flags", (unsigned long) msg->msg_index); + + r = generic_cache_flags_write(maildb, mmapstr, + key, msg->msg_flags); + } + + mail_flags_store_clear(flags_store); + + mail_cache_db_close_unlock(data->db_filename, maildb); + mmap_string_free(mmapstr); + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + +static int db_get_next_msg_number(struct mail_cache_db * maildb, + uint32_t * p_num) +{ + int r; + char key_value[PATH_MAX]; + uint32_t num; + void * serialized; + size_t serialized_len; + int res; + MMAPString * mmapstr; + size_t cur_token; + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(key_value, sizeof(key_value), "next-msg"); + + r = mail_cache_db_get(maildb, key_value, strlen(key_value), + &serialized, &serialized_len); + + if (r >= 0) { + if (mmap_string_append_len(mmapstr, serialized, serialized_len) == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + cur_token = 0; + r = mailimf_cache_int_read(mmapstr, &cur_token, &num); + if (r < 0) + num = 1; + } + else { + num = 1; + } + + mmap_string_set_size(mmapstr, 0); + cur_token = 0; + r = mailimf_cache_int_write(mmapstr, &cur_token, num + 1); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + r = mail_cache_db_put(maildb, key_value, strlen(key_value), + mmapstr->str, mmapstr->len); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto free_mmapstr; + } + + mmap_string_free(mmapstr); + + * p_num = num; + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + +static int db_set_message_list(struct mail_cache_db * maildb, + carray * msglist) +{ + MMAPString * mmapstr; + char key_value[PATH_MAX]; + int r; + unsigned int i; + size_t cur_token; + int res; + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + cur_token = 0; + for(i = 0 ; i < carray_count(msglist) ; i ++) { + uint32_t * msg; + + msg = carray_get(msglist, i); + r = mailimf_cache_int_write(mmapstr, &cur_token, * msg); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + } + + snprintf(key_value, sizeof(key_value), "message-list"); + r = mail_cache_db_put(maildb, key_value, strlen(key_value), + mmapstr->str, mmapstr->len); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmap_string_free(mmapstr); + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + +static int db_get_message_list(struct mail_cache_db * maildb, + carray ** p_msglist) +{ + carray * msglist; + void * serialized; + size_t serialized_len; + int r; + char key_value[PATH_MAX]; + int res; + unsigned int i; + + msglist = carray_new(16); + if (msglist == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(key_value, sizeof(key_value), "message-list"); + r = mail_cache_db_get(maildb, key_value, strlen(key_value), + &serialized, &serialized_len); + if (r >= 0) { + MMAPString * mmapstr; + size_t cur_token; + + /* collect message list */ + + mmapstr = mmap_string_new_len(serialized, serialized_len); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_msglist; + } + + cur_token = 0; + do { + uint32_t num; + uint32_t * msg; + + r = mailimf_cache_int_read(mmapstr, &cur_token, &num); + if (r != MAIL_NO_ERROR) + break; + + msg = malloc(sizeof(* msg)); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + mmap_string_free(mmapstr); + goto free_msglist; + } + * msg = num; + + r = carray_add(msglist, msg, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + free(msg); + mmap_string_free(mmapstr); + goto free_msglist; + } + } while (1); + + mmap_string_free(mmapstr); + } + + * p_msglist = msglist; + + return MAIL_NO_ERROR; + + free_msglist: + for(i = 0 ; i < carray_count(msglist) ; i ++) { + uint32_t * msg; + + msg = carray_get(msglist, i); + free(msg); + } + carray_free(msglist); + err: + return res; +} + +static int initialize(mailsession * session) +{ + struct db_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->db_filename[0] = '\0'; + + data->db_flags_store = mail_flags_store_new(); + if (data->db_flags_store == NULL) + goto free; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free: + free(data); + err: + return MAIL_ERROR_MEMORY; +} + +static void uninitialize(mailsession * session) +{ + struct db_session_state_data * data; + + data = get_data(session); + + flags_store_process(session); + + mail_flags_store_free(data->db_flags_store); + + free(data); + + session->sess_data = NULL; +} + +static int connect_path(mailsession * session, const char * path) +{ + struct db_session_state_data * data; + + data = get_data(session); + + strncpy(data->db_filename, path, sizeof(data->db_filename)); + + return MAIL_NO_ERROR; +} + +static int logout(mailsession * session) +{ + return MAIL_NO_ERROR; +} + +static int expunge_folder(mailsession * session) +{ + int r; + char key_value[PATH_MAX]; + struct mail_cache_db * maildb; + carray * msglist; + unsigned int i; + struct db_session_state_data * data; + int res; + chash * msg_table; + MMAPString * mmapstr; + + data = get_data(session); + + flags_store_process(session); + + r = mail_cache_db_open_lock(data->db_filename, &maildb); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + r = db_get_message_list(maildb, &msglist); + if (r != MAIL_NO_ERROR) { + res = r; + goto close_db; + } + + msg_table = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + if (msg_table == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_msglist; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_msgtable; + } + + i = 0; + while (i < carray_count(msglist)) { + uint32_t num; + uint32_t * msg; + chashdatum key; + chashdatum value; + struct mail_flags * flags; + int deleted; + + msg = carray_get(msglist, i); + num = * msg; + + deleted = 0; + snprintf(key_value, sizeof(key_value), "%lu-flags", + (unsigned long) num); + r = generic_cache_flags_read(maildb, mmapstr, key_value, &flags); + if (r == MAIL_NO_ERROR) { + if ((flags->fl_flags & MAIL_FLAG_DELETED) != 0) + deleted = 1; + } + + if (!deleted) { + snprintf(key_value, sizeof(key_value), "%lu", (unsigned long) num); + key.data = key_value; + key.len = (unsigned int) strlen(key_value); + chash_set(msg_table, &key, &value, NULL); + + snprintf(key_value, sizeof(key_value), "%lu-envelope", + (unsigned long) num); + key.data = key_value; + key.len = (unsigned int) strlen(key_value); + chash_set(msg_table, &key, &value, NULL); + + snprintf(key_value, sizeof(key_value), "%lu-flags", + (unsigned long) num); + key.data = key_value; + key.len = (unsigned int) strlen(key_value); + chash_set(msg_table, &key, &value, NULL); + + i ++; + } + else { + free(msg); + carray_delete(msglist, i); + } + } + + mmap_string_free(mmapstr); + + r = mail_cache_db_clean_up(maildb, msg_table); + + chash_free(msg_table); + + r = db_set_message_list(maildb, msglist); + + for(i = 0 ; i < carray_count(msglist) ; i ++) { + uint32_t * msg; + + msg = carray_get(msglist, i); + free(msg); + } + carray_free(msglist); + + mail_cache_db_close_unlock(data->db_filename, maildb); + + return MAIL_NO_ERROR; + + free_msgtable: + chash_free(msg_table); + free_msglist: + for(i = 0 ; i < carray_count(msglist) ; i ++) { + uint32_t * msg; + + msg = carray_get(msglist, i); + free(msg); + } + close_db: + mail_cache_db_close_unlock(data->db_filename, maildb); + err: + return res; +} + +static int status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + struct mail_cache_db * maildb; + char key_value[PATH_MAX]; + MMAPString * mmapstr; + uint32_t messages; + uint32_t recent; + uint32_t unseen; + struct db_session_state_data * data; + int r; + int res; + carray * msglist; + unsigned int i; + + data = get_data(session); + + flags_store_process(session); + + r = mail_cache_db_open_lock(data->db_filename, &maildb); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + r = db_get_message_list(maildb, &msglist); + if (r != MAIL_NO_ERROR) { + res = r; + goto close_db; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + messages = 0; + recent = 0; + unseen = 0; + for(i = 0 ; i < carray_count(msglist) ; i ++) { + uint32_t num; + uint32_t * msg; + struct mail_flags * flags; + + msg = carray_get(msglist, i); + num = * msg; + free(msg); + carray_set(msglist, i, NULL); + + messages ++; + + snprintf(key_value, sizeof(key_value), "%lu-flags", (unsigned long) num); + + r = generic_cache_flags_read(maildb, mmapstr, key_value, &flags); + if (r == MAIL_NO_ERROR) { + if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) { + recent ++; + } + if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) { + unseen ++; + } + mail_flags_free(flags); + } + } + + mmap_string_free(mmapstr); + + carray_free(msglist); + + mail_cache_db_close_unlock(data->db_filename, maildb); + + * result_messages = messages; + * result_unseen = unseen; + * result_recent = recent; + + return MAIL_NO_ERROR; + + free_list: + for(i = 0 ; i < carray_count(msglist) ; i ++) { + uint32_t * msg; + + msg = carray_get(msglist, i); + if (msg != NULL) + free(msg); + } + carray_free(msglist); + close_db: + mail_cache_db_close_unlock(data->db_filename, maildb); + err: + return res; +} + +static int recent_number(mailsession * session, const char * mb, + uint32_t * result) +{ + uint32_t dummy_messages; + uint32_t dummy_unseen; + + return status_folder(session, mb, + &dummy_messages, result, &dummy_unseen); +} + +static int unseen_number(mailsession * session, const char * mb, + uint32_t * result) +{ + uint32_t dummy_messages; + uint32_t dummy_recent; + + return status_folder(session, mb, + &dummy_messages, &dummy_recent, result); +} + +static int messages_number(mailsession * session, const char * mb, + uint32_t * result) +{ + uint32_t dummy_unseen; + uint32_t dummy_recent; + + return status_folder(session, mb, + result, &dummy_recent, &dummy_unseen); +} + +static int append_message(mailsession * session, + const char * message, size_t size) +{ + return append_message_flags(session, message, size, NULL); +} + +static int append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags) +{ + carray * msglist; + unsigned int i; + uint32_t * msg; + uint32_t num; + char key_value[PATH_MAX]; + MMAPString * mmapstr; + struct mail_cache_db * maildb; + struct db_session_state_data * data; + size_t cur_token; + struct mailimf_fields * fields; + int r; + int res; + + data = get_data(session); + + r = mail_cache_db_open_lock(data->db_filename, &maildb); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + num = 0; + r = db_get_next_msg_number(maildb, &num); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = db_get_message_list(maildb, &msglist); + if (r != MAIL_NO_ERROR) { + res = r; + goto close_db; + } + + msg = malloc(sizeof(* msg)); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_msglist; + } + + * msg = num; + + r = carray_add(msglist, msg, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + free(msg); + goto free_msglist; + } + + r = db_set_message_list(maildb, msglist); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_msglist; + } + + /* free msglist */ + + for(i = 0 ; i < carray_count(msglist) ; i ++) { + msg = carray_get(msglist, i); + free(msg); + } + carray_free(msglist); + + snprintf(key_value, sizeof(key_value), "%lu", (unsigned long) num); + + r = mail_cache_db_put(maildb, key_value, strlen(key_value), + message, size); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto close_db; + } + + /* write envelope */ + + cur_token = 0; + r = mailimf_envelope_fields_parse(message, size, &cur_token, &fields); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_PARSE; + goto close_db; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db; + } + + cur_token = 0; + r = mailimf_cache_fields_write(mmapstr, &cur_token, fields); + if (r != MAIL_NO_ERROR) { + res = r; + mmap_string_free(mmapstr); + goto close_db; + } + + snprintf(key_value, sizeof(key_value), "%lu-envelope", (unsigned long) num); + + r = mail_cache_db_put(maildb, key_value, strlen(key_value), + mmapstr->str, mmapstr->len); + + mmap_string_free(mmapstr); + + mailimf_fields_free(fields); + + /* write flags */ + + if (flags != NULL) { + snprintf(key_value, sizeof(key_value), "%lu-flags", (unsigned long) num); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db; + } + + r = generic_cache_flags_write(maildb, mmapstr, + key_value, flags); + + mmap_string_free(mmapstr); + + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_FILE; + goto close_db; + } + } + + mail_cache_db_close_unlock(data->db_filename, maildb); + + return MAIL_NO_ERROR; + + free_msglist: + for(i = 0 ; i < carray_count(msglist) ; i ++) { + msg = carray_get(msglist, i); + free(msg); + } + carray_free(msglist); + close_db: + mail_cache_db_close_unlock(data->db_filename, maildb); + err: + return res; +} + +static int get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + int r; + char key[PATH_MAX]; + struct mail_cache_db * maildb; + struct db_session_state_data * data; + int res; + carray * msglist; + unsigned int i; + carray * msgtab; + struct mailmessage_list * driver_msglist; + + data = get_data(session); + + r = mail_cache_db_open_lock(data->db_filename, &maildb); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + r = db_get_message_list(maildb, &msglist); + if (r != MAIL_NO_ERROR) { + res = r; + goto close_db; + } + + msgtab = carray_new(16); + if (msgtab == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db; + } + + for(i = 0 ; i < carray_count(msglist) ; i ++) { + uint32_t msg_num; + uint32_t * pmsg_num; + mailmessage * msg; + size_t size; + + pmsg_num = carray_get(msglist, i); + msg_num = * pmsg_num; + free(pmsg_num); + carray_set(msglist, i, NULL); + + snprintf(key, sizeof(key), "%lu", (unsigned long) msg_num); + r = mail_cache_db_get_size(maildb, key, strlen(key), &size); + if (r < 0) { + continue; + } + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = mailmessage_init(msg, session, db_message_driver, + msg_num, size); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg); + res = r; + goto free_list; + } + + r = carray_add(msgtab, msg, NULL); + if (r < 0) { + mailmessage_free(msg); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + carray_free(msglist); + + driver_msglist = mailmessage_list_new(msgtab); + if (driver_msglist == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + mail_cache_db_close_unlock(data->db_filename, maildb); + + * result = driver_msglist; + + return MAIL_NO_ERROR; + + free_list: + for(i = 0 ; i < carray_count(msgtab) ; i ++) { + mailmessage * msg; + + msg = carray_get(msgtab, i); + mailmessage_free(msg); + } + carray_free(msgtab); + + for(i = 0 ; i < carray_count(msglist) ; i ++) { + uint32_t * msg; + + msg = carray_get(msglist, i); + if (msg != NULL) + free(msg); + } + carray_free(msglist); + close_db: + mail_cache_db_close_unlock(data->db_filename, maildb); + err: + return res; +} + +static int get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + unsigned int i; + char key[PATH_MAX]; + int r; + struct mail_cache_db * maildb; + int res; + struct db_session_state_data * data; + MMAPString * mmapstr; + + data = get_data(session); + + flags_store_process(session); + + r = mail_cache_db_open_lock(data->db_filename, &maildb); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + if (msg->msg_fields == NULL) { + snprintf(key, sizeof(key), "%lu-envelope", + (unsigned long) msg->msg_index); + + r = generic_cache_fields_read(maildb, mmapstr, + key, &msg->msg_fields); + } + + if (msg->msg_flags == NULL) { + snprintf(key, sizeof(key), "%lu-flags", + (unsigned long) msg->msg_index); + + r = generic_cache_flags_read(maildb, mmapstr, + key, &msg->msg_flags); + } + } + + mmap_string_free(mmapstr); + + mail_cache_db_close_unlock(data->db_filename, maildb); + + return MAIL_NO_ERROR; + + close_db: + mail_cache_db_close_unlock(data->db_filename, maildb); + err: + return res; +} + +static int check_folder(mailsession * session) +{ + flags_store_process(session); + + return MAIL_NO_ERROR; +} + +static int get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg; + int r; + size_t size; + char key[PATH_MAX]; + struct db_session_state_data * data; + struct mail_cache_db * maildb; + int res; + + data = get_data(session); + + r = mail_cache_db_open_lock(data->db_filename, &maildb); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db; + } + + size = 0; + snprintf(key, sizeof(key), "%lu", (unsigned long) num); + r = mail_cache_db_get_size(maildb, key, (size_t) strlen(key), &size); + /* ignore error */ + + r = mailmessage_init(msg, session, db_message_driver, + num, size); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg); + res = r; + goto close_db; + } + + mail_cache_db_close_unlock(data->db_filename, maildb); + + return MAIL_NO_ERROR; + + close_db: + mail_cache_db_close_unlock(data->db_filename, maildb); + err: + return res; +} + +static int get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result) +{ + uint32_t msg_num; + + msg_num = (uint32_t) strtoul(uid, NULL, 10); + + return get_message(session, msg_num, result); +} diff --git a/Sources/libetpan/driver/implementation/db/dbdriver.h b/Sources/libetpan/driver/implementation/db/dbdriver.h new file mode 100644 index 00000000..5612e838 --- /dev/null +++ b/Sources/libetpan/driver/implementation/db/dbdriver.h @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: dbdriver.h,v 1.2 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef DBDRIVER_H + +#define DBDRIVER_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * db_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/db/dbdriver_message.c b/Sources/libetpan/driver/implementation/db/dbdriver_message.c new file mode 100644 index 00000000..12d9a0b1 --- /dev/null +++ b/Sources/libetpan/driver/implementation/db/dbdriver_message.c @@ -0,0 +1,314 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: dbdriver_message.c,v 1.8 2008/02/17 13:13:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "dbdriver_message.h" +#include "dbdriver.h" +#include "mail_cache_db.h" + +#include "mailmessage_tools.h" +#include "generic_cache.h" + +#include +#ifdef WIN32 +# include "win_etpan.h" +#else +# include +#endif +#include +#include +#include +#include +#include + +static int fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result); + +static int get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +static int prefetch(mailmessage * msg_info); + +static void prefetch_free(struct generic_message_t * msg); + +static int initialize(mailmessage * msg_info); + +static void check(mailmessage * msg_info); + +static mailmessage_driver local_db_message_driver = { + /* msg_name */ "db", + + /* msg_initialize */ initialize, + /* msg_uninitialize */ mailmessage_generic_uninitialize, + + /* msg_flush */ mailmessage_generic_flush, + /* msg_check */ check, + + /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free, + + /* msg_fetch */ mailmessage_generic_fetch, + /* msg_fetch_header */ mailmessage_generic_fetch_header, + /* msg_fetch_body */ mailmessage_generic_fetch_header, + /* msg_fetch_size */ NULL, + /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure, + /* msg_fetch_section */ mailmessage_generic_fetch_section, + /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header, + /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime, + /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body, + /* msg_fetch_envelope */ fetch_envelope, + + /* msg_get_flags */ get_flags +}; + +mailmessage_driver * db_message_driver = &local_db_message_driver; + +struct db_msg_data { + MMAPString * msg_content; +}; + +static inline struct db_session_state_data * +get_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static int prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int res; + struct db_msg_data * data; + struct db_session_state_data * sess_data; + MMAPString * msg_content; + struct mail_cache_db * maildb; + int r; + char key[PATH_MAX]; + void * msg_data; + size_t msg_data_len; + + sess_data = get_session_data(msg_info); + + r = mail_cache_db_open_lock(sess_data->db_filename, &maildb); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + snprintf(key, sizeof(key), "%lu", (unsigned long) msg_info->msg_index); + r = mail_cache_db_get(maildb, key, strlen(key), &msg_data, &msg_data_len); + if (r < 0) { + res = MAIL_ERROR_MSG_NOT_FOUND; + goto close_db; + } + + msg_content = mmap_string_new_len(msg_data, msg_data_len); + if (msg_content == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db; + } + + data = malloc(sizeof(* data)); + if (data == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + data->msg_content = msg_content; + + msg = msg_info->msg_data; + + msg->msg_data = data; + msg->msg_message = msg_content->str; + msg->msg_length = msg_content->len; + + mail_cache_db_close_unlock(sess_data->db_filename, maildb); + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(msg_content); + close_db: + mail_cache_db_close_unlock(sess_data->db_filename, maildb); + err: + return res; +} + +static void prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + struct db_msg_data * data; + + data = msg->msg_data; + mmap_string_free(data->msg_content); + data->msg_content = NULL; + free(data); + msg->msg_message = NULL; + } +} + +static int initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char key[PATH_MAX]; + + snprintf(key, sizeof(key), "%lu", (unsigned long) msg_info->msg_index); + msg_info->msg_uid = strdup(key); + if (msg_info->msg_uid == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + msg->msg_prefetch = prefetch; + msg->msg_prefetch_free = prefetch_free; + + return MAIL_NO_ERROR; +} + +static void check(mailmessage * msg_info) +{ + if (msg_info->msg_flags != NULL) { + mail_flags_store_set(get_session_data(msg_info)->db_flags_store, + msg_info); + /* ignore errors */ + } +} + +static int fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result) +{ + char key[PATH_MAX]; + int r; + struct db_session_state_data * sess_data; + struct mail_cache_db * maildb; + int res; + struct mailimf_fields * fields; + MMAPString * mmapstr; + + sess_data = get_session_data(msg_info); + + r = mail_cache_db_open_lock(sess_data->db_filename, &maildb); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + snprintf(key, sizeof(key), "%lu-envelope", + (unsigned long) msg_info->msg_index); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db; + } + + r = generic_cache_fields_read(maildb, mmapstr, + key, &fields); + + mmap_string_free(mmapstr); + + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_MSG_NOT_FOUND; + goto close_db; + } + + mail_cache_db_close_unlock(sess_data->db_filename, maildb); + + * result = fields; + + return MAIL_NO_ERROR; + + close_db: + mail_cache_db_close_unlock(sess_data->db_filename, maildb); + err: + return res; +} + +static int get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + char key[PATH_MAX]; + int r; + struct db_session_state_data * sess_data; + struct mail_cache_db * maildb; + int res; + MMAPString * mmapstr; + + sess_data = get_session_data(msg_info); + + r = mail_cache_db_open_lock(sess_data->db_filename, &maildb); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + snprintf(key, sizeof(key), "%lu-flags", (unsigned long) msg_info->msg_index); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db; + } + + r = generic_cache_flags_read(maildb, mmapstr, + key, &msg_info->msg_flags); + + mmap_string_free(mmapstr); + + if (r != MAIL_NO_ERROR) { + msg_info->msg_flags = mail_flags_new_empty(); + if (msg_info->msg_flags == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db; + } + } + + mail_cache_db_close_unlock(sess_data->db_filename, maildb); + + * result = msg_info->msg_flags; + + return MAIL_NO_ERROR; + + close_db: + mail_cache_db_close_unlock(sess_data->db_filename, maildb); + err: + return res; +} + diff --git a/Sources/libetpan/driver/implementation/db/dbdriver_message.h b/Sources/libetpan/driver/implementation/db/dbdriver_message.h new file mode 100644 index 00000000..fd5c6bf5 --- /dev/null +++ b/Sources/libetpan/driver/implementation/db/dbdriver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: dbdriver_message.h,v 1.2 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef DBDRIVER_MESSAGE_H + +#define DBDRIVER_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * db_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/db/dbdriver_types.h b/Sources/libetpan/driver/implementation/db/dbdriver_types.h new file mode 100644 index 00000000..31987b3d --- /dev/null +++ b/Sources/libetpan/driver/implementation/db/dbdriver_types.h @@ -0,0 +1,71 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: dbdriver_types.h,v 1.2 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef DBDRIVER_TYPES_H + +#define DBDRIVER_TYPES_H + +#include + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct db_session_state_data { + char db_filename[PATH_MAX]; + struct mail_flags_store * db_flags_store; +}; + +/* db storage */ + +/* + db_mailstorage is the state data specific to the db storage. + + - pathname is the path of the db storage. +*/ + +struct db_mailstorage { + char * db_pathname; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/db/dbstorage.c b/Sources/libetpan/driver/implementation/db/dbstorage.c new file mode 100644 index 00000000..f08ed234 --- /dev/null +++ b/Sources/libetpan/driver/implementation/db/dbstorage.c @@ -0,0 +1,149 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: dbstorage.c,v 1.7 2008/02/17 13:13:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "dbstorage.h" +#include "mailstorage.h" + +#include "mail.h" +#include "mailmessage.h" +#include "dbdriver.h" +#include "maildriver.h" + +#include +#include + +/* db storage */ + +static int db_mailstorage_connect(struct mailstorage * storage); +static int +db_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result); +static void db_mailstorage_uninitialize(struct mailstorage * storage); + +static mailstorage_driver db_mailstorage_driver = { + /* sto_name */ "db", + /* sto_connect */ db_mailstorage_connect, + /* sto_get_folder_session */ db_mailstorage_get_folder_session, + /* sto_uninitialize */ db_mailstorage_uninitialize +}; + +LIBETPAN_EXPORT +int db_mailstorage_init(struct mailstorage * storage, + char * db_pathname) +{ + struct db_mailstorage * db_storage; + + db_storage = malloc(sizeof(* db_storage)); + if (db_storage == NULL) + goto err; + + db_storage->db_pathname = strdup(db_pathname); + if (db_storage->db_pathname == NULL) + goto free; + + storage->sto_data = db_storage; + storage->sto_driver = &db_mailstorage_driver; + + return MAIL_NO_ERROR; + + free: + free(db_storage); + err: + return MAIL_ERROR_MEMORY; +} + +static void db_mailstorage_uninitialize(struct mailstorage * storage) +{ + struct db_mailstorage * db_storage; + + db_storage = storage->sto_data; + free(db_storage->db_pathname); + free(db_storage); + + storage->sto_data = NULL; +} + +static int db_mailstorage_connect(struct mailstorage * storage) +{ + struct db_mailstorage * db_storage; + mailsession_driver * driver; + int r; + int res; + mailsession * session; + + db_storage = storage->sto_data; + + driver = db_session_driver; + + session = mailsession_new(driver); + if (session == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailsession_connect_path(session, db_storage->db_pathname); + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto free; + } + + storage->sto_session = session; + + return MAIL_NO_ERROR; + + free: + mailsession_free(session); + err: + return res; +} + +static int +db_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result) +{ + * result = storage->sto_session; + + return MAIL_NO_ERROR; +} + diff --git a/Sources/libetpan/driver/implementation/db/dbstorage.h b/Sources/libetpan/driver/implementation/db/dbstorage.h new file mode 100644 index 00000000..812d79d2 --- /dev/null +++ b/Sources/libetpan/driver/implementation/db/dbstorage.h @@ -0,0 +1,62 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: dbstorage.h,v 1.3 2005/06/01 12:21:57 smarinier Exp $ + */ + +#ifndef DBSTORAGE_H + +#define DBSTORAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + db_mailstorage_init is the constructor for a DB storage. + + @param storage this is the storage to initialize. + + @param pathname is the directory that contains the mailbox. +*/ + +LIBETPAN_EXPORT +int db_mailstorage_init(struct mailstorage * storage, + char * db_pathname); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/feed/Makefile.am b/Sources/libetpan/driver/implementation/feed/Makefile.am new file mode 100644 index 00000000..fb00471a --- /dev/null +++ b/Sources/libetpan/driver/implementation/feed/Makefile.am @@ -0,0 +1,51 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +etpaninclude_HEADERS = \ + feeddriver.h \ + feeddriver_message.h \ + feeddriver_types.h \ + feedstorage.h + +AM_CPPFLAGS = -I$(top_builddir)/include \ + -I$(top_srcdir)/src/driver/interface \ + -I$(top_srcdir)/src/driver/tools \ + -I$(top_srcdir)/src/low-level/feed \ + -I$(top_srcdir)/src/low-level/mime \ + -I$(top_srcdir)/src/low-level/imf \ + -I$(top_srcdir)/src/data-types + +noinst_LTLIBRARIES = libfeed.la + +libfeed_la_SOURCES = \ + feeddriver.c \ + feeddriver_message.c \ + feedstorage.c diff --git a/Sources/libetpan/driver/implementation/feed/feeddriver.c b/Sources/libetpan/driver/implementation/feed/feeddriver.c new file mode 100644 index 00000000..eaebf900 --- /dev/null +++ b/Sources/libetpan/driver/implementation/feed/feeddriver.c @@ -0,0 +1,796 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: feeddriver.c,v 1.3 2008/04/11 07:33:08 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "feeddriver.h" + +#include +#include +#include + +#include "mailimf_types_helper.h" +#include "newsfeed.h" +#include "mail.h" +#include "mailmessage.h" +#include "maildriver_tools.h" +#include "feeddriver_message.h" +#include "feeddriver_types.h" + +#define MIN_DELAY 5 + +static int feeddriver_initialize(mailsession * session); + +static void feeddriver_uninitialize(mailsession * session); + +static int feeddriver_connect_path(mailsession * session, const char * path); + +static int feeddriver_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, + uint32_t * result_recent, + uint32_t * result_unseen); + +static int feeddriver_messages_number(mailsession * session, const char * mb, + uint32_t * result); + +static int +feeddriver_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + + +static int feeddriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int feeddriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int feeddriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static mailsession_driver local_feed_session_driver = { + /* sess_name */ "feed", + + /* sess_initialize */ feeddriver_initialize, + /* sess_uninitialize */ feeddriver_uninitialize, + + /* sess_parameters */ NULL, + + /* sess_connect_stream */ NULL, + /* sess_connect_path */ feeddriver_connect_path, + /* sess_starttls */ NULL, + /* sess_login */ NULL, + /* sess_logout */ NULL, + /* sess_noop */ NULL, + + /* sess_build_folder_name */ NULL, + /* sess_create_folder */ NULL, + /* sess_delete_folder */ NULL, + /* sess_rename_folder */ NULL, + /* sess_check_folder */ NULL, + /* sess_examine_folder */ NULL, + /* sess_select_folder */ NULL, + /* sess_expunge_folder */ NULL, + /* sess_status_folder */ feeddriver_status_folder, + /* sess_messages_number */ feeddriver_messages_number, + /* sess_recent_number */ feeddriver_messages_number, + /* sess_unseen_number */ feeddriver_messages_number, + /* sess_list_folders */ NULL, + /* sess_lsub_folders */ NULL, + /* sess_subscribe_folder */ NULL, + /* sess_unsubscribe_folder */ NULL, + + /* sess_append_message */ NULL, + /* sess_append_message_flags */ NULL, + /* sess_copy_message */ NULL, + /* sess_move_message */ NULL, + + /* sess_get_message */ feeddriver_get_message, + /* sess_get_message_by_uid */ feeddriver_get_message_by_uid, + + /* sess_get_messages_list */ feeddriver_get_messages_list, + /* sess_get_envelopes_list */ feeddriver_get_envelopes_list, + /* sess_remove_message */ NULL, + + /* sess_login_sasl */ NULL, +}; + + +mailsession_driver * feed_session_driver = &local_feed_session_driver; + +static void update(mailsession * session); + +static int feeddriver_feed_error_to_mail_error(int error) +{ + switch (error) { + case NEWSFEED_NO_ERROR: + return MAIL_NO_ERROR; + + case NEWSFEED_ERROR_CANCELLED: + return MAIL_ERROR_STREAM; + + case NEWSFEED_ERROR_INTERNAL: + return MAIL_ERROR_UNKNOWN; + + case NEWSFEED_ERROR_BADURL: + return MAIL_ERROR_INVAL; + + case NEWSFEED_ERROR_RESOLVE_PROXY: + case NEWSFEED_ERROR_RESOLVE_HOST: + return MAIL_ERROR_CONNECT; + + case NEWSFEED_ERROR_CONNECT: + return MAIL_ERROR_CONNECT; + + case NEWSFEED_ERROR_STREAM: + return MAIL_ERROR_STREAM; + + case NEWSFEED_ERROR_PROTOCOL: + case NEWSFEED_ERROR_PARSE: + return MAIL_ERROR_PARSE; + + case NEWSFEED_ERROR_ACCESS: + return MAIL_ERROR_NO_PERMISSION; + + case NEWSFEED_ERROR_AUTHENTICATION: + return MAIL_ERROR_LOGIN; + + case NEWSFEED_ERROR_FTP: + return MAIL_ERROR_UNKNOWN; + + case NEWSFEED_ERROR_PARTIAL_FILE: + case NEWSFEED_ERROR_FETCH: + return MAIL_ERROR_FETCH; + + case NEWSFEED_ERROR_HTTP: + return MAIL_ERROR_UNKNOWN; + + case NEWSFEED_ERROR_FILE: + return MAIL_ERROR_FILE; + + case NEWSFEED_ERROR_PUT: + return MAIL_ERROR_APPEND; + + case NEWSFEED_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case NEWSFEED_ERROR_SSL: + return MAIL_ERROR_SSL; + + case NEWSFEED_ERROR_LDAP: + return MAIL_ERROR_UNKNOWN; + + case NEWSFEED_ERROR_UNSUPPORTED_PROTOCOL: + return MAIL_ERROR_INVAL; + } + + return MAIL_ERROR_UNKNOWN; +} + +static inline struct feed_session_state_data * +get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline struct newsfeed * get_feed_session(mailsession * session) +{ + return get_data(session)->feed_session; +} + +static int feeddriver_initialize(mailsession * session) +{ + struct feed_session_state_data * data; + struct newsfeed * feed; + + feed = newsfeed_new(); + if (feed == NULL) + goto err; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto free; + + data->feed_session = feed; + data->feed_error = MAIL_NO_ERROR; + session->sess_data = data; + + return MAIL_NO_ERROR; + + free: + newsfeed_free(feed); + err: + return MAIL_ERROR_MEMORY; +} + +static void feeddriver_uninitialize(mailsession * session) +{ + struct feed_session_state_data * data; + + data = get_data(session); + + newsfeed_free(data->feed_session); + free(data); + + session->sess_data = NULL; +} + +static int feeddriver_connect_path(mailsession * session, const char * path) +{ + struct feed_session_state_data * data; + int r; + + data = get_data(session); + r = newsfeed_set_url(data->feed_session, path); + return feeddriver_feed_error_to_mail_error(r); +} + +static int feeddriver_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, + uint32_t * result_recent, + uint32_t * result_unseen) +{ + uint32_t count; + int r; + + r = feeddriver_messages_number(session, mb, &count); + if (r != MAIL_NO_ERROR) + return r; + + * result_messages = count; + * result_recent = count; + * result_unseen = count; + + return MAIL_NO_ERROR; +} + +static int feeddriver_messages_number(mailsession * session, const char * mb, + uint32_t * result) +{ + struct feed_session_state_data * data; + unsigned int count; + int res; + + update(session); + data = get_data(session); + if (data->feed_error != MAIL_NO_ERROR) { + res = data->feed_error; + goto err; + } + + count = newsfeed_item_list_get_count(data->feed_session); + + * result = count; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static void update(mailsession * session) +{ + int r; + struct feed_session_state_data * data; + time_t value; + + data = get_data(session); + + value = time(NULL); + if (data->feed_last_update != (time_t) -1) { + if (value - data->feed_last_update < MIN_DELAY) + return; + } + + r = newsfeed_update(data->feed_session, -1); + data->feed_error = feeddriver_feed_error_to_mail_error(r); + if (data->feed_error == MAIL_NO_ERROR) { + value = time(NULL); + data->feed_last_update = value; + } +} + +static int +feeddriver_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + return MAIL_NO_ERROR; +} + +static inline int to_be_quoted(const char * word, size_t size) +{ + int do_quote; + const char * cur; + size_t i; + + do_quote = 0; + cur = word; + for(i = 0 ; i < size ; i ++) { + switch (* cur) { + case ',': + case ':': + case '!': + case '"': + case '#': + case '$': + case '@': + case '[': + case '\\': + case ']': + case '^': + case '`': + case '{': + case '|': + case '}': + case '~': + case '=': + case '?': + case '_': + do_quote = 1; + break; + default: + if (((unsigned char) * cur) >= 128) + do_quote = 1; + break; + } + cur ++; + } + + return do_quote; +} + +#define MAX_IMF_LINE 72 + +static inline int quote_word(const char * display_charset, + MMAPString * mmapstr, const char * word, size_t size) +{ + const char * cur; + size_t i; + char hex[4]; + int col; + + if (mmap_string_append(mmapstr, "=?") == NULL) + return -1; + if (mmap_string_append(mmapstr, display_charset) == NULL) + return -1; + if (mmap_string_append(mmapstr, "?Q?") == NULL) + return -1; + + col = (int) mmapstr->len; + + cur = word; + for(i = 0 ; i < size ; i ++) { + int do_quote_char; + + if (col + 2 /* size of "?=" */ + + 3 /* max size of newly added character */ + + 1 /* minimum column of string in a + folded header */ >= MAX_IMF_LINE) { + int old_pos; + /* adds a concatened encoded word */ + + if (mmap_string_append(mmapstr, "?=") == NULL) + return -1; + + if (mmap_string_append(mmapstr, " ") == NULL) + return -1; + + old_pos = (int) mmapstr->len; + + if (mmap_string_append(mmapstr, "=?") == NULL) + return -1; + if (mmap_string_append(mmapstr, display_charset) == NULL) + return -1; + if (mmap_string_append(mmapstr, "?Q?") == NULL) + return -1; + + col = (int) mmapstr->len - old_pos; + } + + do_quote_char = 0; + switch (* cur) { + case ',': + case ':': + case '!': + case '"': + case '#': + case '$': + case '@': + case '[': + case '\\': + case ']': + case '^': + case '`': + case '{': + case '|': + case '}': + case '~': + case '=': + case '?': + case '_': + do_quote_char = 1; + break; + + default: + if (((unsigned char) * cur) >= 128) + do_quote_char = 1; + break; + } + + if (do_quote_char) { + snprintf(hex, 4, "=%2.2X", (unsigned char) * cur); + if (mmap_string_append(mmapstr, hex) == NULL) + return -1; + col += 3; + } + else { + if (* cur == ' ') { + if (mmap_string_append_c(mmapstr, '_') == NULL) + return -1; + } + else { + if (mmap_string_append_c(mmapstr, * cur) == NULL) + return -1; + } + col += 3; + } + cur ++; + } + + if (mmap_string_append(mmapstr, "?=") == NULL) + return -1; + + return 0; +} + +static inline void get_word(const char * begin, + const char ** pend, int * pto_be_quoted) +{ + const char * cur; + + cur = begin; + + while ((* cur != ' ') && (* cur != '\t') && (* cur != '\0')) { + cur ++; + } + + if (cur - begin + + 1 /* minimum column of string in a + folded header */ > MAX_IMF_LINE) + * pto_be_quoted = 1; + else + * pto_be_quoted = to_be_quoted(begin, cur - begin); + + * pend = cur; +} + +static char * make_quoted_printable(const char * display_charset, + const char * phrase) +{ + char * str; + const char * cur; + MMAPString * mmapstr; + int r; + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) + return NULL; + + cur = phrase; + while (* cur != '\0') { + const char * begin; + const char * end; + int do_quote; + int quote_words; + + begin = cur; + end = begin; + quote_words = 0; + do_quote = 1; + + while (* cur != '\0') { + get_word(cur, &cur, &do_quote); + if (do_quote) { + quote_words = 1; + end = cur; + } + else + break; + if (* cur != '\0') + cur ++; + } + + if (quote_words) { + r = quote_word(display_charset, mmapstr, begin, end - begin); + if (r < 0) { + mmap_string_free(mmapstr); + return NULL; + } + + if ((* end == ' ') || (* end == '\t')) { + if (mmap_string_append_c(mmapstr, * end) == NULL) { + mmap_string_free(mmapstr); + return NULL; + } + end ++; + } + + if (* end != '\0') { + if (mmap_string_append_len(mmapstr, end, cur - end) == NULL) { + mmap_string_free(mmapstr); + return NULL; + } + } + } + else { + if (mmap_string_append_len(mmapstr, begin, cur - begin) == NULL) { + mmap_string_free(mmapstr); + return NULL; + } + } + + if ((* cur == ' ') || (* cur == '\t')) { + if (mmap_string_append_c(mmapstr, * cur) == 0) { + mmap_string_free(mmapstr); + return NULL; + } + cur ++; + } + } + + str = strdup(mmapstr->str); + if (str == NULL) { + mmap_string_free(mmapstr); + return NULL; + } + + mmap_string_free(mmapstr); + + return str; +} + +static mailmessage * feed_item_to_message(mailsession * session, + unsigned int num, + struct newsfeed_item * item) +{ + struct mailimf_fields * fields; + struct mailimf_date_time * date_time; + time_t time_modified; + struct mailimf_mailbox_list * from; + mailmessage * msg; + char * subject; + const char * subject_const; + char * msg_id; + int r; + const char * author_const; + + from = NULL; + author_const = newsfeed_item_get_author(item); + if (author_const != NULL) { + char * author; + char * addr_spec; + struct mailimf_mailbox * mb; + + author = strdup(author_const); + if (author == NULL) { + goto err; + } + + from = mailimf_mailbox_list_new_empty(); + if (from == NULL) { + free(author); + goto err; + } + addr_spec = strdup("invalid@localhost.local"); + if (addr_spec == NULL) { + free(author); + goto free_from; + } + + /* XXX - encode author with MIME */ + mb = mailimf_mailbox_new(author, addr_spec); + if (mb == NULL) { + free(addr_spec); + free(author); + goto free_from; + } + + r = mailimf_mailbox_list_add(from, mb); + if (r != MAILIMF_NO_ERROR) { + mailimf_mailbox_free(mb); + goto free_from; + } + } + + date_time = NULL; + time_modified = newsfeed_item_get_date_modified(item); + if (time_modified != (time_t) -1) { + date_time = mailimf_get_date(time_modified); + if (date_time == NULL) { + goto free_from; + } + } + + subject = NULL; + subject_const = newsfeed_item_get_title(item); + if (subject_const != NULL) { + subject = make_quoted_printable("utf-8", subject_const); + if (subject == NULL) { + goto free_date; + } + } + + msg_id = mailimf_get_message_id(); + if (msg_id == NULL) { + goto free_subject; + } + + fields = mailimf_fields_new_with_data_all(date_time, + from, + NULL, + NULL, + NULL, + NULL, + NULL, + msg_id, + NULL, + NULL, + subject); + + msg = mailmessage_new(); + r = mailmessage_init(msg, session, feed_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + goto free_fields; + } + msg->msg_fields = fields; + + return msg; + + free_fields: + mailimf_fields_free(fields); + goto err; + free_subject: + free(subject); + free_date: + mailimf_date_time_free(date_time); + free_from: + mailimf_mailbox_list_free(from); + err: + return NULL; +} + +static int feeddriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + unsigned int i; + struct feed_session_state_data * data; + unsigned int count; + struct mailmessage_list * msg_list; + carray * tab; + int res; + int r; + + update(session); + data = get_data(session); + if (data->feed_error != MAIL_NO_ERROR) { + res = data->feed_error; + goto err; + } + + count = newsfeed_item_list_get_count(data->feed_session); + + tab = carray_new(count); + if (tab == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + fprintf(stderr, "count: %i\n", count); + + for(i = 0 ; i < count ; i ++) { + struct newsfeed_item * item; + mailmessage * msg; + + item = newsfeed_get_item(data->feed_session, i); + msg = feed_item_to_message(session, i, item); + r = carray_add(tab, msg, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_tab; + } + } + + msg_list = mailmessage_list_new(tab); + if (msg_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_tab; + } + + * result = msg_list; + + return MAIL_NO_ERROR; + + free_tab: + for(i = 0 ; i < carray_count(tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(tab, i); + mailmessage_free(msg); + } + err: + return res; +} + +static int feeddriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, feed_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int feeddriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ +#if 0 + uint32_t num; + char * p; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + num = strtoul(uid, &p, 10); + if ((p == uid) || (* p != '\0')) + return MAIL_ERROR_INVAL; + + return feeddriver_get_message(session, num, result); +#endif + return MAIL_ERROR_INVAL; + } diff --git a/Sources/libetpan/driver/implementation/feed/feeddriver.h b/Sources/libetpan/driver/implementation/feed/feeddriver.h new file mode 100644 index 00000000..32993836 --- /dev/null +++ b/Sources/libetpan/driver/implementation/feed/feeddriver.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: feeddriver.h,v 1.1 2007/01/18 09:15:01 hoa Exp $ + */ + +#ifndef FEEDDRIVER_H + +#define FEEDDRIVER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * feed_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/feed/feeddriver_message.c b/Sources/libetpan/driver/implementation/feed/feeddriver_message.c new file mode 100644 index 00000000..cb7ed6b9 --- /dev/null +++ b/Sources/libetpan/driver/implementation/feed/feeddriver_message.c @@ -0,0 +1,200 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: feeddriver_message.c,v 1.2 2007/04/07 16:12:14 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "feeddriver_message.h" + +#include "mailmessage_tools.h" +#include "feeddriver.h" +#include "newsfeed.h" +#include +#include + +static int feed_prefetch(mailmessage * msg_info); + +static void feed_prefetch_free(struct generic_message_t * msg); + +static int feed_initialize(mailmessage * msg_info); + +static int feed_fetch_size(mailmessage * msg_info, + size_t * result); + +static mailmessage_driver local_feed_message_driver = { + /* msg_name */ "feed", + + /* msg_initialize */ feed_initialize, + /* msg_uninitialize */ mailmessage_generic_uninitialize, + + /* msg_flush */ mailmessage_generic_flush, + /* msg_check */ NULL, + + /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free, + + /* msg_fetch */ mailmessage_generic_fetch, + /* msg_fetch_header */ mailmessage_generic_fetch_header, + /* msg_fetch_body */ mailmessage_generic_fetch_body, + /* msg_fetch_size */ feed_fetch_size, + /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure, + /* msg_fetch_section */ mailmessage_generic_fetch_section, + /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header, + /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime, + /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body, + /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope, + + /* msg_get_flags */ NULL, +}; + +mailmessage_driver * feed_message_driver = &local_feed_message_driver; + +static inline struct feed_session_state_data * +get_data(mailmessage * msg_info) +{ + return msg_info->msg_session->sess_data; +} + +static inline struct newsfeed * get_feed_session(mailmessage * msg_info) +{ + return get_data(msg_info)->feed_session; +} + +static int feed_prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + MMAPString * str; + const char * text; + int col; + struct newsfeed * feed; + struct newsfeed_item * item; + int res; + + feed = get_feed_session(msg_info); + item = newsfeed_get_item(feed, msg_info->msg_index); + + str = mmap_string_new(""); + if (str == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + col = 0; + r = mailimf_fields_write_mem(str, &col, + msg_info->msg_fields); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto free_str; + } + + if (mmap_string_append(str, "\r\n") == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_str; + } + + text = newsfeed_item_get_text(item); + if (text == NULL) { + /* if no content, fallback on summary */ + text = newsfeed_item_get_summary(item); + } + if (mmap_string_append(str, text) == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_str; + } + + msg = msg_info->msg_data; + msg->msg_message = str->str; + msg->msg_length = str->len; + + mmap_string_ref(str); + + return MAIL_NO_ERROR; + + free_str: + mmap_string_free(str); + err: + return res; +} + +static void feed_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static int feed_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + char static_uid[20]; + + snprintf(static_uid, 20, "%u", msg_info->msg_index); + uid = strdup(static_uid); + if (uid == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + return r; + } + + msg = msg_info->msg_data; + msg->msg_prefetch = feed_prefetch; + msg->msg_prefetch_free = feed_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; +} + +static int feed_fetch_size(mailmessage * msg_info, + size_t * result) +{ + int r; + struct generic_message_t * msg; + struct mailmime * mime; + + r = mailmessage_generic_get_bodystructure(msg_info, &mime); + if (r != MAIL_NO_ERROR) { + return r; + } + + msg = msg_info->msg_data; + return (int) msg->msg_length; +} diff --git a/Sources/libetpan/driver/implementation/feed/feeddriver_message.h b/Sources/libetpan/driver/implementation/feed/feeddriver_message.h new file mode 100644 index 00000000..2242b140 --- /dev/null +++ b/Sources/libetpan/driver/implementation/feed/feeddriver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: feeddriver_message.h,v 1.1 2007/01/18 09:15:01 hoa Exp $ + */ + +#ifndef FEEDDRIVER_MESSAGE_H + +#define FEEDDRIVER_MESSAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +extern mailmessage_driver * feed_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/feed/feeddriver_types.h b/Sources/libetpan/driver/implementation/feed/feeddriver_types.h new file mode 100644 index 00000000..16079714 --- /dev/null +++ b/Sources/libetpan/driver/implementation/feed/feeddriver_types.h @@ -0,0 +1,68 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: feeddriver_types.h,v 1.1 2007/01/18 09:15:01 hoa Exp $ + */ + +#ifndef FEEDDRIVER_TYPES_H + +#define FEEDDRIVER_TYPES_H + +#include + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct feed_session_state_data { + time_t feed_last_update; + struct newsfeed * feed_session; + int feed_error; +}; + +struct feed_mailstorage { + char * feed_url; + + int feed_cached; + char * feed_cache_directory; + char * feed_flags_directory; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/feed/feedstorage.c b/Sources/libetpan/driver/implementation/feed/feedstorage.c new file mode 100644 index 00000000..183f499c --- /dev/null +++ b/Sources/libetpan/driver/implementation/feed/feedstorage.c @@ -0,0 +1,183 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: feedstorage.c,v 1.1 2007/01/18 09:15:01 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "feedstorage.h" + +#include +#include + +#include "maildriver.h" +#include "feeddriver.h" +#include "mailstorage_tools.h" +#include "mail.h" + +/* feed storage */ + +#define FEED_DEFAULT_PORT 119 +#define FEEDS_DEFAULT_PORT 563 + +static int feed_mailstorage_connect(struct mailstorage * storage); +static int feed_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result); +static void feed_mailstorage_uninitialize(struct mailstorage * storage); + +static mailstorage_driver feed_mailstorage_driver = { + /* sto_name */ "feed", + /* sto_connect */ feed_mailstorage_connect, + /* sto_get_folder_session */ feed_mailstorage_get_folder_session, + /* sto_uninitialize */ feed_mailstorage_uninitialize, +}; + +int feed_mailstorage_init(struct mailstorage * storage, + const char * feed_url, + int feed_cached, const char * feed_cache_directory, + const char * feed_flags_directory) +{ + struct feed_mailstorage * feed_storage; + int res; + + feed_storage = malloc(sizeof(* feed_storage)); + if (feed_storage == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + feed_storage->feed_url = strdup(feed_url); + if (feed_storage->feed_url == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + feed_storage->feed_cached = feed_cached; + + if (feed_cached && (feed_cache_directory != NULL) && + (feed_flags_directory != NULL)) { + feed_storage->feed_cache_directory = strdup(feed_cache_directory); + if (feed_storage->feed_cache_directory == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_url; + } + feed_storage->feed_flags_directory = strdup(feed_flags_directory); + if (feed_storage->feed_flags_directory == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_cache_directory; + } + } + else { + feed_storage->feed_cached = FALSE; + feed_storage->feed_cache_directory = NULL; + feed_storage->feed_flags_directory = NULL; + } + + storage->sto_data = feed_storage; + storage->sto_driver = &feed_mailstorage_driver; + + return MAIL_NO_ERROR; + + free_cache_directory: + free(feed_storage->feed_cache_directory); + free_url: + free(feed_storage->feed_url); + free: + free(feed_storage); + err: + return res; +} + +static void feed_mailstorage_uninitialize(struct mailstorage * storage) +{ + struct feed_mailstorage * feed_storage; + + feed_storage = storage->sto_data; + + if (feed_storage->feed_flags_directory != NULL) + free(feed_storage->feed_flags_directory); + if (feed_storage->feed_cache_directory != NULL) + free(feed_storage->feed_cache_directory); + free(feed_storage->feed_url); + free(feed_storage); + + storage->sto_data = NULL; +} + +static int feed_mailstorage_connect(struct mailstorage * storage) +{ + struct feed_mailstorage * feed_storage; + mailsession_driver * driver; + int r; + int res; + mailsession * session; + + feed_storage = storage->sto_data; + driver = feed_session_driver; + + session = mailsession_new(driver); + if (session == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailsession_connect_path(session, feed_storage->feed_url); + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto free; + } + + storage->sto_session = session; + + return MAIL_NO_ERROR; + + free: + mailsession_free(session); + err: + return res; +} + +static int feed_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result) +{ + * result = storage->sto_session; + + return MAIL_NO_ERROR; +} diff --git a/Sources/libetpan/driver/implementation/feed/feedstorage.h b/Sources/libetpan/driver/implementation/feed/feedstorage.h new file mode 100644 index 00000000..b8ed0df8 --- /dev/null +++ b/Sources/libetpan/driver/implementation/feed/feedstorage.h @@ -0,0 +1,72 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: feedstorage.h,v 1.1 2007/01/18 09:15:01 hoa Exp $ + */ + +#ifndef FEEDSTORAGE_H + +#define FEEDSTORAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + feed_mailstorage_init is the constructor for a FEED storage + + @param storage this is the storage to initialize. + + @param feed_url this is the URL of the feed. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache + + @param flags_directory is the location of the flags +*/ + +LIBETPAN_EXPORT +int feed_mailstorage_init(struct mailstorage * storage, + const char * feed_url, + int feed_cached, const char * feed_cache_directory, + const char * feed_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/hotmail/Makefile.am b/Sources/libetpan/driver/implementation/hotmail/Makefile.am new file mode 100644 index 00000000..169b6a80 --- /dev/null +++ b/Sources/libetpan/driver/implementation/hotmail/Makefile.am @@ -0,0 +1,42 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +etpaninclude_HEADERS = \ + hotmailstorage.h + +AM_CPPFLAGS = -I$(top_builddir)/include \ + -I$(top_srcdir)/src/driver/interface \ + -I$(top_srcdir)/src/driver/implementation/pop3 + +noinst_LTLIBRARIES = libhotmail.la + +libhotmail_la_SOURCES = \ + hotmailstorage.c diff --git a/Sources/libetpan/driver/implementation/hotmail/hotmailstorage.c b/Sources/libetpan/driver/implementation/hotmail/hotmailstorage.c new file mode 100644 index 00000000..9f35743c --- /dev/null +++ b/Sources/libetpan/driver/implementation/hotmail/hotmailstorage.c @@ -0,0 +1,67 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: hotmailstorage.c,v 1.4 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "hotmailstorage.h" + +#include "pop3storage.h" +#include "pop3driver_types.h" + +/* + hotway is a gateway from hotmail to POP3 + + http://hotwayd.sourceforge.net/ +*/ + +static char hotway_command[512] = "/usr/bin/hotwayd"; + +LIBETPAN_EXPORT +int hotmail_mailstorage_init(struct mailstorage * storage, + char * hotmail_login, char * hotmail_password, + int hotmail_cached, char * hotmail_cache_directory, + char * hotmail_flags_directory) +{ + return pop3_mailstorage_init(storage, + "hotmail.dummy", 0, + hotway_command, + CONNECTION_TYPE_COMMAND, POP3_AUTH_TYPE_PLAIN, + hotmail_login, hotmail_password, + hotmail_cached, hotmail_cache_directory, + hotmail_flags_directory); +} + diff --git a/Sources/libetpan/driver/implementation/hotmail/hotmailstorage.h b/Sources/libetpan/driver/implementation/hotmail/hotmailstorage.h new file mode 100644 index 00000000..d61614fb --- /dev/null +++ b/Sources/libetpan/driver/implementation/hotmail/hotmailstorage.h @@ -0,0 +1,57 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: hotmailstorage.h,v 1.3 2005/06/01 12:21:58 smarinier Exp $ + */ + +#ifndef HOTMAILSTORAGE_H + +#define HOTMAILSTORAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailstorage_types.h" + +LIBETPAN_EXPORT +int hotmail_mailstorage_init(struct mailstorage * storage, + char * hotmail_login, char * hotmail_password, + int hotmail_cached, char * hotmail_cache_directory, + char * hotmail_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Sources/libetpan/driver/implementation/imap/Makefile.am b/Sources/libetpan/driver/implementation/imap/Makefile.am new file mode 100644 index 00000000..a6f26a43 --- /dev/null +++ b/Sources/libetpan/driver/implementation/imap/Makefile.am @@ -0,0 +1,58 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +etpaninclude_HEADERS = \ + imapdriver.h \ + imapdriver_message.h \ + imapdriver_cached.h \ + imapdriver_cached_message.h \ + imapdriver_types.h \ + imapstorage.h \ + imapdriver_tools.h \ + imapdriver_tools_private.h + +AM_CPPFLAGS = -I$(top_builddir)/include \ + -I$(top_srcdir)/src/driver/interface \ + -I$(top_srcdir)/src/driver/tools \ + -I$(top_srcdir)/src/low-level/imap \ + -I$(top_srcdir)/src/low-level/mime \ + -I$(top_srcdir)/src/low-level/imf \ + -I$(top_srcdir)/src/data-types + +noinst_LTLIBRARIES = libimap.la + +libimap_la_SOURCES = \ + imapdriver.c \ + imapdriver_cached.c \ + imapdriver_cached_message.c \ + imapdriver_message.c \ + imapdriver_tools.h imapdriver_tools.c \ + imapstorage.c diff --git a/Sources/libetpan/driver/implementation/imap/imapdriver.c b/Sources/libetpan/driver/implementation/imap/imapdriver.c new file mode 100644 index 00000000..9ba5a1f4 --- /dev/null +++ b/Sources/libetpan/driver/implementation/imap/imapdriver.c @@ -0,0 +1,1290 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver.c,v 1.59 2010/04/05 14:21:35 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "imapdriver.h" + +#include "mail.h" +#include "imapdriver_tools.h" +#include "imapdriver_tools_private.h" +#include "mailmessage.h" +#include "imapdriver_message.h" +#include "imapdriver_types.h" +#include "maildriver.h" +#include "maildriver_tools.h" +#include "generic_cache.h" + +#include +#include + +static int imapdriver_initialize(mailsession * session); + +static void imapdriver_uninitialize(mailsession * session); + +static int imapdriver_connect_stream(mailsession * session, mailstream * s); + +static int imapdriver_starttls(mailsession * session); + +static int imapdriver_login(mailsession * session, + const char * userid, const char * password); + +static int imapdriver_logout(mailsession * session); + +static int imapdriver_noop(mailsession * session); + +static int imapdriver_build_folder_name(mailsession * session, const char * mb, + const char * name, char ** result); + +static int imapdriver_create_folder(mailsession * session, const char * mb); + +static int imapdriver_delete_folder(mailsession * session, const char * mb); + +static int imapdriver_rename_folder(mailsession * session, const char * mb, + const char * new_name); + +static int imapdriver_check_folder(mailsession * session); + +static int imapdriver_examine_folder(mailsession * session, const char * mb); + +static int imapdriver_select_folder(mailsession * session, const char * mb); +static int imapdriver_expunge_folder(mailsession * session); + +static int imapdriver_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int imapdriver_messages_number(mailsession * session, const char * mb, + uint32_t * result); + +static int imapdriver_recent_number(mailsession * session, const char * mb, + uint32_t * result); + +static int imapdriver_unseen_number(mailsession * session, const char * mb, + uint32_t * result); + +static int imapdriver_list_folders(mailsession * session, const char * mb, + struct mail_list ** result); +static int imapdriver_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result); +static int imapdriver_subscribe_folder(mailsession * session, const char * mb); +static int imapdriver_unsubscribe_folder(mailsession * session, const char * mb); +static int imapdriver_append_message(mailsession * session, + const char * message, size_t size); +static int imapdriver_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); +static int imapdriver_copy_message(mailsession * session, + uint32_t num, const char * mb); + +static int imapdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int +imapdriver_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + + +#if 0 +static int imapdriver_search_messages(mailsession * session, const char * charset, + struct mail_search_key * key, + struct mail_search_result ** result); +#endif + +static int imapdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int imapdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static int imapdriver_login_sasl(mailsession * session, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); + +static int imapdriver_remove_message(mailsession * session, uint32_t num); + +static int imapdriver_parameters(mailsession * session, + int id, void * value); + +static mailsession_driver local_imap_session_driver = { + /* sess_name */ "imap", + + /* sess_initialize */ imapdriver_initialize, + /* sess_uninitialize */ imapdriver_uninitialize, + + /* sess_parameters */ imapdriver_parameters, + + /* sess_connect_stream */ imapdriver_connect_stream, + /* sess_connect_path */ NULL, + /* sess_starttls */ imapdriver_starttls, + /* sess_login */ imapdriver_login, + /* sess_logout */ imapdriver_logout, + /* sess_noop */ imapdriver_noop, + + /* sess_build_folder_name */ imapdriver_build_folder_name, + /* sess_create_folder */ imapdriver_create_folder, + /* sess_delete_folder */ imapdriver_delete_folder, + /* sess_rename_folder */ imapdriver_rename_folder, + /* sess_check_folder */ imapdriver_check_folder, + /* sess_examine_folder */ imapdriver_examine_folder, + /* sess_select_folder */ imapdriver_select_folder, + /* sess_expunge_folder */ imapdriver_expunge_folder, + /* sess_status_folder */ imapdriver_status_folder, + /* sess_messages_number */ imapdriver_messages_number, + /* sess_recent_number */ imapdriver_recent_number, + /* sess_unseen_number */ imapdriver_unseen_number, + /* sess_list_folders */ imapdriver_list_folders, + /* sess_lsub_folders */ imapdriver_lsub_folders, + /* sess_subscribe_folder */ imapdriver_subscribe_folder, + /* sess_unsubscribe_folder */ imapdriver_unsubscribe_folder, + + /* sess_append_message */ imapdriver_append_message, + /* sess_append_message_flags */ imapdriver_append_message_flags, + /* sess_copy_message */ imapdriver_copy_message, + /* sess_move_message */ NULL, + + /* sess_get_message */ imapdriver_get_message, + /* sess_get_message_by_uid */ imapdriver_get_message_by_uid, + + /* sess_get_messages_list */ imapdriver_get_messages_list, + /* sess_get_envelopes_list */ imapdriver_get_envelopes_list, + /* sess_remove_message */ imapdriver_remove_message, + + /* sess_login_sasl */ imapdriver_login_sasl +}; + +mailsession_driver * imap_session_driver = &local_imap_session_driver; + +static inline struct imap_session_state_data * get_data(mailsession * session) +{ + return session->sess_data; +} + +static mailimap * get_imap_session(mailsession * session) +{ + return get_data(session)->imap_session; +} + +static int imapdriver_initialize(mailsession * session) +{ + struct imap_session_state_data * data; + mailimap * imap; + struct mail_flags_store * flags_store; + + imap = mailimap_new(0, NULL); + if (imap == NULL) + goto err; + + flags_store = mail_flags_store_new(); + if (flags_store == NULL) + goto free_session; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto free_flags_store; + + data->imap_mailbox = NULL; + data->imap_session = imap; + data->imap_flags_store = flags_store; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free_flags_store: + mail_flags_store_free(flags_store); + free_session: + mailimap_free(imap); + err: + return MAIL_ERROR_MEMORY; +} + +static void imap_flags_store_process(mailimap * imap, + struct mail_flags_store * flags_store) +{ + unsigned int i; + int r; + mailmessage * first; + mailmessage * last; + + mail_flags_store_sort(flags_store); + + if (carray_count(flags_store->fls_tab) == 0) + return; + + first = carray_get(flags_store->fls_tab, 0); + last = first; + + for(i = 1 ; i < carray_count(flags_store->fls_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(flags_store->fls_tab, i); + + if (last->msg_index + 1 == msg->msg_index) { + r = mail_flags_compare(first->msg_flags, msg->msg_flags); + if (r == 0) { + last = msg; + continue; + } + } + + r = imap_store_flags(imap, first->msg_index, + last->msg_index, first->msg_flags); + + first = msg; + last = msg; + } + + r = imap_store_flags(imap, first->msg_index, last->msg_index, + first->msg_flags); + + mail_flags_store_clear(flags_store); +} + +static void imapdriver_uninitialize(mailsession * session) +{ + struct imap_session_state_data * data; + + data = get_data(session); + + imap_flags_store_process(data->imap_session, + data->imap_flags_store); + mail_flags_store_free(data->imap_flags_store); + + mailimap_free(data->imap_session); + if (data->imap_mailbox != NULL) + free(data->imap_mailbox); + free(data); + + session->sess_data = NULL; +} + +static int imapdriver_connect_stream(mailsession * session, mailstream * s) +{ + int r; + + r = mailimap_connect(get_imap_session(session), s); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_login(mailsession * session, + const char * userid, const char * password) +{ + int r; + + r = mailimap_login(get_imap_session(session), userid, password); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_logout(mailsession * session) +{ + int r; + + imap_flags_store_process(get_imap_session(session), + get_data(session)->imap_flags_store); + + r = mailimap_logout(get_imap_session(session)); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_noop(mailsession * session) +{ + int r; + + r = mailimap_noop(get_imap_session(session)); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_build_folder_name(mailsession * session, const char * mb, + const char * name, char ** result) +{ + char delimiter[2] = "X"; + char * folder_name; + mailimap * imap; + struct mailimap_mailbox_list * mb_list; + int r; + clist * imap_list; + + imap = get_imap_session(session); + + r = mailimap_list(imap, mb, "", &imap_list); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (clist_begin(imap_list) == NULL) + return MAIL_ERROR_LIST; + + mb_list = clist_begin(imap_list)->data; + delimiter[0] = mb_list->mb_delimiter; + + folder_name = malloc(strlen(mb) + strlen(delimiter) + strlen(name) + 1); + if (folder_name == NULL) + return MAIL_ERROR_MEMORY; + + strcpy(folder_name, mb); + strcat(folder_name, delimiter); + strcat(folder_name, name); + + * result = folder_name; + + return MAIL_NO_ERROR; +} + +/* folders operations */ + +static int imapdriver_create_folder(mailsession * session, const char * mb) +{ + int r; + + r = mailimap_create(get_imap_session(session), mb); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_delete_folder(mailsession * session, const char * mb) +{ + int r; + + r = mailimap_delete(get_imap_session(session), mb); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_rename_folder(mailsession * session, const char * mb, + const char * new_name) +{ + int r; + + r = mailimap_rename(get_imap_session(session), mb, new_name); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_check_folder(mailsession * session) +{ + int r; + + imap_flags_store_process(get_imap_session(session), + get_data(session)->imap_flags_store); + + r = mailimap_check(get_imap_session(session)); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_examine_folder(mailsession * session, const char * mb) +{ + int r; + + r = mailimap_examine(get_imap_session(session), mb); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_select_folder(mailsession * session, const char * mb) +{ + int r; + char * new_mb; + char * old_mb; + + old_mb = get_data(session)->imap_mailbox; + if (old_mb != NULL) + if (strcmp(mb, old_mb) == 0) + return MAIL_NO_ERROR; + + imap_flags_store_process(get_imap_session(session), + get_data(session)->imap_flags_store); + + r = mailimap_select(get_imap_session(session), mb); + + switch (r) { + case MAILIMAP_NO_ERROR: + new_mb = strdup(mb); + if (new_mb == NULL) { + if (old_mb != NULL) + free(old_mb); + get_data(session)->imap_mailbox = NULL; + return MAIL_ERROR_MEMORY; + } + + if (old_mb != NULL) + free(old_mb); + get_data(session)->imap_mailbox = new_mb; + + return MAIL_NO_ERROR; + default: + return imap_error_to_mail_error(r); + } +} + +static int imapdriver_expunge_folder(mailsession * session) +{ + int r; + + imap_flags_store_process(get_imap_session(session), + get_data(session)->imap_flags_store); + + r = mailimap_expunge(get_imap_session(session)); + + return imap_error_to_mail_error(r); +} + +static int status_selected_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + int r; + int res; + mailimap * imap; + uint32_t exists; + uint32_t unseen; + uint32_t recent; + struct mailimap_search_key * search_key; + clist * search_result; + + imap = get_imap_session(session); + + exists = imap->imap_selection_info->sel_exists; + recent = imap->imap_selection_info->sel_recent; + + search_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNSEEN, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, 0, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, NULL, NULL); + if (search_key == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + /* default : use the RECENT count if search fails */ + unseen = recent; + r = mailimap_search(imap, NULL, search_key, &search_result); + mailimap_search_key_free(search_key); + if (r == MAILIMAP_NO_ERROR) { + /* if this succeed, we use the real count */ + unseen = clist_count(search_result); + mailimap_mailbox_data_search_free(search_result); + } + + * result_messages = exists; + * result_unseen = unseen; + * result_recent = recent; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int status_unselected_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + struct mailimap_status_att_list * att_list; + struct mailimap_mailbox_data_status * status; + int r; + int res; + clistiter * cur; + mailimap * imap; + + imap = get_imap_session(session); + + att_list = mailimap_status_att_list_new_empty(); + if (att_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_MESSAGES); + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + res = MAIL_ERROR_MEMORY; + goto free; + } + + r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_RECENT); + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + res = MAIL_ERROR_MEMORY; + goto free; + } + + r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_UNSEEN); + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + res = MAIL_ERROR_MEMORY; + goto free; + } + + r = mailimap_status(imap, mb, att_list, &status); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + res = imap_error_to_mail_error(r); + goto free; + } + + * result_messages = 0; + * result_recent = 0; + * result_unseen = 0; + + for (cur = clist_begin(status->st_info_list); + cur != NULL ; cur = clist_next(cur)) { + struct mailimap_status_info * status_info; + + status_info = clist_content(cur); + switch (status_info->st_att) { + case MAILIMAP_STATUS_ATT_MESSAGES: + * result_messages = status_info->st_value; + break; + case MAILIMAP_STATUS_ATT_RECENT: + * result_recent = status_info->st_value; + break; + case MAILIMAP_STATUS_ATT_UNSEEN: + * result_unseen = status_info->st_value; + break; + } + } + + mailimap_mailbox_data_status_free(status); + mailimap_status_att_list_free(att_list); + + return MAIL_NO_ERROR; + + free: + mailimap_status_att_list_free(att_list); + err: + return res; +} + +static int imapdriver_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + int res; + int current_folder; + char * current_mb; + + if (mb == NULL) { + mb = get_data(session)->imap_mailbox; + if (mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + } + + current_mb = get_data(session)->imap_mailbox; + if (strcmp(mb, current_mb) == 0) + current_folder = 1; + else + current_folder = 0; + + if (current_folder) + return status_selected_folder(session, mb, result_messages, + result_recent, result_unseen); + else + return status_unselected_folder(session, mb, result_messages, + result_recent, result_unseen); + + err: + return res; +} + +/* TODO : more efficient functions */ + +static int imapdriver_messages_number(mailsession * session, const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = imapdriver_status_folder(session, mb, &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = messages; + + return MAIL_NO_ERROR; +} + +static int imapdriver_recent_number(mailsession * session, const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = imapdriver_status_folder(session, mb, &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = recent; + + return MAIL_NO_ERROR; +} + +static int imapdriver_unseen_number(mailsession * session, const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + messages = 0; + recent = 0; + unseen = 0; + r = imapdriver_status_folder(session, mb, &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = unseen; + + return MAIL_NO_ERROR; +} + +enum { + IMAP_LIST, IMAP_LSUB +}; + +static int imapdriver_list_lsub_folders(mailsession * session, int type, + const char * mb, + struct mail_list ** result) +{ + clist * imap_list; + struct mail_list * resp; + int r; + int res; + + switch (type) { + case IMAP_LIST: + r = mailimap_list(get_imap_session(session), mb, + "*", &imap_list); + break; + case IMAP_LSUB: + r = mailimap_lsub(get_imap_session(session), mb, + "*", &imap_list); + break; + default: + res = MAIL_ERROR_LIST; + goto err; + } + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + res = imap_error_to_mail_error(r); + goto err; + } + + r = imap_list_to_list(imap_list, &resp); + if (r != MAIL_NO_ERROR) { + mailimap_list_result_free(imap_list); + res = r; + goto err; + } + + mailimap_list_result_free(imap_list); + + * result = resp; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int imapdriver_list_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + return imapdriver_list_lsub_folders(session, IMAP_LIST, mb, + result); +} + +static int imapdriver_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + return imapdriver_list_lsub_folders(session, IMAP_LSUB, mb, + result); +} + +static int imapdriver_subscribe_folder(mailsession * session, const char * mb) +{ + int r; + + r = mailimap_subscribe(get_imap_session(session), mb); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_unsubscribe_folder(mailsession * session, const char * mb) +{ + int r; + + r = mailimap_unsubscribe(get_imap_session(session), mb); + + return imap_error_to_mail_error(r); +} + +/* messages operations */ + +static int imapdriver_append_message(mailsession * session, + const char * message, size_t size) +{ + int r; + + r = mailimap_append_simple(get_imap_session(session), + get_data(session)->imap_mailbox, + message, size); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags) +{ + struct mailimap_flag_list * flag_list; + int r; + + if (flags != NULL) { + r = imap_flags_to_imap_flags(flags, &flag_list); + if (r != MAIL_NO_ERROR) + return r; + } + else { + flag_list = NULL; + } + + r = mailimap_append(get_imap_session(session), + get_data(session)->imap_mailbox, + flag_list, NULL, message, size); + + if (flag_list != NULL) + mailimap_flag_list_free(flag_list); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_copy_message(mailsession * session, + uint32_t num, const char * mb) +{ + int r; + struct mailimap_set * set; + int res; + + set = mailimap_set_new_single(num); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailimap_uid_copy(get_imap_session(session), set, mb); + + mailimap_set_free(set); + + return imap_error_to_mail_error(r); + + err: + return res; +} + +static int imapdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + return imap_get_messages_list(get_imap_session(session), + session, imap_message_driver, 1, + result); +} + + + +#define IMAP_SET_MAX_COUNT 100 + +static int +imapdriver_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + struct mailimap_set * set; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + int res; + clist * fetch_result; + int r; + uint32_t exists; + clist * msg_list; + clistiter * set_iter; + + if (get_imap_session(session)->imap_selection_info == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + imap_flags_store_process(get_imap_session(session), + get_data(session)->imap_flags_store); + + exists = get_imap_session(session)->imap_selection_info->sel_exists; + + if (exists == 0) + return MAIL_NO_ERROR; + + fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fetch_att = mailimap_fetch_att_new_uid(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + fetch_att = mailimap_fetch_att_new_flags(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = imap_add_envelope_fetch_att(fetch_type); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_fetch_type; + } + + r = maildriver_env_list_to_msg_list(env_list, &msg_list); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + if (clist_begin(msg_list) == NULL) { + /* no need to fetch envelopes */ + + mailimap_fetch_type_free(fetch_type); + clist_free(msg_list); + return MAIL_NO_ERROR; + } + + r = imap_msg_list_to_imap_set(msg_list, &set); + if (r != MAIL_NO_ERROR) { + clist_foreach(msg_list, (clist_func) free, NULL); + clist_free(msg_list); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + clist_foreach(msg_list, (clist_func) free, NULL); + clist_free(msg_list); + + set_iter = clist_begin(set->set_list); + while (set_iter != NULL) { + struct mailimap_set * subset; + unsigned int count; + + subset = mailimap_set_new_empty(); + if (subset == NULL) { + res = MAIL_ERROR_MEMORY; + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + goto err; + } + + count = 0; + while (count < IMAP_SET_MAX_COUNT) { + struct mailimap_set_item * item; + + item = clist_content(set_iter); + set_iter = clist_delete(set->set_list, set_iter); + + r = mailimap_set_add(subset, item); + if (r != MAILIMAP_NO_ERROR) { + mailimap_set_item_free(item); + mailimap_set_free(subset); + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + res = MAIL_ERROR_MEMORY; + goto err; + } + + count ++; + + if (set_iter == NULL) + break; + } + + r = mailimap_uid_fetch(get_imap_session(session), subset, + fetch_type, &fetch_result); + + mailimap_set_free(subset); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + return imap_error_to_mail_error(r); + } + + if (clist_begin(fetch_result) == NULL) { + res = MAIL_ERROR_FETCH; + goto err; + } + + r = imap_fetch_result_to_envelop_list(fetch_result, env_list); + mailimap_fetch_list_free(fetch_result); + + if (r != MAIL_NO_ERROR) { + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + res = MAIL_ERROR_MEMORY; + goto err; + } + } + +#if 0 + r = mailimap_uid_fetch(get_imap_session(session), set, + fetch_type, &fetch_result); +#endif + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); +#if 0 + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + r = imap_fetch_result_to_envelop_list(fetch_result, env_list); + mailimap_fetch_list_free(fetch_result); + + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto err; + } +#endif + + return MAIL_NO_ERROR; + + free_fetch_type: + mailimap_fetch_type_free(fetch_type); + err: + return res; +} + + +#if 0 +static int imapdriver_search_messages(mailsession * session, const char * charset, + struct mail_search_key * key, + struct mail_search_result ** result) +{ + struct mailimap_search_key * imap_key; + int r; + clist * imap_result; + clist * result_list; + struct mail_search_result * search_result; + clistiter * cur; + + r = mail_search_to_imap_search(key, &imap_key); + if (r != MAIL_NO_ERROR) + return MAIL_ERROR_MEMORY; + + r = mailimap_uid_search(get_imap_session(session), charset, imap_key, + &imap_result); + + mailimap_search_key_free(imap_key); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + result_list = clist_new(); + if (result_list == NULL) + return MAIL_ERROR_MEMORY; + + for(cur = clist_begin(imap_result) ; cur != NULL ; cur = clist_next(cur)) { + uint32_t val = * (uint32_t *) clist_content(cur); + uint32_t * new; + + new = malloc(sizeof(* new)); + if (new == NULL) { + goto free_imap_result; + } + + * new = val; + + r = clist_append(result_list, new); + if (r != 0) { + free(new); + goto free_imap_result; + } + } + + search_result = mail_search_result_new(result_list); + if (search_result == NULL) + goto free_imap_result; + + mailimap_search_result_free(imap_result); + + * result = search_result; + + return MAIL_NO_ERROR; + + free_imap_result: + mailimap_search_result_free(imap_result); + return MAIL_ERROR_MEMORY; +} +#endif + +static int imapdriver_starttls(mailsession * session) +{ + mailimap * imap; + int r; + struct mailimap_capability_data * cap_data; + clistiter * cur; + int starttls; + int capability_available; + + imap = get_imap_session(session); + + capability_available = FALSE; + if (imap->imap_connection_info != NULL) + if (imap->imap_connection_info->imap_capability != NULL) { + capability_available = TRUE; + cap_data = imap->imap_connection_info->imap_capability; + } + + if (!capability_available) { + r = mailimap_capability(imap, &cap_data); + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + } + + starttls = FALSE; + for(cur = clist_begin(cap_data->cap_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_capability * cap; + + cap = clist_content(cur); + + if (cap->cap_type == MAILIMAP_CAPABILITY_NAME) + if (strcasecmp(cap->cap_data.cap_name, "STARTTLS") == 0) { + starttls = TRUE; + break; + } + } + + if (!capability_available) + mailimap_capability_data_free(cap_data); + + if (!starttls) + return MAIL_ERROR_NO_TLS; + + r = mailimap_socket_starttls(imap); + return imap_error_to_mail_error(r); +} + +static int imapdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, imap_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +/* Retrieve a message by UID + + libEtPan! uid format for IMAP is "UIDVALIDITY-UID" + where UIDVALIDITY and UID are decimal representation of + respectively uidvalidity and uid numbers. + + Return value: + MAIL_ERROR_INVAL if uid is NULL or has an incorrect format. + MAIL_ERROR_MSG_NOT_FOUND if uidvalidity has changed or uid was not found + MAIL_NO_ERROR if message was found. Result is in result +*/ + +static int imapdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t uidvalidity; + uint32_t num; + char * p1, * p2; + mailimap * imap; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + uidvalidity = (uint32_t) strtoul(uid, &p1, 10); + if (p1 == uid || * p1 != '-') + return MAIL_ERROR_INVAL; + + p1++; + num = (uint32_t) strtoul(p1, &p2, 10); + if (p2 == p1 || * p2 != '\0') + return MAIL_ERROR_INVAL; + + imap = get_imap_session(session); + if (imap->imap_selection_info->sel_uidvalidity != uidvalidity) + return MAIL_ERROR_MSG_NOT_FOUND; + + return imapdriver_get_message(session, num, result); +} + +static int imapdriver_login_sasl(mailsession * session, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm) +{ + int r; + + if (strcasecmp(auth_type, "xoauth2") == 0) + r = mailimap_oauth2_authenticate(get_imap_session(session), auth_name, password); + else + r = mailimap_authenticate(get_imap_session(session), + auth_type, server_fqdn, local_ip_port, remote_ip_port, + login, auth_name, password, realm); + + return imap_error_to_mail_error(r); +} + + +static int imapdriver_remove_message(mailsession * session, uint32_t num) { + + int res; + struct mail_flags *flags = NULL; + + /* protection if SELECT folder not done */ + if (get_imap_session(session)->imap_selection_info == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + /* Deleted flag */ + if ((flags = mail_flags_new_empty()) == NULL) { res = MAIL_ERROR_MEMORY; goto err;} + flags->fl_flags = MAIL_FLAG_DELETED; + + /* STORE num \Deleted */ + /* EXPUNGE */ + if ((res = imap_store_flags(get_imap_session(session), num, num, flags)) == MAILIMAP_NO_ERROR) + res = mailimap_expunge(get_imap_session(session)); + res = imap_error_to_mail_error(res); + +err: + if (flags != NULL) mail_flags_free( flags); + return res; +} + +static int imapdriver_parameters(mailsession * session, + int id, void * value) +{ + struct imap_session_state_data * data; + + data = get_data(session); + + switch (id) { + case IMAPDRIVER_CACHED_SET_SSL_CALLBACK: + data->imap_ssl_callback = value; + break; + case IMAPDRIVER_CACHED_SET_SSL_CALLBACK_DATA: + data->imap_ssl_cb_data = value; + break; + } + + return MAIL_ERROR_INVAL; +} diff --git a/Sources/libetpan/driver/implementation/imap/imapdriver.h b/Sources/libetpan/driver/implementation/imap/imapdriver.h new file mode 100644 index 00000000..d5bd055f --- /dev/null +++ b/Sources/libetpan/driver/implementation/imap/imapdriver.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver.h,v 1.12 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef IMAPDRIVER_H + +#define IMAPDRIVER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +extern mailsession_driver * imap_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/imap/imapdriver_cached.c b/Sources/libetpan/driver/implementation/imap/imapdriver_cached.c new file mode 100644 index 00000000..282d1f6f --- /dev/null +++ b/Sources/libetpan/driver/implementation/imap/imapdriver_cached.c @@ -0,0 +1,1540 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver_cached.c,v 1.61 2008/02/20 22:35:47 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "imapdriver_cached.h" + +#include "libetpan-config.h" + +#include +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include + +#include "mail.h" +#include "imapdriver_tools.h" +#include "imapdriver_tools_private.h" +#include "mail_cache_db.h" +#include "mailmessage.h" +#include "imapdriver_cached_message.h" +#include "maildriver.h" +#include "imapdriver_types.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "maildriver_tools.h" +#include "imapdriver.h" + +static int imapdriver_cached_initialize(mailsession * session); +static void imapdriver_cached_uninitialize(mailsession * session); + +static int imapdriver_cached_parameters(mailsession * session, + int id, void * value); + +static int imapdriver_cached_connect_stream(mailsession * session, + mailstream * s); + +static int imapdriver_cached_starttls(mailsession * session); + +static int imapdriver_cached_login(mailsession * session, + const char * userid, const char * password); +static int imapdriver_cached_logout(mailsession * session); +static int imapdriver_cached_noop(mailsession * session); +static int imapdriver_cached_build_folder_name(mailsession * session, + const char * mb, + const char * name, char ** result); +static int imapdriver_cached_create_folder(mailsession * session, const char * mb); +static int imapdriver_cached_delete_folder(mailsession * session, const char * mb); +static int imapdriver_cached_rename_folder(mailsession * session, const char * mb, + const char * new_name); +static int imapdriver_cached_check_folder(mailsession * session); +static int imapdriver_cached_examine_folder(mailsession * session, + const char * mb); +static int imapdriver_cached_select_folder(mailsession * session, const char * mb); +static int imapdriver_cached_expunge_folder(mailsession * session); +static int imapdriver_cached_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, + uint32_t * result_recent, + uint32_t * result_unseen); +static int imapdriver_cached_messages_number(mailsession * session, + const char * mb, + uint32_t * result); +static int imapdriver_cached_recent_number(mailsession * session, const char * mb, + uint32_t * result); +static int imapdriver_cached_unseen_number(mailsession * session, const char * mb, + uint32_t * result); +static int imapdriver_cached_list_folders(mailsession * session, const char * mb, + struct mail_list ** result); +static int imapdriver_cached_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result); +static int imapdriver_cached_subscribe_folder(mailsession * session, + const char * mb); +static int imapdriver_cached_unsubscribe_folder(mailsession * session, + const char * mb); +static int imapdriver_cached_append_message(mailsession * session, + const char * message, size_t size); +static int imapdriver_cached_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); +static int imapdriver_cached_copy_message(mailsession * session, + uint32_t num, const char * mb); + +static int imapdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** + result); +static int +imapdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); +static int imapdriver_cached_remove_message(mailsession * session, + uint32_t num); + +#if 0 +static int imapdriver_cached_search_messages(mailsession * session, + const char * charset, + struct mail_search_key * key, + struct mail_search_result ** + result); +#endif + +static int imapdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int imapdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static int imapdriver_cached_login_sasl(mailsession * session, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); + +static mailsession_driver local_imap_cached_session_driver = { + /* sess_name */ "imap-cached", + + /* sess_initialize */ imapdriver_cached_initialize, + /* sess_uninitialize */ imapdriver_cached_uninitialize, + + /* sess_parameters */ imapdriver_cached_parameters, + + /* sess_connect_stream */ imapdriver_cached_connect_stream, + /* sess_connect_path */ NULL, + /* sess_starttls */ imapdriver_cached_starttls, + /* sess_login */ imapdriver_cached_login, + /* sess_logout */ imapdriver_cached_logout, + /* sess_noop */ imapdriver_cached_noop, + + /* sess_build_folder_name */ imapdriver_cached_build_folder_name, + /* sess_create_folder */ imapdriver_cached_create_folder, + /* sess_delete_folder */ imapdriver_cached_delete_folder, + /* sess_rename_folder */ imapdriver_cached_rename_folder, + /* sess_check_folder */ imapdriver_cached_check_folder, + /* sess_examine_folder */ imapdriver_cached_examine_folder, + /* sess_select_folder */ imapdriver_cached_select_folder, + /* sess_expunge_folder */ imapdriver_cached_expunge_folder, + /* sess_status_folder */ imapdriver_cached_status_folder, + /* sess_messages_number */ imapdriver_cached_messages_number, + /* sess_recent_number */ imapdriver_cached_recent_number, + /* sess_unseen_number */ imapdriver_cached_unseen_number, + /* sess_list_folders */ imapdriver_cached_list_folders, + /* sess_lsub_folders */ imapdriver_cached_lsub_folders, + /* sess_subscribe_folder */ imapdriver_cached_subscribe_folder, + /* sess_unsubscribe_folder */ imapdriver_cached_unsubscribe_folder, + + /* sess_append_message */ imapdriver_cached_append_message, + /* sess_append_message_flags */ imapdriver_cached_append_message_flags, + /* sess_copy_message */ imapdriver_cached_copy_message, + /* sess_move_message */ NULL, + + /* sess_get_message */ imapdriver_cached_get_message, + /* sess_get_message_by_uid */ imapdriver_cached_get_message_by_uid, + + /* sess_get_messages_list */ imapdriver_cached_get_messages_list, + /* sess_get_envelopes_list */ imapdriver_cached_get_envelopes_list, + /* sess_remove_message */ imapdriver_cached_remove_message, +#if 0 + /* sess_search_messages */ imapdriver_cached_search_messages, +#endif + /* sess_cached_login_sasl */ imapdriver_cached_login_sasl +}; + +mailsession_driver * imap_cached_session_driver = +&local_imap_cached_session_driver; + +#define CACHE_MESSAGE_LIST + +static inline struct imap_cached_session_state_data * +get_cached_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * get_ancestor(mailsession * s) +{ + return get_cached_data(s)->imap_ancestor; +} + +static inline +struct imap_session_state_data * get_ancestor_data(mailsession * s) +{ + return get_ancestor(s)->sess_data; +} + +static inline mailimap * get_imap_session(mailsession * session) +{ + return get_ancestor_data(session)->imap_session; +} + +static int imapdriver_cached_initialize(mailsession * session) +{ + struct imap_cached_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->imap_ancestor = mailsession_new(imap_session_driver); + if (data->imap_ancestor == NULL) + goto free_data; + data->imap_quoted_mb = NULL; + data->imap_cache_directory[0] = '\0'; + data->imap_uid_list = carray_new(128); + if (data->imap_uid_list == NULL) + goto free_session; + data->imap_uidvalidity = 0; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free_session: + mailsession_free(data->imap_ancestor); + free_data: + free(data); + err: + return MAIL_ERROR_MEMORY; +} + +static void +free_quoted_mb(struct imap_cached_session_state_data * imap_cached_data) +{ + if (imap_cached_data->imap_quoted_mb != NULL) { + free(imap_cached_data->imap_quoted_mb); + imap_cached_data->imap_quoted_mb = NULL; + } +} + +struct uid_cache_item { + uint32_t uid; + uint32_t size; +}; + +static int update_uid_cache(mailsession * session, + struct mailmessage_list * env_list) +{ + unsigned int i; + int r; + struct imap_cached_session_state_data * data; + int res; + mailimap * imap; + + data = get_cached_data(session); + imap = get_imap_session(session); + + /* free all UID cache */ + for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) { + struct uid_cache_item * cache_item; + + cache_item = carray_get(data->imap_uid_list, i); + free(cache_item); + } + + if (env_list == NULL) { + r = carray_set_size(data->imap_uid_list, 0); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + } + else { + /* build UID cache */ + r = carray_set_size(data->imap_uid_list, + carray_count(env_list->msg_tab)); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + struct uid_cache_item * cache_item; + mailmessage * msg; + + cache_item = malloc(sizeof(* cache_item)); + if (cache_item == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + msg = carray_get(env_list->msg_tab, i); + cache_item->uid = msg->msg_index; + cache_item->size = (uint32_t) msg->msg_size; + + carray_set(data->imap_uid_list, i, cache_item); + } + } + data->imap_uidvalidity = imap->imap_selection_info->sel_uidvalidity; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static void check_for_uid_cache(mailsession * session) +{ +#if 0 + mailsession * imap; +#endif + mailimap * imap; +#if 0 + struct imap_session_state_data * imap_data; +#endif + clist * list; + clistiter * cur; + struct imap_cached_session_state_data * data; + unsigned int i; + unsigned dest; + + data = get_cached_data(session); +#if 0 + imap = get_ancestor(session); + + imap_data = imap->data; +#endif + + imap = get_imap_session(session); + + if (imap->imap_response_info == NULL) + return; + + list = imap->imap_response_info->rsp_expunged; + if (list == NULL) + return; + + dest = 0; + i = 0; + /* remove expunged */ + for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) { + uint32_t expunged; + + expunged = * (uint32_t *) clist_content(cur); + + while (i < carray_count(data->imap_uid_list)) { + struct uid_cache_item * cache_item; + + if (dest + 1 == expunged) { + cache_item = carray_get(data->imap_uid_list, i); + free(cache_item); + i ++; + break; + } + else { + cache_item = carray_get(data->imap_uid_list, i); + carray_set(data->imap_uid_list, dest, cache_item); + i ++; + dest ++; + } + } + } + /* complete list */ + while (i < carray_count(data->imap_uid_list)) { + struct uid_cache_item * cache_item; + + cache_item = carray_get(data->imap_uid_list, i); + carray_set(data->imap_uid_list, dest, cache_item); + i ++; + dest ++; + } + carray_set_size(data->imap_uid_list, dest); +} + +static void imapdriver_cached_uninitialize(mailsession * session) +{ + struct imap_cached_session_state_data * data; + unsigned int i; + + data = get_cached_data(session); + + for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) { + struct uid_cache_item * cache_item; + + cache_item = carray_get(data->imap_uid_list, i); + free(cache_item); + } + carray_free(data->imap_uid_list); + free_quoted_mb(data); + mailsession_free(data->imap_ancestor); + free(data); + + session->sess_data = NULL; +} + + +static int imapdriver_cached_parameters(mailsession * session, + int id, void * value) +{ + struct imap_cached_session_state_data * data; + int r; + + data = get_cached_data(session); + + switch (id) { + case IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY: + strncpy(data->imap_cache_directory, value, PATH_MAX); + data->imap_cache_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(data->imap_cache_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + default: + return mailsession_parameters(data->imap_ancestor, id, value); + } +} + + +static int imapdriver_cached_connect_stream(mailsession * session, + mailstream * s) +{ + int r; + + check_for_uid_cache(session); + + r = mailsession_connect_stream(get_ancestor(session), s); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_starttls(mailsession * session) +{ + int r; + + r = mailsession_starttls(get_ancestor(session)); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_login(mailsession * session, + const char * userid, const char * password) +{ + int r; + + r = mailsession_login(get_ancestor(session), userid, password); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_logout(mailsession * session) +{ + int r; + + r = mailsession_logout(get_ancestor(session)); + + check_for_uid_cache(session); + + if (r == MAIL_NO_ERROR) { + struct imap_cached_session_state_data * imap_cached_data; + + imap_cached_data = get_cached_data(session); + + free_quoted_mb(imap_cached_data); + } + + return r; +} + +static int imapdriver_cached_noop(mailsession * session) +{ + int r; + + r = mailsession_noop(get_ancestor(session)); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_build_folder_name(mailsession * session, + const char * mb, + const char * name, char ** result) +{ + int r; + + r = mailsession_build_folder_name(get_ancestor(session), mb, + name, result); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_create_folder(mailsession * session, const char * mb) +{ + int r; + + r = mailsession_create_folder(get_ancestor(session), mb); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_delete_folder(mailsession * session, const char * mb) +{ + int r; + + r = mailsession_delete_folder(get_ancestor(session), mb); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_rename_folder(mailsession * session, const char * mb, + const char * new_name) +{ + int r; + + r = mailsession_rename_folder(get_ancestor(session), mb, new_name); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_check_folder(mailsession * session) +{ + int r; + + r = mailsession_check_folder(get_ancestor(session)); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_examine_folder(mailsession * session, + const char * mb) +{ + int r; + + r = mailsession_examine_folder(get_ancestor(session), mb); + + check_for_uid_cache(session); + + return r; +} + +static int get_cache_folder(mailsession * session, char ** result) +{ +#if 0 + mailsession * imap_session; +#endif + mailimap * imap; + char * mb; + char * cache_dir; + char * dirname; + char * quoted_mb; + int res; + int r; + char key[PATH_MAX]; +#if 0 + struct imap_session_state_data * imap_data; + struct imap_cached_session_state_data * cached_data; +#endif + +#if 0 + imap_session = get_ancestor(session); + imap_data = imap_session->data; + imap = imap_data->session; +#endif + imap = get_imap_session(session); + + mb = get_ancestor_data(session)->imap_mailbox; + + cache_dir = get_cached_data(session)->imap_cache_directory; + + if (imap->imap_state != MAILIMAP_STATE_SELECTED) + return MAIL_ERROR_BAD_STATE; + + if (imap->imap_selection_info == NULL) + return MAIL_ERROR_BAD_STATE; + + quoted_mb = maildriver_quote_mailbox(mb); + if (quoted_mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(key, PATH_MAX, "%s/%s", cache_dir, quoted_mb); + + dirname = strdup(key); + if (dirname == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_mb; + } + + r = generic_cache_create_dir(dirname); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_dirname; + } + + free(quoted_mb); + + * result = dirname; + + return MAIL_NO_ERROR; + + free_dirname: + free(dirname); + free_mb: + free(quoted_mb); + err: + return res; +} + +static int imapdriver_cached_select_folder(mailsession * session, const char * mb) +{ + int r; + char * quoted_mb; + struct imap_cached_session_state_data * data; + char * old_mb; + + old_mb = get_ancestor_data(session)->imap_mailbox; + if (old_mb != NULL) + if (strcmp(mb, old_mb) == 0) + return MAIL_NO_ERROR; + + r = mailsession_select_folder(get_ancestor(session), mb); + if (r != MAIL_NO_ERROR) + return r; + + check_for_uid_cache(session); + + quoted_mb = NULL; + r = get_cache_folder(session, "ed_mb); + if (r != MAIL_NO_ERROR) + return r; + + data = get_cached_data(session); + if (data->imap_quoted_mb != NULL) + free(data->imap_quoted_mb); + data->imap_quoted_mb = quoted_mb; + + /* clear UID cache */ + carray_set_size(data->imap_uid_list, 0); + + return MAIL_NO_ERROR; +} + +static int imapdriver_cached_expunge_folder(mailsession * session) +{ + int r; + + r = mailsession_expunge_folder(get_ancestor(session)); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + int r; + + r = mailsession_status_folder(get_ancestor(session), mb, result_messages, + result_recent, result_unseen); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_messages_number(mailsession * session, + const char * mb, + uint32_t * result) +{ + int r; + + r = mailsession_messages_number(get_ancestor(session), mb, result); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_recent_number(mailsession * session, const char * mb, + uint32_t * result) +{ + int r; + + r = mailsession_recent_number(get_ancestor(session), mb, result); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_unseen_number(mailsession * session, const char * mb, + uint32_t * result) +{ + int r; + + r = mailsession_unseen_number(get_ancestor(session), mb, result); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_list_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + int r; + + r = mailsession_list_folders(get_ancestor(session), mb, result); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + int r; + + r = mailsession_lsub_folders(get_ancestor(session), mb, result); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_subscribe_folder(mailsession * session, + const char * mb) +{ + int r; + + r = mailsession_subscribe_folder(get_ancestor(session), mb); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_unsubscribe_folder(mailsession * session, + const char * mb) +{ + int r; + + r = mailsession_unsubscribe_folder(get_ancestor(session), mb); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_append_message(mailsession * session, + const char * message, size_t size) +{ + int r; + + r = mailsession_append_message(get_ancestor(session), message, size); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags) +{ + int r; + + r = mailsession_append_message_flags(get_ancestor(session), + message, size, flags); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_copy_message(mailsession * session, + uint32_t num, const char * mb) +{ + int r; + + r = mailsession_copy_message(get_ancestor(session), num, mb); + + check_for_uid_cache(session); + + return r; +} + +static int cmp_uid(uint32_t ** pa, uint32_t ** pb) +{ + uint32_t * a; + uint32_t * b; + + a = * pa; + b = * pb; + + return * a - * b; +} + + +static void get_uid_from_filename(char * filename) +{ + char * p; + + p = strstr(filename, "-part"); + if (p != NULL) + * p = 0; + p = strstr(filename, "-envelope"); + if (p != NULL) + * p = 0; + p = strstr(filename, "-rfc822"); + if (p != NULL) + * p = 0; +} + +#define ENV_NAME "env.db" + +static int boostrap_cache(mailsession * session) +{ + struct mail_cache_db * cache_db; + char filename[PATH_MAX]; + struct imap_cached_session_state_data * data; + MMAPString * mmapstr; + int r; + int res; + chashiter * iter; + chash * keys; + chash * keys_uid; + + data = get_cached_data(session); + + if (data->imap_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(filename, PATH_MAX, "%s/%s", data->imap_quoted_mb, ENV_NAME); + + r = mail_cache_db_open_lock(filename, &cache_db); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto free_mmapstr; + } + + keys = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + if (keys == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db; + } + + r = mail_cache_db_get_keys(cache_db, keys); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_keys; + } + + keys_uid = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + if (keys_uid == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_keys; + } + + for(iter = chash_begin(keys) ; iter != NULL ; iter = chash_next(keys, iter)) { + chashdatum key; + chashdatum value; + char msg_uid[PATH_MAX]; + + chash_key(iter, &key); + if (key.len >= sizeof(msg_uid)) { + strncpy(msg_uid, key.data, sizeof(msg_uid)); + msg_uid[sizeof(msg_uid) - 1] = 0; + } + else { + strncpy(msg_uid, key.data, key.len); + msg_uid[key.len] = 0; + } + + get_uid_from_filename(msg_uid); + key.data = msg_uid; + key.len = (unsigned int) strlen(msg_uid) + 1; + value.data = NULL; + value.len = 0; + chash_set(keys_uid, &key, &value, NULL); + } + + for(iter = chash_begin(keys_uid) ; iter != NULL ; iter = chash_next(keys_uid, iter)) { + chashdatum key; + uint32_t uidvalidity; + uint32_t indx; + char * uid; + char * p1, * p2; + struct uid_cache_item * cache_item; + + chash_key(iter, &key); + uid = key.data; + + uidvalidity = (uint32_t) strtoul(uid, &p1, 10); + if (p1 == uid || * p1 != '-') + continue; + + data->imap_uidvalidity = uidvalidity; + + p1++; + indx = (uint32_t) strtoul(p1, &p2, 10); + if (p2 == p1 || * p2 != '\0') + continue; + + cache_item = malloc(sizeof(* cache_item)); + if (cache_item == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_keys_uid; + } + + cache_item->uid = indx; + cache_item->size = 0; + + carray_add(data->imap_uid_list, cache_item, NULL); + } + + chash_free(keys_uid); + chash_free(keys); + + mail_cache_db_close_unlock(filename, cache_db); + mmap_string_free(mmapstr); + + return MAIL_NO_ERROR; + + free_keys_uid: + chash_free(keys_uid); + free_keys: + chash_free(keys); + close_db: + mail_cache_db_close_unlock(filename, cache_db); + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + + +static int imapdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** + result) +{ + mailimap * imap; + uint32_t uid_max; + struct imap_cached_session_state_data * data; + struct mailmessage_list * env_list; + unsigned i; + int r; + int res; + carray * tab; + + data = get_cached_data(session); + imap = get_imap_session(session); + + uid_max = 0; + +#ifdef CACHE_MESSAGE_LIST + if (data->imap_uidvalidity == 0) { + boostrap_cache(session); + } + + if (imap->imap_selection_info->sel_uidvalidity != data->imap_uidvalidity) { + update_uid_cache(session, NULL); + } + + /* get UID max */ + for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) { + struct uid_cache_item * cache_item; + + cache_item = carray_get(data->imap_uid_list, i); + if (cache_item->uid > uid_max) + uid_max = cache_item->uid; + } +#endif + + r = imap_get_messages_list(imap, session, imap_cached_message_driver, + uid_max + 1, &env_list); + + check_for_uid_cache(session); + + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + +#ifdef CACHE_MESSAGE_LIST + /* remove unsollicited message */ + i = 0; + while (i < carray_count(env_list->msg_tab)) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + if (msg->msg_index < uid_max + 1) { + mailmessage_free(msg); + carray_delete(env_list->msg_tab, i); + } + else { + i ++; + } + } + + tab = carray_new(carray_count(env_list->msg_tab) + + carray_count(data->imap_uid_list)); + if (tab == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + carray_set_size(tab, + carray_count(env_list->msg_tab) + carray_count(data->imap_uid_list)); + + /* sort cached data before adding them to the list */ + qsort(carray_data(data->imap_uid_list), carray_count(data->imap_uid_list), + sizeof(* carray_data(data->imap_uid_list)), + (int (*)(const void *, const void *)) cmp_uid); + + /* adds cached UID */ + for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) { + struct uid_cache_item * cache_item; + mailmessage * msg; + + cache_item = carray_get(data->imap_uid_list, i); + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + r = mailmessage_init(msg, session, imap_cached_message_driver, + cache_item->uid, cache_item->size); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg); + res = r; + goto free; + } + + carray_set(tab, i, msg); + } + + /* adds new elements */ + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + carray_set(tab, carray_count(data->imap_uid_list) + i, msg); + } + + /* replace list of messages in env_list */ + carray_free(env_list->msg_tab); + env_list->msg_tab = tab; + + r = update_uid_cache(session, env_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } +#endif + + * result = env_list; + + return MAIL_NO_ERROR; + + free: + mailmessage_list_free(env_list); + err: + return res; +} + +#define IMAP_SET_MAX_COUNT 100 + +static int get_flags_list(mailsession * session, + struct mailmessage_list * env_list) +{ + struct mailimap_set * set; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + int res; + clist * fetch_result; + int r; + clist * msg_list; +#if 0 + struct imap_session_state_data * data; +#endif + unsigned i; + unsigned dest; + clistiter * set_iter; + +#if 0 + data = session->data; +#endif + + fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fetch_att = mailimap_fetch_att_new_uid(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + fetch_att = mailimap_fetch_att_new_flags(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = maildriver_env_list_to_msg_list_no_flags(env_list, &msg_list); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + if (clist_begin(msg_list) == NULL) { + /* no need to fetch envelopes */ + + clist_free(msg_list); + mailimap_fetch_type_free(fetch_type); + return MAIL_NO_ERROR; + } + + r = imap_msg_list_to_imap_set(msg_list, &set); + if (r != MAIL_NO_ERROR) { + clist_foreach(msg_list, (clist_func) free, NULL); + clist_free(msg_list); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + clist_foreach(msg_list, (clist_func) free, NULL); + clist_free(msg_list); + + set_iter = clist_begin(set->set_list); + while (set_iter != NULL) { + struct mailimap_set * subset; + unsigned int count; + + subset = mailimap_set_new_empty(); + if (subset == NULL) { + res = MAIL_ERROR_MEMORY; + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + goto err; + } + + count = 0; + while (count < IMAP_SET_MAX_COUNT) { + struct mailimap_set_item * item; + + item = clist_content(set_iter); + set_iter = clist_delete(set->set_list, set_iter); + + r = mailimap_set_add(subset, item); + if (r != MAILIMAP_NO_ERROR) { + mailimap_set_item_free(item); + mailimap_set_free(subset); + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + res = MAIL_ERROR_MEMORY; + goto err; + } + + count ++; + + if (set_iter == NULL) + break; + } + + r = mailimap_uid_fetch(get_imap_session(session), subset, + fetch_type, &fetch_result); + + mailimap_set_free(subset); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + return imap_error_to_mail_error(r); + } + +#if 0 + if (clist_begin(fetch_result) == NULL) { + res = MAIL_ERROR_FETCH; + goto err; + } +#endif + + r = imap_fetch_result_to_envelop_list(fetch_result, env_list); + mailimap_fetch_list_free(fetch_result); + + if (r != MAIL_NO_ERROR) { + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + res = MAIL_ERROR_MEMORY; + goto err; + } + } + +#if 0 + r = mailimap_uid_fetch(get_imap_session(session), set, + fetch_type, &fetch_result); +#endif + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + +#if 0 + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + r = imap_fetch_result_to_envelop_list(fetch_result, env_list); + mailimap_fetch_list_free(fetch_result); + + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto err; + } +#endif + + /* remove messages that don't have flags */ + i = 0; + dest = 0; + while (i < carray_count(env_list->msg_tab)) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + if (msg->msg_flags != NULL) { + carray_set(env_list->msg_tab, dest, msg); + dest ++; + } + else { + mailmessage_free(msg); + } + i ++; + } + carray_set_size(env_list->msg_tab, dest); + + return MAIL_NO_ERROR; + + free_fetch_type: + mailimap_fetch_type_free(fetch_type); + err: + return res; +} + + +static int +imapdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + int res; + uint32_t i; + struct imap_cached_session_state_data * data; + MMAPString * mmapstr; + struct mail_cache_db * cache_db; + char filename[PATH_MAX]; + + data = get_cached_data(session); + if (data->imap_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(filename, PATH_MAX, "%s/%s", data->imap_quoted_mb, ENV_NAME); + + r = mail_cache_db_open_lock(filename, &cache_db); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto free_mmapstr; + } + + /* fill with cached */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailimf_fields * fields; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + r = imapdriver_get_cached_envelope(cache_db, mmapstr, + session, msg, &fields); + if (r == MAIL_NO_ERROR) { + msg->msg_cached = TRUE; + msg->msg_fields = fields; + } + } + } + + mail_cache_db_close_unlock(filename, cache_db); + + r = mailsession_get_envelopes_list(get_ancestor(session), env_list); + + check_for_uid_cache(session); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + r = get_flags_list(session, env_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + +#ifdef CACHE_MESSAGE_LIST + r = update_uid_cache(session, env_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } +#endif + + /* must write cache */ + + r = mail_cache_db_open_lock(filename, &cache_db); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto free_mmapstr; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields != NULL) { + if (!msg->msg_cached) { + r = imapdriver_write_cached_envelope(cache_db, mmapstr, + session, msg, msg->msg_fields); + } + } + } + + /* flush cache */ + + maildriver_cache_clean_up(cache_db, NULL, env_list); + + mail_cache_db_close_unlock(filename, cache_db); + mmap_string_free(mmapstr); + + /* remove cache files */ + + maildriver_message_cache_clean_up(data->imap_quoted_mb, env_list, + get_uid_from_filename); + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + +static int imapdriver_cached_remove_message(mailsession * session, + uint32_t num) +{ + int r; + + r = mailsession_remove_message(get_ancestor(session), num); + + check_for_uid_cache(session); + + return r; +} + +#if 0 +static int imapdriver_cached_search_messages(mailsession * session, + char * charset, + struct mail_search_key * key, + struct mail_search_result ** + result) +{ + int r; + + r = mailsession_search_messages(get_ancestor(session), charset, key, result); + + check_for_uid_cache(session); + + return r; +} +#endif + +static int imapdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, imap_cached_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +/* Retrieve a message by UID + * libEtPan! uid format for IMAP is "UIDVALIDITY-UID" + * where UIDVALIDITY and UID are decimal representation of + * respectively uidvalidity and uid numbers. + * Return value: + * MAIL_ERROR_INVAL if uid is NULL or has an incorrect format. + * MAIL_ERROR_MSG_NOT_FOUND if uidvalidity has changed or uid was not found + * MAIL_NO_ERROR if message was found. Result is in result + */ +static int imapdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t uidvalidity; + uint32_t num; + char * p1, * p2; + mailimap *imap; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + uidvalidity = (uint32_t) strtoul(uid, &p1, 10); + if (p1 == uid || * p1 != '-') + return MAIL_ERROR_INVAL; + + p1++; + num = (uint32_t) strtoul(p1, &p2, 10); + if (p2 == p1 || * p2 != '\0') + return MAIL_ERROR_INVAL; + + imap = get_imap_session(session); + if (imap->imap_selection_info->sel_uidvalidity != uidvalidity) + return MAIL_ERROR_MSG_NOT_FOUND; + + return imapdriver_cached_get_message(session, num, result); +} + +static int imapdriver_cached_login_sasl(mailsession * session, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm) +{ + return mailsession_login_sasl(get_ancestor(session), auth_type, + server_fqdn, + local_ip_port, + remote_ip_port, + login, auth_name, + password, realm); +} diff --git a/Sources/libetpan/driver/implementation/imap/imapdriver_cached.h b/Sources/libetpan/driver/implementation/imap/imapdriver_cached.h new file mode 100644 index 00000000..c7405bf0 --- /dev/null +++ b/Sources/libetpan/driver/implementation/imap/imapdriver_cached.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver_cached.h,v 1.11 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef IMAPDRIVER_CACHED_H + +#define IMAPDRIVER_CACHED_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * imap_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/imap/imapdriver_cached_message.c b/Sources/libetpan/driver/implementation/imap/imapdriver_cached_message.c new file mode 100644 index 00000000..59a1795a --- /dev/null +++ b/Sources/libetpan/driver/implementation/imap/imapdriver_cached_message.c @@ -0,0 +1,747 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver_cached_message.c,v 1.30 2008/09/14 11:01:50 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "imapdriver_cached_message.h" + +#include "imapdriver_tools.h" +#include "imapdriver_tools_private.h" +#include "imapdriver_message.h" +#include "imapdriver_cached.h" +#include "imapdriver_types.h" +#include "imapdriver.h" +#include "mailmessage.h" +#include "generic_cache.h" +#include "mail_cache_db.h" + +#include +#include + +static int imap_initialize(mailmessage * msg_info); + +static void imap_uninitialize(mailmessage * msg_info); + +static void imap_flush(mailmessage * msg_info); + +static void imap_check(mailmessage * msg_info); + +static void imap_fetch_result_free(mailmessage * msg_info, + char * msg); + +static int imap_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static int imap_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static int imap_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len); + +static int imap_fetch_size(mailmessage * msg_info, + size_t * result); + +static int imap_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result); + +static int imap_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + +static int imap_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +static int imap_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +static int imap_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + +static int imap_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result); + +static int imap_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +static mailmessage_driver local_imap_cached_message_driver = { + /* msg_name */ "imap-cached", + + /* msg_initialize */ imap_initialize, + /* msg_uninitialize */ imap_uninitialize, + + /* msg_flush */ imap_flush, + /* msg_check */ imap_check, + + /* msg_fetch_result_free */ imap_fetch_result_free, + + /* msg_fetch */ imap_fetch, + /* msg_fetch_header */ imap_fetch_header, + /* msg_fetch_body */ imap_fetch_body, + /* msg_fetch_size */ imap_fetch_size, + /* msg_get_bodystructure */ imap_get_bodystructure, + /* msg_fetch_section */ imap_fetch_section, + /* msg_fetch_section_header */ imap_fetch_section_header, + /* msg_fetch_section_mime */ imap_fetch_section_mime, + /* msg_fetch_section_body */ imap_fetch_section_body, + /* msg_fetch_envelope */ imap_fetch_envelope, + + /* msg_get_flags */ imap_get_flags +}; + +mailmessage_driver * imap_cached_message_driver = +&local_imap_cached_message_driver; + +static inline struct imap_cached_session_state_data * +get_cached_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline mailmessage * get_ancestor(mailmessage * msg_info) +{ + return msg_info->msg_data; +} + +static inline struct imap_cached_session_state_data * +cached_session_get_data(mailsession * s) +{ + return s->sess_data; +} + +static inline mailsession * cached_session_get_ancestor(mailsession * s) +{ + return cached_session_get_data(s)->imap_ancestor; +} + +static inline struct imap_session_state_data * +cached_session_get_ancestor_data(mailsession * s) +{ + return cached_session_get_ancestor(s)->sess_data; +} + +static inline mailimap * +cached_session_get_imap_session(mailsession * session) +{ + return cached_session_get_ancestor_data(session)->imap_session; +} + +static inline mailimap * get_imap_session(mailmessage * msg) +{ + return cached_session_get_imap_session(msg->msg_session); +} + +static inline mailsession * get_ancestor_session(mailmessage * msg_info) +{ + return cached_session_get_ancestor(msg_info->msg_session); +} + + +static void generate_key_from_mime_section(char * key, size_t size, + struct mailmime * mime) +{ + clistiter * cur; + MMAPString * gstr; + struct mailmime_section * part; + int r; + + snprintf(key, size, "unvalid"); + + r = mailmime_get_section_id(mime, &part); + if (r != MAILIMF_NO_ERROR) + goto err; + + gstr = mmap_string_new("part"); + if (gstr == NULL) + goto free_section; + + for(cur = clist_begin(part->sec_list) ; + cur != NULL ; cur = clist_next(cur)) { + char s[20]; + + snprintf(s, 20, ".%u", * (uint32_t *) clist_content(cur)); + if (mmap_string_append(gstr, s) == NULL) + goto free_str; + } + + snprintf(key, size, "%s", gstr->str); + + mmap_string_free(gstr); + mailmime_section_free(part); + + return; + + free_str: + mmap_string_free(gstr); + free_section: + mailmime_section_free(part); + err:; +} + +static void generate_key_from_section(char * key, size_t size, + mailmessage * msg_info, + struct mailmime * mime, int type) +{ + char section_str[PATH_MAX]; + + generate_key_from_mime_section(section_str, PATH_MAX, mime); + + switch (type) { + case IMAP_SECTION_MESSAGE: + snprintf(key, size, "%s-%s", msg_info->msg_uid, section_str); + break; + case IMAP_SECTION_HEADER: + snprintf(key, size, "%s-%s-header", msg_info->msg_uid, section_str); + break; + case IMAP_SECTION_MIME: + snprintf(key, size, "%s-%s-mime", msg_info->msg_uid, section_str); + break; + case IMAP_SECTION_BODY: + snprintf(key, size, "%s-%s-text", msg_info->msg_uid, section_str); + break; + } +} + +static void generate_key_from_message(char * key, size_t size, + mailmessage * msg_info, + int type) +{ + switch (type) { + case MAILIMAP_MSG_ATT_RFC822: + snprintf(key, size, "%s-rfc822", msg_info->msg_uid); + break; + case MAILIMAP_MSG_ATT_RFC822_HEADER: + snprintf(key, size, "%s-rfc822-header", msg_info->msg_uid); + break; + case MAILIMAP_MSG_ATT_RFC822_TEXT: + snprintf(key, size, "%s-rfc822-text", msg_info->msg_uid); + break; + case MAILIMAP_MSG_ATT_ENVELOPE: + snprintf(key, size, "%s-envelope", msg_info->msg_uid); + break; + case MAILIMAP_MSG_ATT_BODYSTRUCTURE: + snprintf(key, size, "%s-bodystructure", msg_info->msg_uid); + break; + } +} + +static void build_cache_name(char * filename, size_t size, + mailmessage * msg, char * key) +{ + char * quoted_mb; + + quoted_mb = get_cached_session_data(msg)->imap_quoted_mb; + + snprintf(filename, size, "%s/%s", quoted_mb, key); +} + +static int imap_initialize(mailmessage * msg_info) +{ + mailmessage * ancestor; + int r; + char key[PATH_MAX]; + char * uid; + mailimap * imap; + + ancestor = mailmessage_new(); + if (ancestor == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(ancestor, get_ancestor_session(msg_info), + imap_message_driver, + msg_info->msg_index, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(ancestor); + return r; + } + + imap = get_imap_session(msg_info); + + snprintf(key, PATH_MAX, "%u-%u", + imap->imap_selection_info->sel_uidvalidity, msg_info->msg_index); + uid = strdup(key); + if (uid == NULL) { + mailmessage_free(ancestor); + return MAIL_ERROR_MEMORY; + } + + msg_info->msg_data = ancestor; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; +} + +static void imap_uninitialize(mailmessage * msg_info) +{ + mailmessage_free(get_ancestor(msg_info)); + msg_info->msg_data = NULL; +} + +static void imap_flush(mailmessage * msg_info) +{ + if (msg_info->msg_mime != NULL) { + mailmime_free(msg_info->msg_mime); + msg_info->msg_mime = NULL; + } +} + +static void imap_check(mailmessage * msg_info) +{ + get_ancestor(msg_info)->msg_flags = msg_info->msg_flags; + mailmessage_check(get_ancestor(msg_info)); + get_ancestor(msg_info)->msg_flags = NULL; +} + +static void imap_fetch_result_free(mailmessage * msg_info, + char * msg) +{ + mailmessage_fetch_result_free(get_ancestor(msg_info), msg); +} + +static int imap_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + char key[PATH_MAX]; + char filename[PATH_MAX]; + int r; + char * str; + size_t len; + + generate_key_from_message(key, PATH_MAX, + msg_info, MAILIMAP_MSG_ATT_RFC822); + + build_cache_name(filename, PATH_MAX, msg_info, key); + + r = generic_cache_read(filename, &str, &len); + if (r == MAIL_NO_ERROR) { + * result = str; + * result_len = len; + + return MAIL_NO_ERROR; + } + + r = mailmessage_fetch(get_ancestor(msg_info), + result, result_len); + if (r == MAIL_NO_ERROR) + generic_cache_store(filename, * result, strlen(* result)); + + return r; +} + +static int imap_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + char key[PATH_MAX]; + char filename[PATH_MAX]; + int r; + char * str; + size_t len; + + generate_key_from_message(key, PATH_MAX, + msg_info, MAILIMAP_MSG_ATT_RFC822_HEADER); + + build_cache_name(filename, PATH_MAX, msg_info, key); + + r = generic_cache_read(filename, &str, &len); + if (r == MAIL_NO_ERROR) { + * result = str; + * result_len = len; + + return MAIL_NO_ERROR; + } + + r = mailmessage_fetch_header(get_ancestor(msg_info), result, + result_len); + if (r == MAIL_NO_ERROR) + generic_cache_store(filename, * result, * result_len); + + return r; +} + +static int imap_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len) +{ + char key[PATH_MAX]; + char filename[PATH_MAX]; + int r; + char * str; + size_t len; + + generate_key_from_message(key, PATH_MAX, + msg_info, MAILIMAP_MSG_ATT_RFC822_TEXT); + + build_cache_name(filename, PATH_MAX, msg_info, key); + + r = generic_cache_read(filename, &str, &len); + if (r == MAIL_NO_ERROR) { + * result = str; + * result_len = len; + return MAIL_NO_ERROR; + } + + r = mailmessage_fetch_body(get_ancestor(msg_info), result, + result_len); + if (r == MAIL_NO_ERROR) + generic_cache_store(filename, * result, * result_len); + + return r; +} + +static int imap_fetch_size(mailmessage * msg_info, + size_t * result) +{ + return mailmessage_fetch_size(get_ancestor(msg_info), result); +} + +static void cleanup_mime(struct mailmime * mime) +{ + mime->mm_mime_start = NULL; + mime->mm_length = 0; + if (mime->mm_body != NULL) { + mailmime_data_free(mime->mm_body); + mime->mm_body = NULL; + } + switch (mime->mm_type) { + case MAILMIME_SINGLE: + mime->mm_data.mm_single = NULL; + break; + case MAILMIME_MULTIPLE: + { + clistiter * cur; + + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * submime; + + submime = clist_content(cur); + cleanup_mime(submime); + } + } + break; + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_msg_mime != NULL) + cleanup_mime(mime->mm_data.mm_message.mm_msg_mime); + break; + } +} + +static int imap_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result) +{ + int r; + char key[PATH_MAX]; + char filename[PATH_MAX]; + char * str; + size_t len; + + if (msg_info->msg_mime != NULL) { + * result = msg_info->msg_mime; + + return MAIL_NO_ERROR; + } + + generate_key_from_message(key, PATH_MAX, + msg_info, MAILIMAP_MSG_ATT_BODYSTRUCTURE); + + build_cache_name(filename, PATH_MAX, msg_info, key); + + r = generic_cache_read(filename, &str, &len); + if (r == MAIL_NO_ERROR) { + size_t cur_index; + struct mailmime * mime; + + cur_index = 0; + r = mailmime_parse(str, len, &cur_index, &mime); + + mmap_string_unref(str); + + cleanup_mime(mime); + + msg_info->msg_mime = mime; + + * result = mime; + + return MAIL_NO_ERROR; + } + + r = mailmessage_get_bodystructure(get_ancestor(msg_info), + result); + if (r == MAIL_NO_ERROR) { + int col; + FILE * f; + + msg_info->msg_mime = get_ancestor(msg_info)->msg_mime; + get_ancestor(msg_info)->msg_mime = NULL; + + f = fopen(filename, "w"); + if (f == NULL) { + return MAIL_ERROR_FILE; + } + col = 0; + r = mailmime_write(f, &col, msg_info->msg_mime); + if (r != MAILIMF_NO_ERROR) { + fclose(f); + return MAIL_ERROR_FILE; + } + fclose(f); + } + + return r; +} + +static int imap_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + char key[PATH_MAX]; + char filename[PATH_MAX]; + int r; + char * str; + size_t len; + + generate_key_from_section(key, PATH_MAX, + msg_info, mime, IMAP_SECTION_MESSAGE); + + build_cache_name(filename, PATH_MAX, msg_info, key); + + r = generic_cache_read(filename, &str, &len); + if (r == MAIL_NO_ERROR) { + * result = str; + * result_len = len; + + return MAIL_NO_ERROR; + } + + r = mailmessage_fetch_section(get_ancestor(msg_info), + mime, result, result_len); + if (r == MAIL_NO_ERROR) + generic_cache_store(filename, * result, * result_len); + + return r; +} + +static int imap_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + char key[PATH_MAX]; + char filename[PATH_MAX]; + int r; + char * str; + size_t len; + + generate_key_from_section(key, PATH_MAX, + msg_info, mime, IMAP_SECTION_HEADER); + + build_cache_name(filename, PATH_MAX, msg_info, key); + + r = generic_cache_read(filename, &str, &len); + if (r == MAIL_NO_ERROR) { + * result = str; + * result_len = len; + + return MAIL_NO_ERROR; + } + + r = mailmessage_fetch_section_header(get_ancestor(msg_info), + mime, result, result_len); + if (r == MAIL_NO_ERROR) + generic_cache_store(filename, * result, * result_len); + + return r; +} + +static int imap_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + char key[PATH_MAX]; + char filename[PATH_MAX]; + int r; + char * str; + size_t len; + + generate_key_from_section(key, PATH_MAX, + msg_info, mime, IMAP_SECTION_MIME); + + build_cache_name(filename, PATH_MAX, msg_info, key); + + r = generic_cache_read(filename, &str, &len); + if (r == MAIL_NO_ERROR) { + * result = str; + * result_len = len; + + return MAIL_NO_ERROR; + } + + r = mailmessage_fetch_section_mime(get_ancestor(msg_info), + mime, result, result_len); + if (r == MAIL_NO_ERROR) + generic_cache_store(filename, * result, * result_len); + + return r; +} + +static int imap_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + char key[PATH_MAX]; + char filename[PATH_MAX]; + int r; + char * str; + size_t len; + + generate_key_from_section(key, PATH_MAX, + msg_info, mime, IMAP_SECTION_BODY); + + build_cache_name(filename, PATH_MAX, msg_info, key); + + r = generic_cache_read(filename, &str, &len); + if (r == MAIL_NO_ERROR) { + + * result = str; + * result_len = len; + + return MAIL_NO_ERROR; + } + + r = mailmessage_fetch_section_body(get_ancestor(msg_info), + mime, result, result_len); + if (r == MAIL_NO_ERROR) + generic_cache_store(filename, * result, * result_len); + + return r; +} + +static int imap_get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + int r; + struct mail_flags * flags; + + if (msg_info->msg_flags != NULL) { + * result = msg_info->msg_flags; + return MAIL_NO_ERROR; + } + + r = mailmessage_get_flags(get_ancestor(msg_info), &flags); + if (r != MAIL_NO_ERROR) + return r; + + get_ancestor(msg_info)->msg_flags = NULL; + msg_info->msg_flags = flags; + * result = flags; + + return MAIL_NO_ERROR; +} + +#define ENV_NAME "env.db" + +static int imap_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result) +{ + struct mailimf_fields * fields; + int r; + struct mail_cache_db * cache_db; + MMAPString * mmapstr; + char filename[PATH_MAX]; + struct imap_cached_session_state_data * data; + int res; + + data = get_cached_session_data(msg_info); + if (data->imap_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + snprintf(filename, PATH_MAX, "%s/%s", data->imap_quoted_mb, ENV_NAME); + + r = mail_cache_db_open_lock(filename, &cache_db); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db; + } + + r = imapdriver_get_cached_envelope(cache_db, mmapstr, + msg_info->msg_session, msg_info, &fields); + + if ((r != MAIL_ERROR_CACHE_MISS) && (r != MAIL_NO_ERROR)) { + res = r; + goto close_db; + } + + r = mailmessage_fetch_envelope(get_ancestor(msg_info), &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto close_db; + } + + r = imapdriver_write_cached_envelope(cache_db, mmapstr, + msg_info->msg_session, msg_info, fields); + + * result = fields; + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename, cache_db); + + return MAIL_NO_ERROR; + + close_db: + mail_cache_db_close_unlock(filename, cache_db); + err: + return res; +} diff --git a/Sources/libetpan/driver/implementation/imap/imapdriver_cached_message.h b/Sources/libetpan/driver/implementation/imap/imapdriver_cached_message.h new file mode 100644 index 00000000..3315c7d6 --- /dev/null +++ b/Sources/libetpan/driver/implementation/imap/imapdriver_cached_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver_cached_message.h,v 1.6 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef IMAPDRIVER_CACHED_MESSAGE_H + +#define IMAPDRIVER_CACHED_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * imap_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/imap/imapdriver_message.c b/Sources/libetpan/driver/implementation/imap/imapdriver_message.c new file mode 100644 index 00000000..b29d75ce --- /dev/null +++ b/Sources/libetpan/driver/implementation/imap/imapdriver_message.c @@ -0,0 +1,1244 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver_message.c,v 1.26 2008/02/17 13:13:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "imapdriver_message.h" + +#include "imapdriver_tools.h" +#include "imapdriver_tools_private.h" +#include "imapdriver.h" +#include "imapdriver_types.h" +#include "mailimap.h" +#include "maildriver_tools.h" +#include "generic_cache.h" + +#include +#include + +static int imap_initialize(mailmessage * msg_info); + +static void imap_fetch_result_free(mailmessage * msg_info, + char * msg); + +static int imap_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static int imap_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static int imap_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len); + +static int imap_fetch_size(mailmessage * msg_info, + size_t * result); + +static int imap_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result); + +static int imap_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + +static int imap_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +static int imap_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +static int imap_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +static int imap_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result); + +static int imap_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +static void imap_flush(mailmessage * msg_info); + +static void imap_check(mailmessage * msg_info); + +static mailmessage_driver local_imap_message_driver = { + /* msg_name */ "imap", + + /* msg_initialize */ imap_initialize, + /* msg_uninitialize */ NULL, + + /* msg_flush */ imap_flush, + /* msg_check */ imap_check, + + /* msg_fetch_result_free */ imap_fetch_result_free, + + /* msg_fetch */ imap_fetch, + /* msg_fetch_header */ imap_fetch_header, + /* msg_fetch_body */ imap_fetch_body, + /* msg_fetch_size */ imap_fetch_size, + /* msg_get_bodystructure */ imap_get_bodystructure, + /* msg_fetch_section */ imap_fetch_section, + /* msg_fetch_section_header */ imap_fetch_section_header, + /* msg_fetch_section_mime */ imap_fetch_section_mime, + /* msg_fetch_section_body */ imap_fetch_section_body, + /* msg_fetch_envelope */ imap_fetch_envelope, + + /* msg_get_flags */ imap_get_flags +}; + +mailmessage_driver * imap_message_driver = &local_imap_message_driver; + +static inline struct imap_session_state_data * +get_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline mailimap * get_imap_session(mailmessage * msg) +{ + return get_session_data(msg)->imap_session; +} + + + +static int imap_initialize(mailmessage * msg_info) +{ + char key[PATH_MAX]; + char * uid; + mailimap * imap; + + imap = get_imap_session(msg_info); + + snprintf(key, PATH_MAX, "%u-%u", + imap->imap_selection_info->sel_uidvalidity, msg_info->msg_index); + + uid = strdup(key); + if (uid == NULL) { + return MAIL_ERROR_MEMORY; + } + + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; +} + + +static void imap_fetch_result_free(mailmessage * msg_info, + char * msg) +{ + if (msg != NULL) { + if (mmap_string_unref(msg) != 0) + free(msg); + } +} + + +static void imap_flush(mailmessage * msg_info) +{ + if (msg_info->msg_mime != NULL) { + mailmime_free(msg_info->msg_mime); + msg_info->msg_mime = NULL; + } +} + +static void imap_check(mailmessage * msg_info) +{ + if (msg_info->msg_flags != NULL) { + mail_flags_store_set(get_session_data(msg_info)->imap_flags_store, + msg_info); + /* ignore errors */ + } +} + +static int imap_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + int r; + struct mailimap_set * set; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + clist * fetch_result; + struct mailimap_msg_att * msg_att; + struct mailimap_msg_att_item * msg_att_item; + char * text; + size_t text_length; + int res; + clistiter * cur; + struct mailimap_section * section; + + set = mailimap_set_new_single(msg_info->msg_index); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + +#if 0 + fetch_att = mailimap_fetch_att_new_rfc822(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_att; + } + + r = mailimap_uid_fetch(get_imap_session(msg_info->session), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); +#endif + + section = mailimap_section_new(NULL); + if (section == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + if (fetch_att == NULL) { + mailimap_section_free(section); + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_att; + } + + r = mailimap_uid_fetch(get_imap_session(msg_info), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + if (clist_begin(fetch_result) == NULL) { + mailimap_fetch_list_free(fetch_result); + return MAIL_ERROR_FETCH; + } + + msg_att = clist_begin(fetch_result)->data; + + text = NULL; + text_length = 0; + + for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; + cur = clist_next(cur)) { + msg_att_item = clist_content(cur); + + if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { +#if 0 + if (msg_att_item->msg_att_static->type == MAILIMAP_MSG_ATT_RFC822) { + text = msg_att_item->msg_att_static->rfc822; + msg_att_item->msg_att_static->rfc822 = NULL; + text_length = msg_att_item->msg_att_static->length; + } +#endif + if (msg_att_item->att_data.att_static->att_type == + MAILIMAP_MSG_ATT_BODY_SECTION) { + text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part; + /* detach */ + msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL; + text_length = + msg_att_item->att_data.att_static->att_data.att_body_section->sec_length; + } + } + } + + mailimap_fetch_list_free(fetch_result); + + if (text == NULL) + return MAIL_ERROR_FETCH; + + * result = text; + * result_len = text_length; + + return MAIL_NO_ERROR; + + free_fetch_att: + mailimap_fetch_att_free(fetch_att); + free_set: + mailimap_set_free(set); + err: + return res; +} + +static int imap_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + int r; + struct mailimap_set * set; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + clist * fetch_result; + struct mailimap_msg_att * msg_att; + struct mailimap_msg_att_item * msg_att_item; + char * text; + size_t text_length; + int res; + clistiter * cur; + struct mailimap_section * section; + + set = mailimap_set_new_single(msg_info->msg_index); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + +#if 0 + fetch_att = mailimap_fetch_att_new_rfc822_header(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_att; + } + + r = mailimap_uid_fetch(get_imap_session(msg_info->session), + set, fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); +#endif + + section = mailimap_section_new_header(); + if (section == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + if (fetch_att == NULL) { + mailimap_section_free(section); + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_att; + } + + r = mailimap_uid_fetch(get_imap_session(msg_info), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + if (clist_begin(fetch_result) == NULL) { + mailimap_fetch_list_free(fetch_result); + return MAIL_ERROR_FETCH; + } + + msg_att = clist_begin(fetch_result)->data; + + text = NULL; + text_length = 0; + + for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; + cur = clist_next(cur)) { + msg_att_item = clist_content(cur); + + if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { +#if 0 + if (msg_att_item->msg_att_static->type == + MAILIMAP_MSG_ATT_RFC822_HEADER) { + text = msg_att_item->msg_att_static->rfc822_header; + msg_att_item->msg_att_static->rfc822_header = NULL; + text_length = msg_att_item->msg_att_static->length; + } +#endif + if (msg_att_item->att_data.att_static->att_type == + MAILIMAP_MSG_ATT_BODY_SECTION) { + text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part; + msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL; + text_length = + msg_att_item->att_data.att_static->att_data.att_body_section->sec_length; + } + } + } + + mailimap_fetch_list_free(fetch_result); + + if (text == NULL) + return MAIL_ERROR_FETCH; + + * result = text; + * result_len = text_length; + + return MAIL_NO_ERROR; + + free_fetch_att: + mailimap_fetch_att_free(fetch_att); + free_set: + mailimap_set_free(set); + err: + return res; +} + +static int imap_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len) +{ + int r; + struct mailimap_set * set; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + clist * fetch_result; + struct mailimap_msg_att * msg_att; + struct mailimap_msg_att_item * msg_att_item; + char * text; + size_t text_length; + int res; + clistiter * cur; + struct mailimap_section * section; + + set = mailimap_set_new_single(msg_info->msg_index); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + +#if 0 + fetch_att = mailimap_fetch_att_new_rfc822_text(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_att; + } + + r = mailimap_uid_fetch(get_imap_session(msg_info->session), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); +#endif + section = mailimap_section_new_text(); + if (section == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + if (fetch_att == NULL) { + mailimap_section_free(section); + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_att; + } + + r = mailimap_uid_fetch(get_imap_session(msg_info), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + cur = clist_begin(fetch_result); + if (cur == NULL) { + mailimap_fetch_list_free(fetch_result); + return MAIL_ERROR_FETCH; + } + + msg_att = clist_content(cur); + + text = NULL; + text_length = 0; + + for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; + cur = clist_next(cur)) { + msg_att_item = clist_content(cur); + + if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { +#if 0 + if (msg_att_item->msg_att_static->type == + MAILIMAP_MSG_ATT_RFC822_TEXT) { + text = msg_att_item->msg_att_static->rfc822_text; + msg_att_item->msg_att_static->rfc822_text = NULL; + text_length = msg_att_item->msg_att_static->length; + } +#endif + if (msg_att_item->att_data.att_static->att_type == + MAILIMAP_MSG_ATT_BODY_SECTION) { + text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part; + msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL; + text_length = + msg_att_item->att_data.att_static->att_data.att_body_section->sec_length; + } + } + } + + mailimap_fetch_list_free(fetch_result); + + if (text == NULL) + return MAIL_ERROR_FETCH; + + * result = text; + * result_len = text_length; + + return MAIL_NO_ERROR; + + free_fetch_att: + mailimap_fetch_att_free(fetch_att); + free_set: + mailimap_set_free(set); + err: + return res; +} + +static int imap_fetch_size(mailmessage * msg_info, + size_t * result) +{ + int r; + struct mailimap_set * set; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + clist * fetch_result; + struct mailimap_msg_att * msg_att; + struct mailimap_msg_att_item * msg_att_item; + size_t size; + int res; + clistiter * cur; + + set = mailimap_set_new_single(msg_info->msg_index); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fetch_att = mailimap_fetch_att_new_rfc822_size(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_att; + } + + r = mailimap_uid_fetch(get_imap_session(msg_info), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_ERROR_BAD_STATE: + return MAIL_ERROR_BAD_STATE; + case MAILIMAP_ERROR_STREAM: + return MAIL_ERROR_STREAM; + case MAILIMAP_NO_ERROR: + break; + default: + return MAIL_ERROR_FETCH; + } + + if (clist_begin(fetch_result) == NULL) { + mailimap_fetch_list_free(fetch_result); + return MAIL_ERROR_FETCH; + } + + msg_att = clist_begin(fetch_result)->data; + + for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; + cur = clist_next(cur)) { + msg_att_item = clist_content(cur); + + if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { + + if (msg_att_item->att_data.att_static->att_type == + MAILIMAP_MSG_ATT_RFC822_SIZE) { + size = msg_att_item->att_data.att_static->att_data.att_rfc822_size; + + * result = size; + + mailimap_fetch_list_free(fetch_result); + return MAIL_NO_ERROR; + } + } + } + + mailimap_fetch_list_free(fetch_result); + + return MAIL_ERROR_FETCH; + + free_fetch_att: + mailimap_fetch_att_free(fetch_att); + free_set: + mailimap_set_free(set); + err: + return res; +} + +static int imap_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result) +{ + int r; + struct mailimap_set * set; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + clist * fetch_result; + struct mailimap_msg_att * msg_att; + struct mailimap_body * imap_body; + struct mailmime * body; + int res; + struct mailimf_fields * fields; + struct mailmime * new_body; + struct mailmime_content * content_message; + struct mailimap_envelope * envelope; + uint32_t uid; + char * references; + size_t ref_size; + clistiter * cur; + + if (msg_info->msg_mime != NULL) { + * result = msg_info->msg_mime; + + return MAIL_NO_ERROR; + } + + set = mailimap_set_new_single(msg_info->msg_index); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_att = mailimap_fetch_att_new_uid(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + fetch_att = mailimap_fetch_att_new_bodystructure(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = imap_add_envelope_fetch_att(fetch_type); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_fetch_type; + } + + + r = mailimap_uid_fetch(get_imap_session(msg_info), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + cur = clist_begin(fetch_result); + if (cur == NULL) { + mailimap_fetch_list_free(fetch_result); + return MAIL_ERROR_FETCH; + } + + msg_att = clist_content(cur); + + uid = 0; + references = NULL; + ref_size = 0; + imap_body = NULL; + envelope = NULL; + + r = imap_get_msg_att_info(msg_att, + &uid, &envelope, &references, &ref_size, NULL, &imap_body); + if (r != MAIL_NO_ERROR) { + mailimap_fetch_list_free(fetch_result); + res = r; + goto err; + } + + if (uid != msg_info->msg_index) { + mailimap_fetch_list_free(fetch_result); + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + if (imap_body == NULL) { + mailimap_fetch_list_free(fetch_result); + res = MAIL_ERROR_FETCH; + goto err; + } + + r = imap_body_to_body(imap_body, &body); + if (r != MAIL_NO_ERROR) { + mailimap_fetch_list_free(fetch_result); + res = r; + goto err; + } + + fields = NULL; + if (envelope != NULL) { + r = imap_env_to_fields(envelope, references, ref_size, &fields); + if (r != MAIL_NO_ERROR) { + mailmime_free(body); + mailimap_fetch_list_free(fetch_result); + res = r; + goto err; + } + } + + content_message = mailmime_get_content_message(); + if (content_message == NULL) { + if (fields != NULL) + mailimf_fields_free(fields); + mailmime_free(body); + mailimap_fetch_list_free(fetch_result); + res = MAIL_ERROR_MEMORY; + goto err; + } + + new_body = mailmime_new(MAILMIME_MESSAGE, NULL, + 0, NULL, content_message, + NULL, NULL, NULL, NULL, fields, body); + + if (new_body == NULL) { + mailmime_content_free(content_message); + if (fields != NULL) + mailimf_fields_free(fields); + mailmime_free(body); + mailimap_fetch_list_free(fetch_result); + res = MAIL_ERROR_MEMORY; + goto err; + } + msg_info->msg_mime = new_body; + + mailimap_fetch_list_free(fetch_result); + + * result = new_body; + + return MAIL_NO_ERROR; + + free_fetch_type: + mailimap_fetch_type_free(fetch_type); + free_set: + mailimap_set_free(set); + err: + return res; +} + +static int +fetch_imap(mailmessage * msg, + struct mailimap_fetch_type * fetch_type, + char ** result, size_t * result_len) +{ + int r; + struct mailimap_msg_att * msg_att; + struct mailimap_msg_att_item * msg_att_item; + clist * fetch_result; + struct mailimap_set * set; + char * text; + size_t text_length; + clistiter * cur; + + set = mailimap_set_new_single(msg->msg_index); + if (set == NULL) + return MAIL_ERROR_MEMORY; + + r = mailimap_uid_fetch(get_imap_session(msg), set, + fetch_type, &fetch_result); + + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + if (clist_begin(fetch_result) == NULL) { + mailimap_fetch_list_free(fetch_result); + return MAIL_ERROR_FETCH; + } + + msg_att = clist_begin(fetch_result)->data; + + text = NULL; + text_length = 0; + + for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; + cur = clist_next(cur)) { + msg_att_item = clist_content(cur); + + if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { + + if (msg_att_item->att_data.att_static->att_type == + MAILIMAP_MSG_ATT_BODY_SECTION) { + text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part; + msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL; + text_length = + msg_att_item->att_data.att_static->att_data.att_body_section->sec_length; + } + } + } + + mailimap_fetch_list_free(fetch_result); + + if (text == NULL) + return MAIL_ERROR_FETCH; + + * result = text; + * result_len = text_length; + + return MAIL_NO_ERROR; +} + + +static int imap_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + struct mailimap_section * section; + struct mailimap_fetch_att * fetch_att; + int r; + struct mailimap_fetch_type * fetch_type; + char * text; + size_t text_length; + struct mailmime_section * part; + + if (mime->mm_parent == NULL) + return imap_fetch(msg_info, result, result_len); + + r = mailmime_get_section_id(mime, &part); + if (r != MAILIMF_NO_ERROR) + return maildriver_imf_error_to_mail_error(r); + + r = imap_section_to_imap_section(part, IMAP_SECTION_MESSAGE, §ion); + mailmime_section_free(part); + if (r != MAIL_NO_ERROR) + return r; + + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + if (fetch_att == NULL) { + mailimap_section_free(section); + return MAIL_ERROR_MEMORY; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + mailimap_fetch_att_free(fetch_att); + return MAIL_ERROR_MEMORY; + } + + r = fetch_imap(msg_info, fetch_type, &text, &text_length); + + mailimap_fetch_type_free(fetch_type); + + if (r != MAIL_NO_ERROR) + return r; + + * result = text; + * result_len = text_length; + + return MAIL_NO_ERROR; +} + +static int imap_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + struct mailimap_section * section; + struct mailimap_fetch_att * fetch_att; + int r; + struct mailimap_fetch_type * fetch_type; + char * text; + size_t text_length; + struct mailmime_section * part; + + if (mime->mm_parent == NULL) + return imap_fetch_header(msg_info, result, result_len); + + r = mailmime_get_section_id(mime, &part); + if (r != MAILIMF_NO_ERROR) + return maildriver_imf_error_to_mail_error(r); + + r = imap_section_to_imap_section(part, IMAP_SECTION_HEADER, §ion); + mailmime_section_free(part); + if (r != MAIL_NO_ERROR) + return r; + + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + if (fetch_att == NULL) { + mailimap_section_free(section); + return MAIL_ERROR_MEMORY; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + mailimap_fetch_att_free(fetch_att); + return MAIL_ERROR_MEMORY; + } + + r = fetch_imap(msg_info, fetch_type, &text, &text_length); + mailimap_fetch_type_free(fetch_type); + + if (r != MAIL_NO_ERROR) + return r; + + * result = text; + * result_len = text_length; + + return MAIL_NO_ERROR; +} + +static int imap_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + struct mailimap_section * section; + struct mailimap_fetch_att * fetch_att; + int r; + struct mailimap_fetch_type * fetch_type; + char * text; + size_t text_length; + struct mailmime_section * part; + + if (mime->mm_parent == NULL) + return MAIL_ERROR_INVAL; + + if (mime->mm_parent->mm_parent == NULL) + return imap_fetch_header(msg_info, result, result_len); + + r = mailmime_get_section_id(mime, &part); + if (r != MAILIMF_NO_ERROR) + return maildriver_imf_error_to_mail_error(r); + + r = imap_section_to_imap_section(part, IMAP_SECTION_MIME, §ion); + mailmime_section_free(part); + if (r != MAIL_NO_ERROR) + return MAIL_ERROR_MEMORY; + + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + if (fetch_att == NULL) { + mailimap_section_free(section); + return MAIL_ERROR_MEMORY; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + mailimap_fetch_att_free(fetch_att); + return MAIL_ERROR_MEMORY; + } + + r = fetch_imap(msg_info, fetch_type, &text, &text_length); + + mailimap_fetch_type_free(fetch_type); + + if (r != MAIL_NO_ERROR) + return r; + + * result = text; + * result_len = text_length; + + return MAIL_NO_ERROR; +} + +static int imap_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + struct mailimap_section * section; + struct mailimap_fetch_att * fetch_att; + int r; + struct mailimap_fetch_type * fetch_type; + char * text; + size_t text_length; + struct mailmime_section * part; + + if (mime->mm_parent == NULL) + return imap_fetch_body(msg_info, result, result_len); + + if (mime->mm_parent->mm_parent == NULL) + return imap_fetch_body(msg_info, result, result_len); + + r = mailmime_get_section_id(mime, &part); + if (r != MAILIMF_NO_ERROR) + return maildriver_imf_error_to_mail_error(r); + + r = imap_section_to_imap_section(part, IMAP_SECTION_BODY, §ion); + mailmime_section_free(part); + if (r != MAIL_NO_ERROR) + return MAIL_ERROR_MEMORY; + + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + if (fetch_att == NULL) { + mailimap_section_free(section); + return MAIL_ERROR_MEMORY; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + mailimap_fetch_att_free(fetch_att); + return MAIL_ERROR_MEMORY; + } + + text = NULL; + text_length = 0; + r = fetch_imap(msg_info, fetch_type, &text, &text_length); + + mailimap_fetch_type_free(fetch_type); + + if (r != MAIL_NO_ERROR) + return r; + + * result = text; + * result_len = text_length; + + return MAIL_NO_ERROR; +} + +static int imap_get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + int r; + struct mail_flags * flags; + + if (msg_info->msg_flags != NULL) { + * result = msg_info->msg_flags; + return MAIL_NO_ERROR; + } + + flags = mail_flags_store_get(get_session_data(msg_info)->imap_flags_store, + msg_info->msg_index); + + if (flags == NULL) { + r = imap_fetch_flags(get_imap_session(msg_info), + msg_info->msg_index, &flags); + if (r != MAIL_NO_ERROR) + return r; + } + + msg_info->msg_flags = flags; + + * result = flags; + + return MAIL_NO_ERROR; +} + +static int imap_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result) +{ + int r; + struct mailimap_set * set; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + clist * fetch_result; + struct mailimap_msg_att * msg_att; + int res; + struct mailimf_fields * fields; + struct mailimap_envelope * envelope; + uint32_t uid; + char * references; + size_t ref_size; + + set = mailimap_set_new_single(msg_info->msg_index); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_att = mailimap_fetch_att_new_uid(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = imap_add_envelope_fetch_att(fetch_type); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_fetch_type; + } + + r = mailimap_uid_fetch(get_imap_session(msg_info), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + if (clist_begin(fetch_result) == NULL) { + mailimap_fetch_list_free(fetch_result); + return MAIL_ERROR_FETCH; + } + + msg_att = clist_begin(fetch_result)->data; + + uid = 0; + references = NULL; + ref_size = 0; + envelope = NULL; + + r = imap_get_msg_att_info(msg_att, + &uid, + &envelope, + &references, + &ref_size, + NULL, + NULL); + if (r != MAIL_NO_ERROR) { + mailimap_fetch_list_free(fetch_result); + res = r; + goto err; + } + + if (uid != msg_info->msg_index) { + mailimap_fetch_list_free(fetch_result); + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + fields = NULL; + if (envelope != NULL) { + r = imap_env_to_fields(envelope, references, ref_size, &fields); + if (r != MAIL_NO_ERROR) { + mailimap_fetch_list_free(fetch_result); + res = r; + goto err; + } + } + + mailimap_fetch_list_free(fetch_result); + + * result = fields; + + return MAIL_NO_ERROR; + + free_fetch_type: + mailimap_fetch_type_free(fetch_type); + free_set: + mailimap_set_free(set); + err: + return res; +} diff --git a/Sources/libetpan/driver/implementation/imap/imapdriver_message.h b/Sources/libetpan/driver/implementation/imap/imapdriver_message.h new file mode 100644 index 00000000..fe3be6cf --- /dev/null +++ b/Sources/libetpan/driver/implementation/imap/imapdriver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver_message.h,v 1.6 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef IMAPDRIVER_MESSAGE_H + +#define IMAPDRIVER_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * imap_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/imap/imapdriver_tools.c b/Sources/libetpan/driver/implementation/imap/imapdriver_tools.c new file mode 100644 index 00000000..55cbb3dd --- /dev/null +++ b/Sources/libetpan/driver/implementation/imap/imapdriver_tools.c @@ -0,0 +1,3730 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver_tools.c,v 1.38 2011/06/04 13:25:56 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "imapdriver_tools.h" +#include "imapdriver_tools_private.h" + +#include "maildriver.h" + +#include +#include + +#include "mail.h" +#include "imapdriver_types.h" +#include "maildriver_tools.h" +#include "generic_cache.h" +#include "mailmessage.h" +#include "mail_cache_db.h" + + + +static inline struct imap_session_state_data * +session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline struct imap_cached_session_state_data * +cached_session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * +cached_session_get_ancestor(mailsession * session) +{ + return cached_session_get_data(session)->imap_ancestor; +} + +static inline struct imap_session_state_data * +cached_session_get_ancestor_data(mailsession * session) +{ + return session_get_data(cached_session_get_ancestor(session)); +} + +static inline mailimap * +cached_session_get_imap_session(mailsession * session) +{ + return cached_session_get_ancestor_data(session)->imap_session; +} + +int imap_error_to_mail_error(int error) +{ + switch (error) { + case MAILIMAP_NO_ERROR: + return MAIL_NO_ERROR; + + case MAILIMAP_NO_ERROR_AUTHENTICATED: + return MAIL_NO_ERROR_AUTHENTICATED; + + case MAILIMAP_NO_ERROR_NON_AUTHENTICATED: + return MAIL_NO_ERROR_NON_AUTHENTICATED; + + case MAILIMAP_ERROR_BAD_STATE: + return MAIL_ERROR_BAD_STATE; + + case MAILIMAP_ERROR_STREAM: + return MAIL_ERROR_STREAM; + + case MAILIMAP_ERROR_PARSE: + return MAIL_ERROR_PARSE; + + case MAILIMAP_ERROR_CONNECTION_REFUSED: + return MAIL_ERROR_CONNECT; + + case MAILIMAP_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case MAILIMAP_ERROR_FATAL: + return MAIL_ERROR_FATAL; + + case MAILIMAP_ERROR_PROTOCOL: + return MAIL_ERROR_PROTOCOL; + + case MAILIMAP_ERROR_DONT_ACCEPT_CONNECTION: + return MAIL_ERROR_CONNECT; + + case MAILIMAP_ERROR_APPEND: + return MAIL_ERROR_APPEND; + + case MAILIMAP_ERROR_NOOP: + return MAIL_ERROR_NOOP; + + case MAILIMAP_ERROR_LOGOUT: + return MAIL_ERROR_LOGOUT; + + case MAILIMAP_ERROR_CAPABILITY: + return MAIL_ERROR_CAPABILITY; + + case MAILIMAP_ERROR_CHECK: + return MAIL_ERROR_CHECK; + + case MAILIMAP_ERROR_CLOSE: + return MAIL_ERROR_CLOSE; + + case MAILIMAP_ERROR_EXPUNGE: + return MAIL_ERROR_EXPUNGE; + + case MAILIMAP_ERROR_COPY: + case MAILIMAP_ERROR_UID_COPY: + return MAIL_ERROR_COPY; + + case MAILIMAP_ERROR_CREATE: + return MAIL_ERROR_CREATE; + + case MAILIMAP_ERROR_DELETE: + return MAIL_ERROR_DELETE; + + case MAILIMAP_ERROR_EXAMINE: + return MAIL_ERROR_EXAMINE; + + case MAILIMAP_ERROR_FETCH: + case MAILIMAP_ERROR_UID_FETCH: + return MAIL_ERROR_FETCH; + + case MAILIMAP_ERROR_LIST: + return MAIL_ERROR_LIST; + + case MAILIMAP_ERROR_LOGIN: + return MAIL_ERROR_LOGIN; + + case MAILIMAP_ERROR_LSUB: + return MAIL_ERROR_LSUB; + + case MAILIMAP_ERROR_RENAME: + return MAIL_ERROR_RENAME; + + case MAILIMAP_ERROR_SEARCH: + case MAILIMAP_ERROR_UID_SEARCH: + return MAIL_ERROR_SEARCH; + + case MAILIMAP_ERROR_SELECT: + return MAIL_ERROR_SELECT; + + case MAILIMAP_ERROR_STATUS: + return MAIL_ERROR_STATUS; + + case MAILIMAP_ERROR_STORE: + case MAILIMAP_ERROR_UID_STORE: + return MAIL_ERROR_STORE; + + case MAILIMAP_ERROR_SUBSCRIBE: + return MAIL_ERROR_SUBSCRIBE; + + case MAILIMAP_ERROR_UNSUBSCRIBE: + return MAIL_ERROR_UNSUBSCRIBE; + + case MAILIMAP_ERROR_STARTTLS: + return MAIL_ERROR_STARTTLS; + + case MAILIMAP_ERROR_SSL: + return MAIL_ERROR_SSL; + + case MAILIMAP_ERROR_INVAL: + return MAIL_ERROR_INVAL; + + default: + return MAIL_ERROR_INVAL; + } +} + + + + + +static int +imap_body_parameter_to_content(struct mailimap_body_fld_param * + body_parameter, + char * subtype, + struct mailmime_type * mime_type, + struct mailmime_content ** result); + +static int +imap_body_type_text_to_content_type(char * subtype, + struct mailimap_body_fld_param * + body_parameter, + struct mailmime_content ** result); + + +int imap_list_to_list(clist * imap_list, struct mail_list ** result) +{ + clistiter * cur; + clist * list; + struct mail_list * resp; + int r; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(cur = clist_begin(imap_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_mailbox_list * mb_list; + char * new_mb; + + mb_list = clist_content(cur); + + new_mb = strdup(mb_list->mb_name); + if (new_mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, new_mb); + if (r != 0) { + free(new_mb); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + resp = mail_list_new(list); + if (resp == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = resp; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + err: + return res; +} + +int +imap_section_to_imap_section(struct mailmime_section * section, int type, + struct mailimap_section ** result) +{ + struct mailimap_section_part * section_part; + struct mailimap_section * imap_section; + clist * list; + clistiter * cur; + int r; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(cur = clist_begin(section->sec_list) ; cur != NULL ; + cur = clist_next(cur)) { + uint32_t value; + uint32_t * id; + + value = * (uint32_t *) clist_content(cur); + id = malloc(sizeof(* id)); + if (id == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + * id = value; + r = clist_append(list, id); + if (r != 0) { + res = MAIL_ERROR_MEMORY; + free(id); + goto free_list; + } + } + + section_part = mailimap_section_part_new(list); + if (section_part == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + imap_section = NULL; + + switch (type) { + case IMAP_SECTION_MESSAGE: + imap_section = mailimap_section_new_part(section_part); + break; + case IMAP_SECTION_HEADER: + imap_section = mailimap_section_new_part_header(section_part); + break; + case IMAP_SECTION_MIME: + imap_section = mailimap_section_new_part_mime(section_part); + break; + case IMAP_SECTION_BODY: + imap_section = mailimap_section_new_part_text(section_part); + break; + } + + if (imap_section == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_part; + } + + * result = imap_section; + + return MAIL_NO_ERROR; + + free_part: + mailimap_section_part_free(section_part); + free_list: + if (list != NULL) { + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + } + err: + return res; +} + + + +static int +imap_body_media_basic_to_content_type(struct mailimap_media_basic * + media_basic, + struct mailimap_body_fld_param * + body_parameter, + struct mailmime_content ** result) +{ + struct mailmime_content * content; + struct mailmime_type * mime_type; + struct mailmime_discrete_type * discrete_type; + struct mailmime_composite_type * composite_type; + char * discrete_type_extension; + int discrete_type_type; + int composite_type_type; + int mime_type_type; + int r; + int res; + + discrete_type = NULL; + composite_type = NULL; + discrete_type_extension = NULL; + discrete_type_type = 0; + composite_type_type = 0; + mime_type_type = 0; + + switch (media_basic->med_type) { + case MAILIMAP_MEDIA_BASIC_APPLICATION: + mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE; + discrete_type_type = MAILMIME_DISCRETE_TYPE_APPLICATION; + break; + + case MAILIMAP_MEDIA_BASIC_AUDIO: + mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE; + discrete_type_type = MAILMIME_DISCRETE_TYPE_AUDIO; + break; + + case MAILIMAP_MEDIA_BASIC_IMAGE: + mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE; + discrete_type_type = MAILMIME_DISCRETE_TYPE_IMAGE; + break; + + case MAILIMAP_MEDIA_BASIC_MESSAGE: + mime_type_type = MAILMIME_TYPE_COMPOSITE_TYPE; + composite_type_type = MAILMIME_COMPOSITE_TYPE_MESSAGE; + break; + + case MAILIMAP_MEDIA_BASIC_VIDEO: + mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE; + discrete_type_type = MAILMIME_DISCRETE_TYPE_VIDEO; + break; + + case MAILIMAP_MEDIA_BASIC_OTHER: + mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE; + discrete_type_type = MAILMIME_DISCRETE_TYPE_EXTENSION; + discrete_type_extension = media_basic->med_basic_type; + if (discrete_type_extension == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + break; + + default: + res = MAIL_ERROR_INVAL; + goto err; + } + + switch (mime_type_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + if (discrete_type_extension != NULL) { + discrete_type_extension = strdup(discrete_type_extension); + if (discrete_type_extension == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + } + + discrete_type = mailmime_discrete_type_new(discrete_type_type, + discrete_type_extension); + if (discrete_type == NULL) { + if (discrete_type_extension != NULL) + free(discrete_type_extension); + res = MAIL_ERROR_MEMORY; + goto err; + } + + break; + + case MAILMIME_TYPE_COMPOSITE_TYPE: + composite_type = mailmime_composite_type_new(composite_type_type, + NULL); + if (composite_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + break; + + default: + res = MAIL_ERROR_INVAL; + goto err; + } + + mime_type = mailmime_type_new(mime_type_type, discrete_type, composite_type); + if (mime_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + r = imap_body_parameter_to_content(body_parameter, media_basic->med_subtype, + mime_type, &content); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_type; + } + + * result = content; + + return MAIL_NO_ERROR; + + free_type: + mailmime_type_free(mime_type); + free: + if (discrete_type != NULL) + mailmime_discrete_type_free(discrete_type); + if (composite_type != NULL) + mailmime_composite_type_free(composite_type); + err: + return res; +} + +static int +imap_disposition_to_mime_disposition(struct mailimap_body_fld_dsp * imap_dsp, + struct mailmime_disposition ** result) +{ + size_t cur_token; + int r; + struct mailmime_disposition_type * dsp_type; + struct mailmime_disposition * dsp; + clist * parameters; + int res; + + cur_token = 0; + r = mailmime_disposition_type_parse(imap_dsp->dsp_type, + strlen(imap_dsp->dsp_type), &cur_token, &dsp_type); + if (r == MAILIMF_ERROR_PARSE) { + dsp_type = mailmime_disposition_type_new(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, NULL); + if (dsp_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + } + else if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + parameters = clist_new(); + if (parameters == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if (imap_dsp->dsp_attributes != NULL) { + clistiter * cur; + + for(cur = clist_begin(imap_dsp->dsp_attributes->pa_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_single_body_fld_param * imap_param; + struct mailmime_disposition_parm * dsp_param; + struct mailmime_parameter * param; + char * filename; + char * creation_date; + char * modification_date; + char * read_date; + size_t size; + int type; + + imap_param = clist_content(cur); + + filename = NULL; + creation_date = NULL; + modification_date = NULL; + read_date = NULL; + size = 0; + param = NULL; + + type = mailmime_disposition_guess_type(imap_param->pa_name, + strlen(imap_param->pa_name), 0); + + switch (type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + if (strcasecmp(imap_param->pa_name, "filename") != 0) { + type = MAILMIME_DISPOSITION_PARM_PARAMETER; + break; + } + filename = strdup(imap_param->pa_value); + if (filename == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_dsp_type; + } + break; + + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + if (strcasecmp(imap_param->pa_name, "creation-date") != 0) { + type = MAILMIME_DISPOSITION_PARM_PARAMETER; + break; + } + creation_date = strdup(imap_param->pa_value); + if (creation_date == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_dsp_type; + } + break; + + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + if (strcasecmp(imap_param->pa_name, "modification-date") != 0) { + type = MAILMIME_DISPOSITION_PARM_PARAMETER; + break; + } + modification_date = strdup(imap_param->pa_value); + if (modification_date == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_dsp_type; + } + break; + + case MAILMIME_DISPOSITION_PARM_READ_DATE: + if (strcasecmp(imap_param->pa_name, "read-date") != 0) { + type = MAILMIME_DISPOSITION_PARM_PARAMETER; + break; + } + read_date = strdup(imap_param->pa_value); + if (read_date == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_dsp_type; + } + break; + + case MAILMIME_DISPOSITION_PARM_SIZE: + if (strcasecmp(imap_param->pa_name, "size") != 0) { + type = MAILMIME_DISPOSITION_PARM_PARAMETER; + break; + } + size = strtoul(imap_param->pa_value, NULL, 10); + break; + } + + if (type == MAILMIME_DISPOSITION_PARM_PARAMETER) { + char * name; + char * value; + + name = strdup(imap_param->pa_name); + if (name == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_dsp_type; + } + + value = strdup(imap_param->pa_value); + if (value == NULL) { + res = MAIL_ERROR_MEMORY; + free(name); + goto free_dsp_type; + } + + param = mailmime_parameter_new(name, value); + if (param == NULL) { + free(value); + free(name); + res = MAIL_ERROR_MEMORY; + goto free_dsp_type; + } + + } + + dsp_param = mailmime_disposition_parm_new(type, filename, + creation_date, + modification_date, + read_date, + size, param); + if (dsp_param == NULL) { + if (filename != NULL) + free(filename); + if (creation_date != NULL) + free(creation_date); + if (modification_date != NULL) + free(modification_date); + if (read_date != NULL) + free(read_date); + if (param != NULL) + mailmime_parameter_free(param); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(parameters, dsp_param); + if (r != 0) { + mailmime_disposition_parm_free(dsp_param); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + dsp = mailmime_disposition_new(dsp_type, parameters); + if (dsp == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = dsp; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(parameters, + (clist_func) mailmime_disposition_parm_free, NULL); + clist_free(parameters); + free_dsp_type: + mailmime_disposition_type_free(dsp_type); + err: + return res; +} + +static int +imap_language_to_mime_language(struct mailimap_body_fld_lang * imap_lang, + struct mailmime_language ** result) +{ + clist * list; + clistiter * cur; + int res; + char * single; + int r; + struct mailmime_language * lang; + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + switch (imap_lang->lg_type) { + case MAILIMAP_BODY_FLD_LANG_SINGLE: + if (imap_lang->lg_data.lg_single != NULL) { + single = strdup(imap_lang->lg_data.lg_single); + if (single == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + r = clist_append(list, single); + if (r < 0) { + free(single); + res = MAIL_ERROR_MEMORY; + goto free; + } + } + + break; + + case MAILIMAP_BODY_FLD_LANG_LIST: + for(cur = clist_begin(imap_lang->lg_data.lg_list) ; + cur != NULL ; cur = clist_next(cur)) { + char * original_single; + + original_single = clist_content(cur); + + single = strdup(original_single); + if (single == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + r = clist_append(list, single); + if (r < 0) { + free(single); + res = MAIL_ERROR_MEMORY; + goto free; + } + } + } + + lang = mailmime_language_new(list); + if (lang == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + * result = lang; + + return MAIL_NO_ERROR; + + free: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + err: + return res; +} + +static int +imap_body_fields_to_mime_fields(struct mailimap_body_fields * body_fields, + struct mailimap_body_fld_dsp * imap_dsp, + struct mailimap_body_fld_lang * imap_lang, + char * imap_loc, + struct mailmime_fields ** result, + uint32_t * pbody_size) +{ + struct mailmime_field * mime_field; + struct mailmime_fields * mime_fields; + clist * list; + char * id; + struct mailmime_mechanism * encoding; + char * description; + struct mailmime_disposition * dsp; + struct mailmime_language * lang; + char * loc; + int type; + int r; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if (body_fields != NULL) { + + if (pbody_size != NULL) + * pbody_size = body_fields->bd_size; + + if (body_fields->bd_id != NULL) { + type = MAILMIME_FIELD_ID; + id = strdup(body_fields->bd_id); + if (id == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + mime_field = mailmime_field_new(type, NULL, + NULL, id, NULL, 0, NULL, NULL, NULL); + if (mime_field == NULL) { + free(id); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, mime_field); + if (r != 0) { + mailmime_field_free(mime_field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + if (body_fields->bd_description != NULL) { + type = MAILMIME_FIELD_DESCRIPTION; + description = strdup(body_fields->bd_description); + if (description == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + mime_field = mailmime_field_new(type, NULL, + NULL, NULL, description, 0, NULL, NULL, NULL); + if (mime_field == NULL) { + free(description); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, mime_field); + if (r != 0) { + mailmime_field_free(mime_field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + if (body_fields->bd_encoding != NULL) { + char * encoding_value; + int encoding_type; + + type = MAILMIME_FIELD_TRANSFER_ENCODING; + + encoding_value = NULL; + switch (body_fields->bd_encoding->enc_type) { + case MAILIMAP_BODY_FLD_ENC_7BIT: + encoding_type = MAILMIME_MECHANISM_7BIT; + break; + case MAILIMAP_BODY_FLD_ENC_8BIT: + encoding_type = MAILMIME_MECHANISM_8BIT; + break; + case MAILIMAP_BODY_FLD_ENC_BINARY: + encoding_type = MAILMIME_MECHANISM_BINARY; + break; + case MAILIMAP_BODY_FLD_ENC_BASE64: + encoding_type = MAILMIME_MECHANISM_BASE64; + break; + case MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE: + encoding_type = MAILMIME_MECHANISM_QUOTED_PRINTABLE; + break; + case MAILIMAP_BODY_FLD_ENC_OTHER: + encoding_type = MAILMIME_MECHANISM_TOKEN; + encoding_value = strdup(body_fields->bd_encoding->enc_value); + if (encoding_value == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + break; + default: + res = MAIL_ERROR_INVAL; + goto free_list; + } + + encoding = mailmime_mechanism_new(encoding_type, encoding_value); + if (encoding == NULL) { + if (encoding_value != NULL) + free(encoding_value); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + mime_field = mailmime_field_new(type, NULL, + encoding, NULL, NULL, 0, NULL, NULL, NULL); + if (mime_field == NULL) { + mailmime_mechanism_free(encoding); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, mime_field); + if (r != 0) { + mailmime_field_free(mime_field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (imap_dsp != NULL) { + r = imap_disposition_to_mime_disposition(imap_dsp, &dsp); + if (r != MAIL_ERROR_PARSE) { + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + type = MAILMIME_FIELD_DISPOSITION; + + mime_field = mailmime_field_new(type, NULL, + NULL, NULL, NULL, 0, dsp, NULL, NULL); + if (mime_field == NULL) { + mailmime_disposition_free(dsp); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, mime_field); + if (r != 0) { + mailmime_field_free(mime_field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (imap_lang != NULL) { + int has_lang; + + has_lang = 1; + if (imap_lang->lg_type == MAILIMAP_BODY_FLD_LANG_SINGLE) + if (imap_lang->lg_data.lg_single == NULL) + has_lang = 0; + + if (has_lang) { + r = imap_language_to_mime_language(imap_lang, &lang); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + type = MAILMIME_FIELD_LANGUAGE; + + mime_field = mailmime_field_new(type, NULL, + NULL, NULL, NULL, 0, NULL, lang, NULL); + if (mime_field == NULL) { + mailmime_language_free(lang); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, mime_field); + if (r != 0) { + mailmime_field_free(mime_field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (imap_loc != NULL) { + type = MAILMIME_FIELD_LOCATION; + + loc = strdup(imap_loc); + if (loc == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + mime_field = mailmime_field_new(type, NULL, + NULL, NULL, NULL, 0, NULL, NULL, loc); + if (mime_field == NULL) { + mailmime_location_free(loc); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, mime_field); + if (r != 0) { + mailmime_field_free(mime_field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + mime_fields = mailmime_fields_new(list); + if (mime_fields == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = mime_fields; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailmime_field_free, NULL); + clist_free(list); + err: + return res; +} + +static int +imap_body_type_basic_to_body(struct mailimap_body_type_basic * + imap_type_basic, + struct mailimap_body_ext_1part * + body_ext_1part, + struct mailmime ** result) +{ + struct mailmime_content * content; + struct mailmime_fields * mime_fields; + struct mailmime * body; + int r; + int res; + uint32_t mime_size; + + content = NULL; + r = imap_body_media_basic_to_content_type(imap_type_basic->bd_media_basic, + imap_type_basic->bd_fields->bd_parameter, &content); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + if (body_ext_1part != NULL) + r = imap_body_fields_to_mime_fields(imap_type_basic->bd_fields, + body_ext_1part->bd_disposition, + body_ext_1part->bd_language, + body_ext_1part->bd_loc, + &mime_fields, &mime_size); + else + r = imap_body_fields_to_mime_fields(imap_type_basic->bd_fields, + NULL, NULL, NULL, + &mime_fields, &mime_size); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_content; + } + + body = mailmime_new(MAILMIME_SINGLE, NULL, + mime_size, mime_fields, content, + NULL, NULL, NULL, NULL, NULL, NULL); + + if (body == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fields; + } + + * result = body; + + return MAIL_NO_ERROR; + + free_fields: + mailmime_fields_free(mime_fields); + free_content: + mailmime_content_free(content); + err: + return res; +} + +static int +imap_body_type_text_to_body(struct mailimap_body_type_text * + imap_type_text, + struct mailimap_body_ext_1part * + body_ext_1part, + struct mailmime ** result) +{ + struct mailmime_content * content; + struct mailmime_fields * mime_fields; + struct mailmime * body; + int r; + int res; + uint32_t mime_size; + + r = imap_body_type_text_to_content_type(imap_type_text->bd_media_text, + imap_type_text->bd_fields->bd_parameter, + &content); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + if (body_ext_1part == NULL) { + r = imap_body_fields_to_mime_fields(imap_type_text->bd_fields, + NULL, NULL, NULL, + &mime_fields, &mime_size); + } + else { + r = imap_body_fields_to_mime_fields(imap_type_text->bd_fields, + body_ext_1part->bd_disposition, + body_ext_1part->bd_language, + body_ext_1part->bd_loc, + &mime_fields, &mime_size); + } + if (r != MAIL_NO_ERROR) { + res = r; + goto free_content; + } + + body = mailmime_new(MAILMIME_SINGLE, NULL, + mime_size, mime_fields, content, + NULL, NULL, NULL, NULL, NULL, NULL); + + if (body == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fields; + } + + * result = body; + + return MAIL_NO_ERROR; + + free_fields: + mailmime_fields_free(mime_fields); + free_content: + mailmime_content_free(content); + err: + return res; +} + +static int +imap_body_parameter_to_content(struct mailimap_body_fld_param * + body_parameter, + char * subtype, + struct mailmime_type * mime_type, + struct mailmime_content ** result) +{ + clist * parameters; + char * new_subtype; + struct mailmime_content * content; + int r; + int res; + + new_subtype = strdup(subtype); + if (new_subtype == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + parameters = clist_new(); + if (parameters == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_subtype; + } + + if (body_parameter != NULL) { + clistiter * cur; + + for(cur = clist_begin(body_parameter->pa_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_single_body_fld_param * imap_param; + struct mailmime_parameter * param; + char * name; + char * value; + + imap_param = clist_content(cur); + name = strdup(imap_param->pa_name); + if (name == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_parameters; + } + + value = strdup(imap_param->pa_value); + if (value == NULL) { + free(name); + res = MAIL_ERROR_MEMORY; + goto free_parameters; + } + + param = mailmime_parameter_new(name, value); + if (param == NULL) { + free(value); + free(name); + res = MAIL_ERROR_MEMORY; + goto free_parameters; + } + + r = clist_append(parameters, param); + if (r != 0) { + mailmime_parameter_free(param); + res = MAIL_ERROR_MEMORY; + goto free_parameters; + } + } + } + + content = mailmime_content_new(mime_type, new_subtype, parameters); + if (content == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_parameters; + } + + * result = content; + + return MAIL_NO_ERROR; + + free_parameters: + clist_foreach(parameters, (clist_func) mailmime_parameter_free, NULL); + clist_free(parameters); + free_subtype: + free(new_subtype); + err: + return res; +} + +static int +imap_body_type_text_to_content_type(char * subtype, + struct mailimap_body_fld_param * + body_parameter, + struct mailmime_content ** result) +{ + struct mailmime_content * content; + struct mailmime_type * mime_type; + struct mailmime_discrete_type * discrete_type; + int r; + int res; + + discrete_type = NULL; + + discrete_type = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT, + NULL); + if (discrete_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + mime_type = mailmime_type_new(MAILMIME_TYPE_DISCRETE_TYPE, + discrete_type, NULL); + if (mime_type == NULL) { + mailmime_discrete_type_free(discrete_type); + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = imap_body_parameter_to_content(body_parameter, subtype, + mime_type, &content); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_type; + } + + * result = content; + + return MAIL_NO_ERROR; + + free_type: + mailmime_type_free(mime_type); + err: + return res; +} + + +static int +imap_body_type_msg_to_body(struct mailimap_body_type_msg * + imap_type_msg, + struct mailimap_body_ext_1part * + body_ext_1part, + struct mailmime ** result) +{ + struct mailmime * body; + struct mailmime * msg_body; + struct mailmime_fields * mime_fields; + struct mailmime_composite_type * composite_type; + struct mailmime_type * mime_type; + struct mailmime_content * content_type; + struct mailimf_fields * fields; + int r; + int res; + uint32_t mime_size; + + if (body_ext_1part != NULL) { + r = imap_body_fields_to_mime_fields(imap_type_msg->bd_fields, + body_ext_1part->bd_disposition, body_ext_1part->bd_language, body_ext_1part->bd_loc, + &mime_fields, &mime_size); + } + else { + r = imap_body_fields_to_mime_fields(imap_type_msg->bd_fields, + NULL, NULL, NULL, + &mime_fields, &mime_size); + } + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = imap_env_to_fields(imap_type_msg->bd_envelope, NULL, 0, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mime_fields; + } + + r = imap_body_to_body(imap_type_msg->bd_body, &msg_body); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_fields; + } + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MESSAGE, + NULL); + if (composite_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fields; + } + + mime_type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, + NULL, composite_type); + if (mime_type == NULL) { + mailmime_composite_type_free(composite_type); + res = MAIL_ERROR_MEMORY; + goto free_fields; + } + + r = imap_body_parameter_to_content(imap_type_msg->bd_fields->bd_parameter, + "rfc822", mime_type, &content_type); + if (r != MAIL_NO_ERROR) { + mailmime_type_free(mime_type); + res = MAIL_ERROR_MEMORY; + goto free_fields; + } + + body = mailmime_new(MAILMIME_MESSAGE, NULL, + mime_size, mime_fields, content_type, + NULL, NULL, NULL, NULL, fields, msg_body); + + if (body == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_content; + } + + * result = body; + + return MAIL_NO_ERROR; + + free_content: + mailmime_content_free(content_type); + free_fields: + mailimf_fields_free(fields); + free_mime_fields: + mailmime_fields_free(mime_fields); + err: + return res; +} + + +static int +imap_body_type_1part_to_body(struct mailimap_body_type_1part * + type_1part, + struct mailmime ** result) +{ + struct mailmime * body; + int r; + int res; + + body = NULL; + switch (type_1part->bd_type) { + case MAILIMAP_BODY_TYPE_1PART_BASIC: + r = imap_body_type_basic_to_body(type_1part->bd_data.bd_type_basic, + type_1part->bd_ext_1part, + &body); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + break; + case MAILIMAP_BODY_TYPE_1PART_MSG: + r = imap_body_type_msg_to_body(type_1part->bd_data.bd_type_msg, + type_1part->bd_ext_1part, + &body); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + break; + case MAILIMAP_BODY_TYPE_1PART_TEXT: + r = imap_body_type_text_to_body(type_1part->bd_data.bd_type_text, + type_1part->bd_ext_1part, + &body); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + break; + } + + * result = body; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +imap_body_type_mpart_to_body(struct mailimap_body_type_mpart * + type_mpart, + struct mailmime ** result) +{ + struct mailmime_fields * mime_fields; + struct mailmime_composite_type * composite_type; + struct mailmime_type * mime_type; + struct mailmime_content * content_type; + struct mailmime * body; + clistiter * cur; + clist * list; + int r; + int res; + uint32_t mime_size; + + if (type_mpart->bd_ext_mpart == NULL) { + mime_fields = mailmime_fields_new_empty(); + mime_size = 0; + r = MAIL_NO_ERROR; + } + else { + r = imap_body_fields_to_mime_fields(NULL, + type_mpart->bd_ext_mpart->bd_disposition, + type_mpart->bd_ext_mpart->bd_language, + type_mpart->bd_ext_mpart->bd_loc, + &mime_fields, &mime_size); + } + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MULTIPART, + NULL); + if (composite_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fields; + } + + mime_type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, + NULL, composite_type); + if (mime_type == NULL) { + mailmime_composite_type_free(composite_type); + res = MAIL_ERROR_MEMORY; + goto free_fields; + } + + if (type_mpart->bd_ext_mpart == NULL) { + r = imap_body_parameter_to_content(NULL, + type_mpart->bd_media_subtype, + mime_type, &content_type); + } + else { + r = imap_body_parameter_to_content(type_mpart->bd_ext_mpart->bd_parameter, + type_mpart->bd_media_subtype, + mime_type, &content_type); + } + if (r != MAIL_NO_ERROR) { + mailmime_type_free(mime_type); + res = r; + goto free_fields; + } + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_content; + } + + for(cur = clist_begin(type_mpart->bd_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_body * imap_body; + struct mailmime * sub_body; + + imap_body = clist_content(cur); + + r = imap_body_to_body(imap_body, &sub_body); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(list, sub_body); + if (r != 0) { + mailmime_free(sub_body); + res = r; + goto free_list; + } + } + + body = mailmime_new(MAILMIME_MULTIPLE, NULL, + mime_size, mime_fields, content_type, + NULL, NULL, NULL, list, NULL, NULL); + + if (body == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = body; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailmime_free, NULL); + clist_free(list); + free_content: + mailmime_content_free(content_type); + free_fields: + mailmime_fields_free(mime_fields); + err: + return res; +} + + +int imap_body_to_body(struct mailimap_body * imap_body, + struct mailmime ** result) +{ + struct mailmime * body; + int r; + int res; + + body = NULL; + switch (imap_body->bd_type) { + case MAILIMAP_BODY_1PART: + r = imap_body_type_1part_to_body(imap_body->bd_data.bd_body_1part, &body); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMAP_BODY_MPART: + r = imap_body_type_mpart_to_body(imap_body->bd_data.bd_body_mpart, &body); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + break; + default: + return MAIL_ERROR_INVAL; + } + + * result = body; + + return MAIL_NO_ERROR; + + err: + return res; +} + +int imap_address_to_mailbox(struct mailimap_address * imap_addr, + struct mailimf_mailbox ** result) +{ + char * dsp_name; + char * addr; + struct mailimf_mailbox * mb; + int res; + + if (imap_addr->ad_personal_name == NULL) + dsp_name = NULL; + else { + dsp_name = strdup(imap_addr->ad_personal_name); + if (dsp_name == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + } + + if (imap_addr->ad_host_name == NULL) { + if (imap_addr->ad_mailbox_name == NULL) { + addr = strdup(""); + } + else { + addr = strdup(imap_addr->ad_mailbox_name); + } + if (addr == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_name; + } + } + else if (imap_addr->ad_mailbox_name == NULL) { + // fix by Gabor Cselle, (http://gaborcselle.com/), reported 8/16/2009 + addr = strdup(imap_addr->ad_host_name); + if (addr == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_name; + } + } + else { + addr = malloc(strlen(imap_addr->ad_mailbox_name) + + strlen(imap_addr->ad_host_name) + 2); + if (addr == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_name; + } + strcpy(addr, imap_addr->ad_mailbox_name); + strcat(addr, "@"); + strcat(addr, imap_addr->ad_host_name); + } + + mb = mailimf_mailbox_new(dsp_name, addr); + if (mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_addr; + } + + * result = mb; + + return MAIL_NO_ERROR; + + free_addr: + free(addr); + free_name: + free(dsp_name); + err: + return res; +} + +int imap_address_to_address(struct mailimap_address * imap_addr, + struct mailimf_address ** result) +{ + struct mailimf_address * addr; + struct mailimf_mailbox * mb; + int r; + int res; + + r = imap_address_to_mailbox(imap_addr, &mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + if (addr == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_mb; + } + + * result = addr; + + return MAIL_NO_ERROR; + + free_mb: + mailimf_mailbox_free(mb); + err: + return res; +} + +int +imap_mailbox_list_to_mailbox_list(clist * imap_mailbox_list, + struct mailimf_mailbox_list ** result) +{ + clistiter * cur; + clist * list; + struct mailimf_mailbox_list * mb_list; + int r; + + list = clist_new(); + if (list == NULL) { + goto err; + } + + for(cur = clist_begin(imap_mailbox_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_address * imap_addr; + struct mailimf_mailbox * mb; + + imap_addr = clist_content(cur); + + if (imap_addr->ad_mailbox_name == NULL) + continue; + + r = imap_address_to_mailbox(imap_addr, &mb); + if (r != MAIL_NO_ERROR) { + goto free_list; + } + + r = clist_append(list, mb); + if (r != 0) { + mailimf_mailbox_free(mb); + goto free_list; + } + } + + mb_list = mailimf_mailbox_list_new(list); + if (mb_list == NULL) { + goto free_list; + } + + * result = mb_list; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL); + clist_free(list); + err: + return MAIL_ERROR_MEMORY; +} + + + +/* + at exit, imap_mb_list will fall on the last element of the group, + where mailbox name will be NIL, so that imap_mailbox_list_to_address_list + can continue +*/ + +static int imap_mailbox_list_to_group(clist * imap_mb_list, clistiter ** iter, + struct mailimf_group ** result) +{ + clistiter * imap_mailbox_listiter; + clist * list; + struct mailimf_group * group; + struct mailimap_address * imap_addr; + char * group_name; + clistiter * cur; + struct mailimf_mailbox_list * mb_list; + int r; + int res; + + imap_mailbox_listiter = * iter; + + imap_addr = clist_content(imap_mailbox_listiter); + if (imap_addr == NULL || imap_addr->ad_mailbox_name == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + group_name = strdup(imap_addr->ad_mailbox_name); + if (group_name == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_group_name; + } + + for(cur = clist_next(imap_mailbox_listiter) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + imap_addr = clist_content(cur); + + if (imap_addr->ad_mailbox_name == NULL) { + break; + } + + r = imap_address_to_mailbox(imap_addr, &mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(list, mb); + if (r != 0) { + mailimf_mailbox_free(mb); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + mb_list = mailimf_mailbox_list_new(list); + if (mb_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + group = mailimf_group_new(group_name, mb_list); + if (group == NULL) { + mailimf_mailbox_list_free(mb_list); + res = MAIL_ERROR_MEMORY; + goto free_group_name; + } + + * result = group; + * iter = cur; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL); + clist_free(list); + free_group_name: + free(group_name); + err: + return res; +} + +int +imap_mailbox_list_to_address_list(clist * imap_mailbox_list, + struct mailimf_address_list ** result) +{ + clistiter * cur; + clist * list; + struct mailimf_address_list * addr_list; + int r; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(cur = clist_begin(imap_mailbox_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_address * imap_addr; + struct mailimf_address * addr; + + imap_addr = clist_content(cur); + + if (imap_addr->ad_mailbox_name == NULL) + continue; + + if ((imap_addr->ad_host_name == NULL) && + (imap_addr->ad_mailbox_name != NULL)) { + struct mailimf_group * group; + + group = NULL; + r = imap_mailbox_list_to_group(imap_mailbox_list, &cur, &group); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + addr = mailimf_address_new(MAILIMF_ADDRESS_GROUP, NULL, group); + if (addr == NULL) { + mailimf_group_free(group); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + else { + r = imap_address_to_address(imap_addr, &addr); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + } + + r = clist_append(list, addr); + if (r != 0) { + mailimf_address_free(addr); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + addr_list = mailimf_address_list_new(list); + if (addr_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = addr_list; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_address_free, NULL); + clist_free(list); + err: + return res; +} + + +int imap_add_envelope_fetch_att(struct mailimap_fetch_type * fetch_type) +{ + struct mailimap_fetch_att * fetch_att; + int res; + int r; + char * header; + clist * hdrlist; + struct mailimap_header_list * imap_hdrlist; + struct mailimap_section * section; + + fetch_att = mailimap_fetch_att_new_envelope(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto err; + } + + header = strdup("References"); + if (header == NULL) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto err; + } + + hdrlist = clist_new(); + if (hdrlist == NULL) { + free(header); + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = clist_append(hdrlist, header); + if (r < 0) { + free(header); + clist_foreach(hdrlist, (clist_func) free, NULL); + clist_free(hdrlist); + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto err; + } + + imap_hdrlist = mailimap_header_list_new(hdrlist); + if (imap_hdrlist == NULL) { + clist_foreach(hdrlist, (clist_func) free, NULL); + clist_free(hdrlist); + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto err; + } + + section = mailimap_section_new_header_fields(imap_hdrlist); + if (section == NULL) { + mailimap_header_list_free(imap_hdrlist); + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto err; + } + + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + if (fetch_att == NULL) { + mailimap_section_free(section); + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + +int imap_env_to_fields(struct mailimap_envelope * env, + char * ref_str, size_t ref_size, + struct mailimf_fields ** result) +{ + clist * list; + struct mailimf_field * field; + int r; + struct mailimf_fields * fields; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if (env->env_date != NULL) { + size_t cur_token; + struct mailimf_date_time * date_time; + + cur_token = 0; + r = mailimf_date_time_parse(env->env_date, strlen(env->env_date), + &cur_token, &date_time); + + if (r == MAILIMF_NO_ERROR) { + struct mailimf_orig_date * orig; + + orig = mailimf_orig_date_new(date_time); + if (orig == NULL) { + mailimf_date_time_free(date_time); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_ORIG_DATE, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, orig, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_orig_date_free(orig); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (env->env_subject != NULL) { + char * subject; + struct mailimf_subject * subject_field; + + subject = strdup(env->env_subject); + if (subject == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + + subject_field = mailimf_subject_new(subject); + if (subject_field == NULL) { + free(subject); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_SUBJECT, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, subject_field, NULL, NULL, NULL); + if (field == NULL) { + mailimf_subject_free(subject_field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + if (env->env_from != NULL) { + if (env->env_from->frm_list != NULL) { + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + + r = imap_mailbox_list_to_mailbox_list(env->env_from->frm_list, &mb_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + from = mailimf_from_new(mb_list); + if (from == NULL) { + mailimf_mailbox_list_free(mb_list); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, from, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_from_free(from); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (env->env_sender != NULL) { + if (env->env_sender->snd_list != NULL) { + struct mailimf_sender * sender; + struct mailimf_mailbox * mb; + + r = imap_address_to_mailbox(clist_begin(env->env_sender->snd_list)->data, &mb); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + sender = mailimf_sender_new(mb); + if (sender == NULL) { + mailimf_mailbox_free(mb); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_SENDER, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + sender, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_sender_free(sender); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (env->env_reply_to != NULL) { + if (env->env_reply_to->rt_list != NULL) { + struct mailimf_address_list * addr_list; + struct mailimf_reply_to * reply_to; + + r = imap_mailbox_list_to_address_list(env->env_reply_to->rt_list, + &addr_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + reply_to = mailimf_reply_to_new(addr_list); + if (reply_to == NULL) { + mailimf_address_list_free(addr_list); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_REPLY_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, reply_to, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_reply_to_free(reply_to); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (env->env_to != NULL) { + if (env->env_to->to_list != NULL) { + struct mailimf_address_list * addr_list; + struct mailimf_to * to; + + r = imap_mailbox_list_to_address_list(env->env_to->to_list, &addr_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + to = mailimf_to_new(addr_list); + if (to == NULL) { + mailimf_address_list_free(addr_list); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, to, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_to_free(to); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (env->env_cc != NULL) { + if (env->env_cc->cc_list != NULL) { + struct mailimf_address_list * addr_list; + struct mailimf_cc * cc; + + r = imap_mailbox_list_to_address_list(env->env_cc->cc_list, &addr_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + cc = mailimf_cc_new(addr_list); + if (cc == NULL) { + mailimf_address_list_free(addr_list); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_CC, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, cc, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_cc_free(cc); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (env->env_bcc != NULL) { + if (env->env_bcc->bcc_list != NULL) { + struct mailimf_address_list * addr_list; + struct mailimf_bcc * bcc; + + r = imap_mailbox_list_to_address_list(env->env_bcc->bcc_list, + &addr_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + bcc = mailimf_bcc_new(addr_list); + if (bcc == NULL) { + mailimf_address_list_free(addr_list); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_BCC, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, bcc, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_bcc_free(bcc); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (env->env_in_reply_to != NULL) { + struct mailimf_in_reply_to * in_reply_to; + size_t cur_token; + clist * msg_id_list; + + cur_token = 0; + r = mailimf_msg_id_list_parse(env->env_in_reply_to, + strlen(env->env_in_reply_to), &cur_token, &msg_id_list); + + switch (r) { + case MAILIMF_NO_ERROR: + in_reply_to = mailimf_in_reply_to_new(msg_id_list); + if (in_reply_to == NULL) { + clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL); + clist_free(msg_id_list); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_IN_REPLY_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + in_reply_to, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_in_reply_to_free(in_reply_to); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + break; + + case MAILIMF_ERROR_PARSE: + break; + + default: + res = maildriver_imf_error_to_mail_error(r); + goto free_list; + } + } + + if (env->env_message_id != NULL) { + char * id; + struct mailimf_message_id * msg_id; + size_t cur_token; + + cur_token = 0; + r = mailimf_msg_id_parse(env->env_message_id, strlen(env->env_message_id), + &cur_token, &id); + switch (r) { + case MAILIMF_NO_ERROR: + + msg_id = mailimf_message_id_new(id); + if (msg_id == NULL) { + mailimf_msg_id_free(id); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, msg_id, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_message_id_free(msg_id); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + break; + + case MAILIMF_ERROR_PARSE: + break; + + default: + res = maildriver_imf_error_to_mail_error(r); + goto free_list; + } + } + + if (ref_str != NULL) { + struct mailimf_references * references; + size_t cur_token; + + cur_token = 0; + r = mailimf_references_parse(ref_str, ref_size, + &cur_token, &references); + switch (r) { + case MAILIMF_NO_ERROR: + field = mailimf_field_new(MAILIMF_FIELD_REFERENCES, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, + references, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_references_free(references); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + break; + + case MAILIMF_ERROR_PARSE: + break; + + default: + res = maildriver_imf_error_to_mail_error(r); + goto free_list; + } + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = fields; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + err: + return res; +} + +int imap_get_msg_att_info(struct mailimap_msg_att * msg_att, + uint32_t * puid, + struct mailimap_envelope ** pimap_envelope, + char ** preferences, + size_t * pref_size, + struct mailimap_msg_att_dynamic ** patt_dyn, + struct mailimap_body ** pimap_body) +{ + clistiter * item_cur; + uint32_t uid; + struct mailimap_envelope * imap_envelope; + char * references; + size_t ref_size; + struct mailimap_msg_att_dynamic * att_dyn; + struct mailimap_body * imap_body; + + uid = 0; + imap_envelope = NULL; + references = NULL; + ref_size = 0; + att_dyn = NULL; + imap_body = NULL; + + for(item_cur = clist_begin(msg_att->att_list) ; item_cur != NULL ; + item_cur = clist_next(item_cur)) { + struct mailimap_msg_att_item * item; + + item = clist_content(item_cur); + + switch (item->att_type) { + case MAILIMAP_MSG_ATT_ITEM_STATIC: + switch (item->att_data.att_static->att_type) { + case MAILIMAP_MSG_ATT_BODYSTRUCTURE: + if (imap_body == NULL) + imap_body = item->att_data.att_static->att_data.att_bodystructure; + break; + + case MAILIMAP_MSG_ATT_ENVELOPE: + if (imap_envelope == NULL) { + imap_envelope = item->att_data.att_static->att_data.att_env; + } + break; + + case MAILIMAP_MSG_ATT_UID: + uid = item->att_data.att_static->att_data.att_uid; + break; + + case MAILIMAP_MSG_ATT_BODY_SECTION: + if (references == NULL) { + references = item->att_data.att_static->att_data.att_body_section->sec_body_part; + ref_size = item->att_data.att_static->att_data.att_body_section->sec_length; + } + break; + } + break; + + case MAILIMAP_MSG_ATT_ITEM_DYNAMIC: + if (att_dyn == NULL) { + att_dyn = item->att_data.att_dyn; + } + break; + } + } + + if (puid != NULL) + * puid = uid; + if (pimap_envelope != NULL) + * pimap_envelope = imap_envelope; + if (preferences != NULL) + * preferences = references; + if (pref_size != NULL) + * pref_size = ref_size; + if (patt_dyn != NULL) + * patt_dyn = att_dyn; + if (pimap_body != NULL) + * pimap_body = imap_body; + + return MAIL_NO_ERROR; +} + +int +imap_fetch_result_to_envelop_list(clist * fetch_result, + struct mailmessage_list * env_list) +{ + clistiter * cur; + int r; + unsigned int i; + chash * msg_hash; + int res; + + msg_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + if (msg_hash == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + chashdatum key; + chashdatum value; + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + key.data = &msg->msg_index; + key.len = sizeof(msg->msg_index); + value.data = msg; + value.len = 0; + r = chash_set(msg_hash, &key, &value, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_hash; + } + } + + for(cur = clist_begin(fetch_result) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_msg_att * msg_att; + uint32_t uid; + struct mailimap_envelope * imap_envelope; + struct mailimap_msg_att_dynamic * att_dyn; + char * references; + size_t ref_size; + + msg_att = clist_content(cur); + + r = imap_get_msg_att_info(msg_att, &uid, &imap_envelope, + &references, &ref_size, + &att_dyn, + NULL); + + if (r == MAIL_NO_ERROR) { + if (uid != 0) { + chashdatum key; + chashdatum value; + + key.data = &uid; + key.len = sizeof(uid); + r = chash_get(msg_hash, &key, &value); + if (r == 0) { + mailmessage * msg; + + msg = value.data; + if (imap_envelope != NULL) { + struct mailimf_fields * fields; + + r = imap_env_to_fields(imap_envelope, + references, ref_size, &fields); + if (r == MAIL_NO_ERROR) { + msg->msg_fields = fields; + } + } + if (att_dyn != NULL) { + struct mail_flags * flags; + + r = imap_flags_to_flags(att_dyn, &flags); + if (r == MAIL_NO_ERROR) { + msg->msg_flags = flags; + } + } + } + } + } + } + + chash_free(msg_hash); + + return MAIL_NO_ERROR; + + free_hash: + chash_free(msg_hash); + err: + return res; +} + + +int mailimf_date_time_to_imap_date(struct mailimf_date_time * date, + struct mailimap_date ** result) +{ + struct mailimap_date * imap_date; + + imap_date = mailimap_date_new(date->dt_day, date->dt_month, date->dt_year); + if (imap_date == NULL) + return MAIL_ERROR_MEMORY; + + * result = imap_date; + + return MAIL_NO_ERROR; +} + + +#if 0 +int mail_search_to_imap_search(struct mail_search_key * key, + struct mailimap_search_key ** result) +{ + struct mailimap_search_key * imap_key; + + char * bcc; + struct mailimap_date * before; + char * body; + char * cc; + char * from; + struct mailimap_date * on; + struct mailimap_date * since; + char * subject; + char * text; + char * to; + char * header_name; + char * header_value; + size_t larger; + struct mailimap_search_key * not; + struct mailimap_search_key * or1; + struct mailimap_search_key * or2; + size_t smaller; + clist * multiple; + int type; + clistiter * cur; + int r; + int res; + + bcc = NULL; + before = NULL; + body = NULL; + cc = NULL; + from = NULL; + on = NULL; + since = NULL; + subject = NULL; + text = NULL; + to = NULL; + header_name = NULL; + header_value = NULL; + not = NULL; + or1 = NULL; + or2 = NULL; + multiple = NULL; + larger = 0; + smaller = 0; + + switch (key->sk_type) { + case MAIL_SEARCH_KEY_ALL: + type = MAILIMAP_SEARCH_KEY_ALL; + break; + + case MAIL_SEARCH_KEY_ANSWERED: + type = MAILIMAP_SEARCH_KEY_ANSWERED; + break; + + case MAIL_SEARCH_KEY_BCC: + type = MAILIMAP_SEARCH_KEY_BCC; + bcc = strdup(key->sk_bcc); + if (bcc == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + break; + + case MAIL_SEARCH_KEY_BEFORE: + type = MAILIMAP_SEARCH_KEY_BEFORE; + r = mailimf_date_time_to_imap_date(key->sk_before, &before); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + break; + + case MAIL_SEARCH_KEY_BODY: + type = MAILIMAP_SEARCH_KEY_BODY; + body = strdup(key->sk_body); + if (body == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + break; + + case MAIL_SEARCH_KEY_CC: + type = MAILIMAP_SEARCH_KEY_CC; + cc = strdup(key->sk_cc); + if (cc == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + break; + + case MAIL_SEARCH_KEY_DELETED: + type = MAILIMAP_SEARCH_KEY_DELETED; + break; + + case MAIL_SEARCH_KEY_FLAGGED: + type = MAILIMAP_SEARCH_KEY_FLAGGED; + break; + + case MAIL_SEARCH_KEY_FROM: + type = MAILIMAP_SEARCH_KEY_FROM; + from = strdup(key->sk_from); + if (from == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + break; + + case MAIL_SEARCH_KEY_NEW: + type = MAILIMAP_SEARCH_KEY_NEW; + break; + + case MAIL_SEARCH_KEY_OLD: + type = MAILIMAP_SEARCH_KEY_OLD; + break; + + case MAIL_SEARCH_KEY_ON: + type = MAILIMAP_SEARCH_KEY_ON; + r = mailimf_date_time_to_imap_date(key->sk_on, &on); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + break; + + case MAIL_SEARCH_KEY_RECENT: + type = MAILIMAP_SEARCH_KEY_RECENT; + break; + + case MAIL_SEARCH_KEY_SEEN: + type = MAILIMAP_SEARCH_KEY_SEEN; + break; + + case MAIL_SEARCH_KEY_SINCE: + type = MAILIMAP_SEARCH_KEY_SINCE; + r = mailimf_date_time_to_imap_date(key->sk_since, &since); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + break; + + case MAIL_SEARCH_KEY_SUBJECT: + type = MAILIMAP_SEARCH_KEY_SUBJECT; + subject = strdup(key->sk_subject); + if (subject == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + break; + + case MAIL_SEARCH_KEY_TEXT: + type = MAILIMAP_SEARCH_KEY_TEXT; + text = strdup(key->sk_text); + if (text == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + break; + + case MAIL_SEARCH_KEY_TO: + type = MAILIMAP_SEARCH_KEY_TO; + to = strdup(key->sk_to); + if (to == NULL) { + return MAIL_ERROR_MEMORY; + goto err; + } + break; + + case MAIL_SEARCH_KEY_UNANSWERED: + type = MAILIMAP_SEARCH_KEY_UNANSWERED; + break; + + case MAIL_SEARCH_KEY_UNDELETED: + type = MAILIMAP_SEARCH_KEY_UNFLAGGED; + break; + + case MAIL_SEARCH_KEY_UNFLAGGED: + type = MAILIMAP_SEARCH_KEY_UNANSWERED; + break; + + case MAIL_SEARCH_KEY_UNSEEN: + type = MAILIMAP_SEARCH_KEY_UNSEEN; + break; + + case MAIL_SEARCH_KEY_HEADER: + type = MAILIMAP_SEARCH_KEY_HEADER; + header_name = strdup(key->sk_header_name); + if (header_name == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + header_value = strdup(key->sk_header_value); + if (header_value == NULL) { + free(header_name); + res = MAIL_ERROR_MEMORY; + goto err; + } + break; + + case MAIL_SEARCH_KEY_LARGER: + type = MAILIMAP_SEARCH_KEY_LARGER; + larger = key->sk_larger; + break; + + case MAIL_SEARCH_KEY_NOT: + type = MAILIMAP_SEARCH_KEY_NOT; + r = mail_search_to_imap_search(key->sk_not, ¬); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + break; + + case MAIL_SEARCH_KEY_OR: + type = MAILIMAP_SEARCH_KEY_OR; + r = mail_search_to_imap_search(key->sk_or1, &or1); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + r = mail_search_to_imap_search(key->sk_or2, &or2); + if (r != MAIL_NO_ERROR) { + mailimap_search_key_free(or1); + res = r; + goto err; + } + break; + + case MAIL_SEARCH_KEY_SMALLER: + type = MAILIMAP_SEARCH_KEY_SMALLER; + smaller = key->sk_smaller; + break; + + case MAIL_SEARCH_KEY_MULTIPLE: + multiple = clist_new(); + if (multiple == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + type = MAILIMAP_SEARCH_KEY_MULTIPLE; + for(cur = clist_begin(key->sk_multiple) ; cur != NULL ; + cur = clist_next(cur)) { + struct mail_search_key * key_elt; + struct mailimap_search_key * imap_key_elt; + + key_elt = clist_content(cur); + r = mail_search_to_imap_search(key_elt, &imap_key_elt); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(multiple, imap_key_elt); + if (r != 0) { + mailimap_search_key_free(imap_key_elt); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + break; + + free_list: + clist_foreach(multiple, (clist_func) mailimap_search_key_free, NULL); + clist_free(multiple); + goto err; + + default: + return MAIL_ERROR_INVAL; + } + + imap_key = mailimap_search_key_new(type, bcc, before, body, cc, from, + NULL, on, since, subject, text, + to, NULL, header_name, + header_value, larger, not, or1, or2, + NULL, NULL, NULL, smaller, NULL, + NULL, multiple); + if (imap_key == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + * result = imap_key; + + return MAIL_NO_ERROR; + + free: + if (bcc != NULL) + free(bcc); + if (before != NULL) + mailimap_date_free(before); + if (body != NULL) + free(body); + if (cc != NULL) + free(cc); + if (from != NULL) + free(from); + if (on != NULL) + mailimap_date_free(on); + if (since != NULL) + mailimap_date_free(since); + if (subject != NULL) + free(subject); + if (text != NULL) + free(text); + if (to != NULL) + free(to); + if (header_name != NULL) + free(header_name); + if (header_value != NULL) + free(header_value); + if (not != NULL) + mailimap_search_key_free(not); + if (or1 != NULL) + mailimap_search_key_free(or1); + if (or2 != NULL) + mailimap_search_key_free(or2); + clist_foreach(multiple, (clist_func) mailimap_search_key_free, NULL); + clist_free(multiple); + err: + return res; +} +#endif + + +int imap_msg_list_to_imap_set(clist * msg_list, + struct mailimap_set ** result) +{ + struct mailimap_set * imap_set; + clistiter * cur; + int previous_valid; + uint32_t first_seq; + uint32_t previous; + int r; + int res; + + imap_set = mailimap_set_new_empty(); + if (imap_set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + cur = clist_begin(msg_list); + previous_valid = FALSE; + first_seq = 0; + previous = 0; + while (1) { + uint32_t * pindex; + + if ((cur == NULL) && (previous_valid)) { + if (first_seq == previous) { + r = mailimap_set_add_single(imap_set, first_seq); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + } + else { + r = mailimap_set_add_interval(imap_set, first_seq, previous); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + } + break; + } + + pindex = clist_content(cur); + if (pindex == NULL) { + // Make clang static analyzer happy. + break; + } + + if (!previous_valid) { + first_seq = * pindex; + previous_valid = TRUE; + previous = * pindex; + cur = clist_next(cur); + } + else { + if (* pindex != previous + 1) { + if (first_seq == previous) { + r = mailimap_set_add_single(imap_set, first_seq); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + } + else { + r = mailimap_set_add_interval(imap_set, first_seq, previous); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + } + previous_valid = FALSE; + } + else { + previous = * pindex; + cur = clist_next(cur); + } + } + } + + * result = imap_set; + + return MAIL_NO_ERROR; + + free: + mailimap_set_free(imap_set); + err: + return res; +} + + +static int +imap_uid_list_to_env_list(mailsession * session, mailmessage_driver * driver, + clist * fetch_result, + struct mailmessage_list ** result) +{ + clistiter * cur; + struct mailmessage_list * env_list; + int r; + int res; + carray * tab; + unsigned int i; + mailmessage * msg; + + tab = carray_new(128); + if (tab == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(cur = clist_begin(fetch_result) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_msg_att * msg_att; + clistiter * item_cur; + uint32_t uid; + size_t size; + + msg_att = clist_content(cur); + + uid = 0; + size = 0; + for(item_cur = clist_begin(msg_att->att_list) ; item_cur != NULL ; + item_cur = clist_next(item_cur)) { + struct mailimap_msg_att_item * item; + + item = clist_content(item_cur); + + switch (item->att_type) { + case MAILIMAP_MSG_ATT_ITEM_STATIC: + switch (item->att_data.att_static->att_type) { + case MAILIMAP_MSG_ATT_UID: + uid = item->att_data.att_static->att_data.att_uid; + break; + + case MAILIMAP_MSG_ATT_RFC822_SIZE: + size = item->att_data.att_static->att_data.att_rfc822_size; + break; + } + break; + } + } + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = mailmessage_init(msg, session, driver, uid, size); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_msg; + } + + r = carray_add(tab, msg, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_msg; + } + } + + env_list = mailmessage_list_new(tab); + if (env_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = env_list; + + return MAIL_NO_ERROR; + + free_msg: + mailmessage_free(msg); + free_list: + for(i = 0 ; i < carray_count(tab) ; i++) + mailmessage_free(carray_get(tab, i)); + err: + return res; +} + + +/* + MAILIMAP_FLAG_FETCH_RECENT, + MAILIMAP_FLAG_FETCH_OTHER + + MAILIMAP_FLAG_ANSWERED, + MAILIMAP_FLAG_FLAGGED, + MAILIMAP_FLAG_DELETED, + MAILIMAP_FLAG_SEEN, + MAILIMAP_FLAG_DRAFT, + MAILIMAP_FLAG_KEYWORD, + MAILIMAP_FLAG_EXTENSION +*/ + +int imap_flags_to_flags(struct mailimap_msg_att_dynamic * att_dyn, + struct mail_flags ** result) +{ + struct mail_flags * flags; + clist * flag_list; + clistiter * cur; + + flags = mail_flags_new_empty(); + if (flags == NULL) + goto err; + flags->fl_flags = 0; + + flag_list = att_dyn->att_list; + if (flag_list != NULL) { + for(cur = clist_begin(flag_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_flag_fetch * flag_fetch; + + flag_fetch = clist_content(cur); + if (flag_fetch->fl_type == MAILIMAP_FLAG_FETCH_RECENT) + flags->fl_flags |= MAIL_FLAG_NEW; + else { + char * keyword; + int r; + + switch (flag_fetch->fl_flag->fl_type) { + case MAILIMAP_FLAG_ANSWERED: + flags->fl_flags |= MAIL_FLAG_ANSWERED; + break; + case MAILIMAP_FLAG_FLAGGED: + flags->fl_flags |= MAIL_FLAG_FLAGGED; + break; + case MAILIMAP_FLAG_DELETED: + flags->fl_flags |= MAIL_FLAG_DELETED; + break; + case MAILIMAP_FLAG_SEEN: + flags->fl_flags |= MAIL_FLAG_SEEN; + break; + case MAILIMAP_FLAG_DRAFT: + keyword = strdup("Draft"); + if (keyword == NULL) + goto free; + r = clist_append(flags->fl_extension, keyword); + if (r < 0) { + free(keyword); + goto free; + } + break; + case MAILIMAP_FLAG_KEYWORD: + if (strcasecmp(flag_fetch->fl_flag->fl_data.fl_keyword, + "$Forwarded") == 0) { + flags->fl_flags |= MAIL_FLAG_FORWARDED; + } + else { + keyword = strdup(flag_fetch->fl_flag->fl_data.fl_keyword); + if (keyword == NULL) + goto free; + r = clist_append(flags->fl_extension, keyword); + if (r < 0) { + free(keyword); + goto free; + } + } + break; + case MAILIMAP_FLAG_EXTENSION: + /* do nothing */ + break; + } + } + } + /* + MAIL_FLAG_NEW was set for \Recent messages. + Correct this flag for \Seen messages by unsetting it. + */ + if ((flags->fl_flags & MAIL_FLAG_SEEN) && (flags->fl_flags & MAIL_FLAG_NEW)) { + flags->fl_flags &= ~MAIL_FLAG_NEW; + } + } + + * result = flags; + + return MAIL_NO_ERROR; + + free: + mail_flags_free(flags); + err: + return MAIL_ERROR_MEMORY; +} + +int imap_flags_to_imap_flags(struct mail_flags * flags, + struct mailimap_flag_list ** result) +{ + struct mailimap_flag * flag; + struct mailimap_flag_list * flag_list; + int res; + clistiter * cur; + int r; + + flag_list = mailimap_flag_list_new_empty(); + if (flag_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if ((flags->fl_flags & MAIL_FLAG_DELETED) != 0) { + flag = mailimap_flag_new_deleted(); + if (flag == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + r = mailimap_flag_list_add(flag_list, flag); + if (r != MAILIMAP_NO_ERROR) { + mailimap_flag_free(flag); + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + } + + if ((flags->fl_flags & MAIL_FLAG_FLAGGED) != 0) { + flag = mailimap_flag_new_flagged(); + if (flag == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + r = mailimap_flag_list_add(flag_list, flag); + if (r != MAILIMAP_NO_ERROR) { + mailimap_flag_free(flag); + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + } + + if ((flags->fl_flags & MAIL_FLAG_SEEN) != 0) { + flag = mailimap_flag_new_seen(); + if (flag == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + r = mailimap_flag_list_add(flag_list, flag); + if (r != MAILIMAP_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + } + + if ((flags->fl_flags & MAIL_FLAG_ANSWERED) != 0) { + flag = mailimap_flag_new_answered(); + if (flag == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + r = mailimap_flag_list_add(flag_list, flag); + if (r != MAILIMAP_NO_ERROR) { + mailimap_flag_free(flag); + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + } + + if ((flags->fl_flags & MAIL_FLAG_FORWARDED) != 0) { + char * flag_str; + + flag_str = strdup("$Forwarded"); + if (flag_str == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + flag = mailimap_flag_new_flag_keyword(flag_str); + if (flag == NULL) { + free(flag_str); + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + r = mailimap_flag_list_add(flag_list, flag); + if (r != MAILIMAP_NO_ERROR) { + mailimap_flag_free(flag); + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + } + + for(cur = clist_begin(flags->fl_extension) ; cur != NULL ; + cur = clist_next(cur)) { + char * flag_str; + + flag_str = clist_content(cur); + + if (strcasecmp(flag_str, "Draft") == 0) { + flag = mailimap_flag_new_draft(); + if (flag == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + r = mailimap_flag_list_add(flag_list, flag); + if (r != MAILIMAP_NO_ERROR) { + mailimap_flag_free(flag); + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + } + else { + flag_str = strdup(flag_str); + if (flag_str == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + flag = mailimap_flag_new_flag_keyword(flag_str); + if (flag == NULL) { + free(flag_str); + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + r = mailimap_flag_list_add(flag_list, flag); + if (r != MAILIMAP_NO_ERROR) { + mailimap_flag_free(flag); + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + } + } + + * result = flag_list; + + return MAIL_NO_ERROR; + + free_flag_list: + mailimap_flag_list_free(flag_list); + err: + return res; +} + +static int flags_to_imap_flags(struct mail_flags * flags, + struct mailimap_store_att_flags ** result) +{ + struct mailimap_flag_list * flag_list; + struct mailimap_store_att_flags * att_flags; + int res; + int r; + + r = imap_flags_to_imap_flags(flags, + &flag_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + att_flags = mailimap_store_att_flags_new_set_flags_silent(flag_list); + if (att_flags == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + + * result = att_flags; + + return MAIL_NO_ERROR; + + free_flag_list: + mailimap_flag_list_free(flag_list); + err: + return res; +} + + +static int +imap_fetch_result_to_flags(clist * fetch_result, uint32_t indx, + struct mail_flags ** result) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(fetch_result) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_msg_att * msg_att; + clistiter * item_cur; + uint32_t uid; + struct mailimap_msg_att_dynamic * att_dyn; + + msg_att = clist_content(cur); + + uid = 0; + att_dyn = NULL; + + for(item_cur = clist_begin(msg_att->att_list) ; item_cur != NULL ; + item_cur = clist_next(item_cur)) { + struct mailimap_msg_att_item * item; + + item = clist_content(item_cur); + + if (item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { + switch (item->att_data.att_static->att_type) { + case MAILIMAP_MSG_ATT_UID: + uid = item->att_data.att_static->att_data.att_uid; + break; + } + } + else if (item->att_type == MAILIMAP_MSG_ATT_ITEM_DYNAMIC) { + if (att_dyn == NULL) { + att_dyn = item->att_data.att_dyn; + } + } + } + + if (uid != 0) { + if (uid == indx) { + struct mail_flags * flags; + + if (att_dyn != NULL) { + r = imap_flags_to_flags(att_dyn, &flags); + + if (r == MAIL_NO_ERROR) { + * result = flags; + return MAIL_NO_ERROR; + } + } + } + } + } + + return MAIL_ERROR_MSG_NOT_FOUND; +} + + +int imap_fetch_flags(mailimap * imap, + uint32_t indx, struct mail_flags ** result) +{ + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + struct mailimap_set * set; + int r; + int res; + clist * fetch_result; + struct mail_flags * flags; + + fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fetch_att = mailimap_fetch_att_new_uid(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + fetch_att = mailimap_fetch_att_new_flags(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + set = mailimap_set_new_single(indx); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_uid_fetch(imap, set, fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + flags = NULL; + r = imap_fetch_result_to_flags(fetch_result, indx, &flags); + mailimap_fetch_list_free(fetch_result); + + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = flags; + + return MAIL_NO_ERROR; + + free_fetch_type: + mailimap_fetch_type_free(fetch_type); + err: + return res; +} + +int imap_store_flags(mailimap * imap, uint32_t first, uint32_t last, + struct mail_flags * flags) +{ + struct mailimap_store_att_flags * att_flags; + struct mailimap_set * set; + int r; + int res; + + set = mailimap_set_new_interval(first, last); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = flags_to_imap_flags(flags, &att_flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_set; + } + + r = mailimap_uid_store(imap, set, att_flags); + if (r != MAILIMAP_NO_ERROR) { + res = imap_error_to_mail_error(r); + goto free_flag; + } + + mailimap_store_att_flags_free(att_flags); + mailimap_set_free(set); + + return MAIL_NO_ERROR; + + free_flag: + mailimap_store_att_flags_free(att_flags); + free_set: + mailimap_set_free(set); + err: + return res; +} + + + + +int imap_get_messages_list(mailimap * imap, + mailsession * session, mailmessage_driver * driver, + uint32_t first_index, + struct mailmessage_list ** result) +{ + struct mailmessage_list * env_list; + int r; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + struct mailimap_set * set; + clist * fetch_result; + int res; + + set = mailimap_set_new_interval(first_index, 0); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_att = mailimap_fetch_att_new_uid(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + fetch_att = mailimap_fetch_att_new_rfc822_size(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_uid_fetch(imap, set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + if (r != MAILIMAP_NO_ERROR) { + res = imap_error_to_mail_error(r); + goto err; + } + + env_list = NULL; + r = imap_uid_list_to_env_list(session, driver, fetch_result, &env_list); + mailimap_fetch_list_free(fetch_result); + + * result = env_list; + + return MAIL_NO_ERROR; + + free_fetch_type: + mailimap_fetch_type_free(fetch_type); + free_set: + mailimap_set_free(set); + err: + return res; +} + +static void generate_key_from_message(char * key, size_t size, + mailmessage * msg_info, + int type) +{ + switch (type) { + case MAILIMAP_MSG_ATT_RFC822: + snprintf(key, size, "%s-rfc822", msg_info->msg_uid); + break; + case MAILIMAP_MSG_ATT_RFC822_HEADER: + snprintf(key, size, "%s-rfc822-header", msg_info->msg_uid); + break; + case MAILIMAP_MSG_ATT_RFC822_TEXT: + snprintf(key, size, "%s-rfc822-text", msg_info->msg_uid); + break; + case MAILIMAP_MSG_ATT_ENVELOPE: + snprintf(key, size, "%s-envelope", msg_info->msg_uid); + break; + } +} + +int +imapdriver_get_cached_envelope(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, mailmessage * msg, + struct mailimf_fields ** result) +{ + int r; + struct mailimf_fields * fields; + int res; + char keyname[PATH_MAX]; + + generate_key_from_message(keyname, PATH_MAX, + msg, MAILIMAP_MSG_ATT_ENVELOPE); + + r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = fields; + + return MAIL_NO_ERROR; + +err: + return res; +} + +int +imapdriver_write_cached_envelope(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, mailmessage * msg, + struct mailimf_fields * fields) +{ + char keyname[PATH_MAX]; + int r; + int res; + + generate_key_from_message(keyname, PATH_MAX, + msg, MAILIMAP_MSG_ATT_ENVELOPE); + + r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + +err: + return res; +} diff --git a/Sources/libetpan/driver/implementation/imap/imapdriver_tools.h b/Sources/libetpan/driver/implementation/imap/imapdriver_tools.h new file mode 100644 index 00000000..36dc4861 --- /dev/null +++ b/Sources/libetpan/driver/implementation/imap/imapdriver_tools.h @@ -0,0 +1,88 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver_tools.h,v 1.9 2007/08/08 21:33:30 hoa Exp $ + */ + +#ifndef IMAPDRIVER_TOOLS_H + +#define IMAPDRIVER_TOOLS_H + +#include "mailimap.h" +#include "mailmime.h" +#include "imapdriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int imap_list_to_list(clist * imap_list, struct mail_list ** result); + +int +imap_section_to_imap_section(struct mailmime_section * section, int type, + struct mailimap_section ** result); + +int imap_get_msg_att_info(struct mailimap_msg_att * msg_att, + uint32_t * puid, + struct mailimap_envelope ** pimap_envelope, + char ** preferences, + size_t * pref_size, + struct mailimap_msg_att_dynamic ** patt_dyn, + struct mailimap_body ** pimap_body); + +int imap_add_envelope_fetch_att(struct mailimap_fetch_type * fetch_type); + +int imap_env_to_fields(struct mailimap_envelope * env, + char * ref_str, size_t ref_size, + struct mailimf_fields ** result); + +int +imap_fetch_result_to_envelop_list(clist * fetch_result, + struct mailmessage_list * env_list); + +int imap_body_to_body(struct mailimap_body * imap_body, + struct mailmime ** result); + +int imap_msg_list_to_imap_set(clist * msg_list, + struct mailimap_set ** result); + +int imap_flags_to_imap_flags(struct mail_flags * flags, + struct mailimap_flag_list ** result); + +int imap_flags_to_flags(struct mailimap_msg_att_dynamic * att_dyn, + struct mail_flags ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/imap/imapdriver_tools_private.h b/Sources/libetpan/driver/implementation/imap/imapdriver_tools_private.h new file mode 100644 index 00000000..0de33cff --- /dev/null +++ b/Sources/libetpan/driver/implementation/imap/imapdriver_tools_private.h @@ -0,0 +1,62 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef IMAPDRIVER_TOOLS_PRIVATE_H + +#define IMAPDRIVER_TOOLS_PRIVATE_H + +#include "mail_cache_db.h" + +int +imapdriver_get_cached_envelope(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, mailmessage * msg, + struct mailimf_fields ** result); + +int +imapdriver_write_cached_envelope(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, mailmessage * msg, + struct mailimf_fields * fields); + +int imap_error_to_mail_error(int error); + +int imap_store_flags(mailimap * imap, uint32_t first, uint32_t last, + struct mail_flags * flags); + +int imap_fetch_flags(mailimap * imap, + uint32_t indx, struct mail_flags ** result); + +int imap_get_messages_list(mailimap * imap, + mailsession * session, mailmessage_driver * driver, + uint32_t first_index, + struct mailmessage_list ** result); + +#endif diff --git a/Sources/libetpan/driver/implementation/imap/imapdriver_types.h b/Sources/libetpan/driver/implementation/imap/imapdriver_types.h new file mode 100644 index 00000000..7f911690 --- /dev/null +++ b/Sources/libetpan/driver/implementation/imap/imapdriver_types.h @@ -0,0 +1,165 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver_types.h,v 1.27 2007/06/30 12:58:21 hoa Exp $ + */ + +#ifndef IMAPDRIVER_TYPES_H + +#define IMAPDRIVER_TYPES_H + +#include + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* IMAP driver for session */ + +struct imap_session_state_data { + mailimap * imap_session; + char * imap_mailbox; + struct mail_flags_store * imap_flags_store; + void (* imap_ssl_callback)(struct mailstream_ssl_context * ssl_context, void * data); + void * imap_ssl_cb_data; +}; + +enum { + IMAP_SECTION_MESSAGE, + IMAP_SECTION_HEADER, + IMAP_SECTION_MIME, + IMAP_SECTION_BODY +}; + +/* cached IMAP driver for session */ + +enum { + IMAPDRIVER_CACHED_SET_SSL_CALLBACK = 1, + IMAPDRIVER_CACHED_SET_SSL_CALLBACK_DATA = 2, + /* cache */ + IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY = 1001 +}; + +struct imap_cached_session_state_data { + mailsession * imap_ancestor; + char * imap_quoted_mb; + char imap_cache_directory[PATH_MAX]; + carray * imap_uid_list; + uint32_t imap_uidvalidity; +}; + + +/* IMAP storage */ + +/* + imap_mailstorage is the state data specific to the IMAP4rev1 storage. + + - servername this is the name of the IMAP4rev1 server + + - port is the port to connect to, on the server. + you give 0 to use the default port. + + - command, if non-NULL the command used to connect to the + server instead of allowing normal TCP connections to be used. + + - connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS, + CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS or + CONNECTION_TYPE_COMMAND. + + - auth_type is the authenticate mechanism to use. + The value can be IMAP_AUTH_TYPE_PLAIN. + Other values are not yet implemented. + + - login is the login of the IMAP4rev1 account. + + - password is the password of the IMAP4rev1 account. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache +*/ + +struct imap_mailstorage { + char * imap_servername; + uint16_t imap_port; + char * imap_command; + int imap_connection_type; + + int imap_auth_type; + char * imap_login; /* deprecated */ + char * imap_password; /* deprecated */ + + int imap_cached; + char * imap_cache_directory; + + struct { + int sasl_enabled; + char * sasl_auth_type; + char * sasl_server_fqdn; + char * sasl_local_ip_port; + char * sasl_remote_ip_port; + char * sasl_login; + char * sasl_auth_name; + char * sasl_password; + char * sasl_realm; + } imap_sasl; + + char * imap_local_address; + uint16_t imap_local_port; +}; + +/* this is the type of IMAP4rev1 authentication */ + +enum { + IMAP_AUTH_TYPE_PLAIN, /* plain text authentication */ + IMAP_AUTH_TYPE_SASL_ANONYMOUS, /* SASL anonymous */ + IMAP_AUTH_TYPE_SASL_CRAM_MD5, /* SASL CRAM MD5 */ + IMAP_AUTH_TYPE_SASL_KERBEROS_V4, /* SASL KERBEROS V4 */ + IMAP_AUTH_TYPE_SASL_PLAIN, /* SASL plain */ + IMAP_AUTH_TYPE_SASL_SCRAM_MD5, /* SASL SCRAM MD5 */ + IMAP_AUTH_TYPE_SASL_GSSAPI, /* SASL GSSAPI */ + IMAP_AUTH_TYPE_SASL_DIGEST_MD5 /* SASL digest MD5 */ +}; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/imap/imapstorage.c b/Sources/libetpan/driver/implementation/imap/imapstorage.c new file mode 100644 index 00000000..385ee37c --- /dev/null +++ b/Sources/libetpan/driver/implementation/imap/imapstorage.c @@ -0,0 +1,477 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapstorage.c,v 1.19 2008/02/17 13:13:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "imapstorage.h" + +#include +#include + +#include "mail.h" +#include "imapdriver.h" +#include "imapdriver_cached.h" +#include "mailstorage_tools.h" +#include "maildriver.h" + +/* imap storage */ + +#define IMAP_DEFAULT_PORT 143 +#define IMAPS_DEFAULT_PORT 993 + +static int imap_mailstorage_connect(struct mailstorage * storage); +static int +imap_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result); +static void imap_mailstorage_uninitialize(struct mailstorage * storage); + +static mailstorage_driver imap_mailstorage_driver = { + /* sto_name */ "imap", + /* sto_connect */ imap_mailstorage_connect, + /* sto_get_folder_session */ imap_mailstorage_get_folder_session, + /* sto_uninitialize */ imap_mailstorage_uninitialize +}; + +LIBETPAN_EXPORT +int imap_mailstorage_init(struct mailstorage * storage, + const char * imap_servername, uint16_t imap_port, + const char * imap_command, + int imap_connection_type, int imap_auth_type, + const char * imap_login, const char * imap_password, + int imap_cached, const char * imap_cache_directory) +{ + return imap_mailstorage_init_sasl(storage, + imap_servername, imap_port, + imap_command, + imap_connection_type, + NULL, + NULL, + NULL, NULL, + imap_login, imap_login, + imap_password, NULL, + imap_cached, imap_cache_directory); +} + +LIBETPAN_EXPORT +int imap_mailstorage_init_sasl(struct mailstorage * storage, + const char * imap_servername, uint16_t imap_port, + const char * imap_command, + int imap_connection_type, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm, + int imap_cached, const char * imap_cache_directory) +{ + return imap_mailstorage_init_sasl_with_local_address(storage, + imap_servername, imap_port, + NULL, 0, + imap_command, + imap_connection_type, + auth_type, + server_fqdn, + local_ip_port, + remote_ip_port, + login, auth_name, + password, realm, + imap_cached, imap_cache_directory); +} + +LIBETPAN_EXPORT +int imap_mailstorage_init_sasl_with_local_address(struct mailstorage * storage, + const char * imap_servername, uint16_t imap_port, + const char * imap_local_address, uint16_t imap_local_port, + const char * imap_command, + int imap_connection_type, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm, + int imap_cached, const char * imap_cache_directory) +{ + struct imap_mailstorage * imap_storage; + + imap_storage = malloc(sizeof(* imap_storage)); + if (imap_storage == NULL) + goto err; + + if (imap_servername != NULL) { + imap_storage->imap_servername = strdup(imap_servername); + if (imap_storage->imap_servername == NULL) + goto free; + } + else { + imap_storage->imap_servername = NULL; + } + + if (imap_local_address != NULL) { + imap_storage->imap_local_address = strdup(imap_local_address); + if (imap_storage->imap_local_address == NULL) + goto free_servername; + } + else { + imap_storage->imap_local_address = NULL; + } + + imap_storage->imap_local_port = imap_local_port; + + imap_storage->imap_connection_type = imap_connection_type; + + if (imap_port == 0) { + switch (imap_connection_type) { + case CONNECTION_TYPE_PLAIN: + case CONNECTION_TYPE_TRY_STARTTLS: + case CONNECTION_TYPE_STARTTLS: + case CONNECTION_TYPE_COMMAND: + case CONNECTION_TYPE_COMMAND_TRY_STARTTLS: + case CONNECTION_TYPE_COMMAND_STARTTLS: + imap_port = IMAP_DEFAULT_PORT; + break; + + case CONNECTION_TYPE_TLS: + case CONNECTION_TYPE_COMMAND_TLS: + imap_port = IMAPS_DEFAULT_PORT; + break; + + default: + imap_port = IMAP_DEFAULT_PORT; + break; + } + } + + imap_storage->imap_port = imap_port; + + if (imap_command != NULL) { + imap_storage->imap_command = strdup(imap_command); + if (imap_storage->imap_command == NULL) + goto free_local_address; + } + else + imap_storage->imap_command = NULL; + + imap_storage->imap_auth_type = IMAP_AUTH_TYPE_PLAIN; + + imap_storage->imap_sasl.sasl_enabled = (auth_type != NULL); + + if (auth_type != NULL) { + imap_storage->imap_sasl.sasl_auth_type = strdup(auth_type); + if (imap_storage->imap_sasl.sasl_auth_type == NULL) + goto free_command; + } + else + imap_storage->imap_sasl.sasl_auth_type = NULL; + + if (server_fqdn != NULL) { + imap_storage->imap_sasl.sasl_server_fqdn = strdup(server_fqdn); + if (imap_storage->imap_sasl.sasl_server_fqdn == NULL) + goto free_auth_type; + } + else + imap_storage->imap_sasl.sasl_server_fqdn = NULL; + + if (local_ip_port != NULL) { + imap_storage->imap_sasl.sasl_local_ip_port = strdup(local_ip_port); + if (imap_storage->imap_sasl.sasl_local_ip_port == NULL) + goto free_server_fqdn; + } + else + imap_storage->imap_sasl.sasl_local_ip_port = NULL; + + if (remote_ip_port != NULL) { + imap_storage->imap_sasl.sasl_remote_ip_port = strdup(remote_ip_port); + if (imap_storage->imap_sasl.sasl_remote_ip_port == NULL) + goto free_local_ip_port; + } + else + imap_storage->imap_sasl.sasl_remote_ip_port = NULL; + + if (login != NULL) { + imap_storage->imap_sasl.sasl_login = strdup(login); + if (imap_storage->imap_sasl.sasl_login == NULL) + goto free_remote_ip_port; + } + else + imap_storage->imap_sasl.sasl_login = NULL; + + if (auth_name != NULL) { + imap_storage->imap_sasl.sasl_auth_name = strdup(auth_name); + if (imap_storage->imap_sasl.sasl_auth_name == NULL) + goto free_login; + } + else + imap_storage->imap_sasl.sasl_auth_name = NULL; + + if (password != NULL) { + imap_storage->imap_sasl.sasl_password = strdup(password); + if (imap_storage->imap_sasl.sasl_password == NULL) + goto free_auth_name; + } + else + imap_storage->imap_sasl.sasl_password = NULL; + + if (realm != NULL) { + imap_storage->imap_sasl.sasl_realm = strdup(realm); + if (imap_storage->imap_sasl.sasl_realm == NULL) + goto free_password; + } + else + imap_storage->imap_sasl.sasl_realm = NULL; + + imap_storage->imap_cached = imap_cached; + + if (imap_cached && (imap_cache_directory != NULL)) { + imap_storage->imap_cache_directory = strdup(imap_cache_directory); + if (imap_storage->imap_cache_directory == NULL) + goto free_realm; + } + else { + imap_storage->imap_cached = FALSE; + imap_storage->imap_cache_directory = NULL; + } + + imap_storage->imap_auth_type = imap_storage->imap_auth_type; + if (imap_storage->imap_sasl.sasl_login != NULL) { + imap_storage->imap_login = strdup(imap_storage->imap_sasl.sasl_login); + if (imap_storage->imap_login == NULL) + goto free_cache_directory; + } + else { + imap_storage->imap_login = NULL; + } + + if (imap_storage->imap_sasl.sasl_password != NULL) { + imap_storage->imap_password = strdup(imap_storage->imap_sasl.sasl_password); + if (imap_storage->imap_password == NULL) + goto free_copy_login; + } + else { + imap_storage->imap_password = NULL; + } + + storage->sto_data = imap_storage; + storage->sto_driver = &imap_mailstorage_driver; + + return MAIL_NO_ERROR; + + free_copy_login: + free(imap_storage->imap_login); + free_cache_directory: + free(imap_storage->imap_cache_directory); + free_realm: + free(imap_storage->imap_sasl.sasl_realm); + free_password: + free(imap_storage->imap_sasl.sasl_password); + free_auth_name: + free(imap_storage->imap_sasl.sasl_auth_name); + free_login: + free(imap_storage->imap_sasl.sasl_login); + free_remote_ip_port: + free(imap_storage->imap_sasl.sasl_remote_ip_port); + free_local_ip_port: + free(imap_storage->imap_sasl.sasl_local_ip_port); + free_server_fqdn: + free(imap_storage->imap_sasl.sasl_server_fqdn); + free_auth_type: + free(imap_storage->imap_sasl.sasl_auth_type); + free_command: + free(imap_storage->imap_command); + free_local_address: + free(imap_storage->imap_local_address); + free_servername: + free(imap_storage->imap_servername); + free: + free(imap_storage); + err: + return MAIL_ERROR_MEMORY; +} + +static void imap_mailstorage_uninitialize(struct mailstorage * storage) +{ + struct imap_mailstorage * imap_storage; + + imap_storage = storage->sto_data; + + free(imap_storage->imap_password); + free(imap_storage->imap_login); + + free(imap_storage->imap_cache_directory); + + free(imap_storage->imap_sasl.sasl_realm); + free(imap_storage->imap_sasl.sasl_password); + free(imap_storage->imap_sasl.sasl_auth_name); + free(imap_storage->imap_sasl.sasl_login); + free(imap_storage->imap_sasl.sasl_remote_ip_port); + free(imap_storage->imap_sasl.sasl_local_ip_port); + free(imap_storage->imap_sasl.sasl_server_fqdn); + free(imap_storage->imap_sasl.sasl_auth_type); + + free(imap_storage->imap_command); + free(imap_storage->imap_local_address); + free(imap_storage->imap_servername); + free(imap_storage); + + storage->sto_data = NULL; +} + +static int imap_connect(struct mailstorage * storage, + mailsession ** result) +{ + struct imap_mailstorage * imap_storage; + mailsession_driver * driver; + int r; + int res; + mailsession * session; + + imap_storage = storage->sto_data; + + if (imap_storage->imap_cached) + driver = imap_cached_session_driver; + else + driver = imap_session_driver; + + r = mailstorage_generic_connect_with_local_address(driver, + imap_storage->imap_servername, + imap_storage->imap_port, + imap_storage->imap_local_address, + imap_storage->imap_local_port, + imap_storage->imap_command, + imap_storage->imap_connection_type, + IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY, + imap_storage->imap_cache_directory, + 0, NULL, + &session); + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto err; + } + + r = mailstorage_generic_auth_sasl(session, r, + imap_storage->imap_sasl.sasl_auth_type, + imap_storage->imap_sasl.sasl_server_fqdn, + imap_storage->imap_sasl.sasl_local_ip_port, + imap_storage->imap_sasl.sasl_remote_ip_port, + imap_storage->imap_sasl.sasl_login, + imap_storage->imap_sasl.sasl_auth_name, + imap_storage->imap_sasl.sasl_password, + imap_storage->imap_sasl.sasl_realm); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + * result = session; + + return MAIL_NO_ERROR; + + free: + mailsession_free(session); + err: + return res; +} + +static int imap_mailstorage_connect(struct mailstorage * storage) +{ + mailsession * session; + int r; + int res; + + r = imap_connect(storage, &session); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = mailsession_select_folder(session, "INBOX"); + if (r != MAIL_NO_ERROR) { + mailsession_logout(session); + res = r; + goto err; + } + + storage->sto_session = session; + storage->sto_driver = &imap_mailstorage_driver; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +imap_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result) +{ + mailsession * session; + int r; + int res; + + if (strcasecmp(pathname, "INBOX") == 0) { + session = storage->sto_session; + } + else { + r = imap_connect(storage, &session); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = mailsession_select_folder(session, pathname); + if (r != MAIL_NO_ERROR) { + mailsession_logout(session); + res = r; + goto free; + } + } + + * result = session; + + return MAIL_NO_ERROR; + + free: + mailsession_free(session); + err: + return res; +} diff --git a/Sources/libetpan/driver/implementation/imap/imapstorage.h b/Sources/libetpan/driver/implementation/imap/imapstorage.h new file mode 100644 index 00000000..e79a1b56 --- /dev/null +++ b/Sources/libetpan/driver/implementation/imap/imapstorage.h @@ -0,0 +1,120 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapstorage.h,v 1.13 2007/06/30 12:58:21 hoa Exp $ + */ + +#ifndef IMAPSTORAGE_H + +#define IMAPSTORAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + imap_mailstorage_init is the constructor for a IMAP4rev1 storage + + @param storage this is the storage to initialize. + + @param servername this is the name of the IMAP4rev1 server + + @param port is the port to connect to, on the server. + you give 0 to use the default port. + + @param command the command used to connect to the server instead of + allowing normal TCP connections to be used. + + @param connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS, + CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS, + CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS, + CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,. + + @param auth_type is the authenticate mechanism to use. + The value can be IMAP_AUTH_TYPE_PLAIN. + Other values are not yet implemented. + + @param login is the login of the IMAP4rev1 account. + + @param password is the password of the IMAP4rev1 account. + If performing OAuth2 login, use the OAuth2 token here + instead of password. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache +*/ + +LIBETPAN_EXPORT +int imap_mailstorage_init(struct mailstorage * storage, + const char * imap_servername, uint16_t imap_port, + const char * imap_command, + int imap_connection_type, int imap_auth_type, + const char * imap_login, const char * imap_password, + int imap_cached, const char * imap_cache_directory); + +LIBETPAN_EXPORT +int imap_mailstorage_init_sasl(struct mailstorage * storage, + const char * imap_servername, uint16_t imap_port, + const char * imap_command, + int imap_connection_type, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm, + int imap_cached, const char * imap_cache_directory); + +LIBETPAN_EXPORT +int imap_mailstorage_init_sasl_with_local_address(struct mailstorage * storage, + const char * imap_servername, uint16_t imap_port, + const char * imap_local_address, uint16_t imap_local_port, + const char * imap_command, + int imap_connection_type, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm, + int imap_cached, const char * imap_cache_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/maildir/Makefile.am b/Sources/libetpan/driver/implementation/maildir/Makefile.am new file mode 100644 index 00000000..0fa3f3ac --- /dev/null +++ b/Sources/libetpan/driver/implementation/maildir/Makefile.am @@ -0,0 +1,56 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +etpaninclude_HEADERS = \ + maildirdriver.h \ + maildirdriver_cached.h \ + maildirdriver_cached_message.h \ + maildirdriver_message.h \ + maildirdriver_types.h \ + maildirstorage.h + +AM_CPPFLAGS = -I$(top_builddir)/include \ + -I$(top_srcdir)/src/driver/interface \ + -I$(top_srcdir)/src/driver/tools \ + -I$(top_srcdir)/src/low-level/maildir \ + -I$(top_srcdir)/src/low-level/mime \ + -I$(top_srcdir)/src/low-level/imf \ + -I$(top_srcdir)/src/data-types + +noinst_LTLIBRARIES = libmaildir.la + +libmaildir_la_SOURCES = \ + maildirdriver.c \ + maildirdriver_cached.c \ + maildirdriver_cached_message.c \ + maildirdriver_message.c \ + maildirdriver_tools.h maildirdriver_tools.c \ + maildirstorage.c diff --git a/Sources/libetpan/driver/implementation/maildir/maildirdriver.c b/Sources/libetpan/driver/implementation/maildir/maildirdriver.c new file mode 100644 index 00000000..d5f7f51c --- /dev/null +++ b/Sources/libetpan/driver/implementation/maildir/maildirdriver.c @@ -0,0 +1,685 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver.c,v 1.17 2008/02/17 13:13:26 hoa Exp $ + */ + + +/* + flags directory MUST be kept so that we can have other flags + than standards +*/ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "maildirdriver.h" + +#include +#include +#ifdef WIN32 +# include "win_etpan.h" +#else +# include +# include +# include +#endif +#include +#include +#include +#include +#include + +#include "maildir.h" +#include "maildriver_tools.h" +#include "maildirdriver_message.h" +#include "maildirdriver_tools.h" +#include "mailmessage.h" +#include "generic_cache.h" + +static int initialize(mailsession * session); + +static void uninitialize(mailsession * session); + +static int connect_path(mailsession * session, const char * path); + +static int logout(mailsession * session); + +static int expunge_folder(mailsession * session); + +static int status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int recent_number(mailsession * session, const char * mb, + uint32_t * result); + +static int unseen_number(mailsession * session, const char * mb, + uint32_t * result); + +static int messages_number(mailsession * session, const char * mb, + uint32_t * result); + +static int append_message(mailsession * session, + const char * message, size_t size); + +static int append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); + +static int get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +static int check_folder(mailsession * session); + +static int get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result); + +static mailsession_driver local_maildir_session_driver = { + /* sess_name */ "maildir", + + /* sess_initialize */ initialize, + /* sess_uninitialize */ uninitialize, + + /* sess_parameters */ NULL, + + /* sess_connect_stream */ NULL, + /* sess_connect_path */ connect_path, + /* sess_starttls */ NULL, + /* sess_login */ NULL, + /* sess_logout */ logout, + /* sess_noop */ NULL, + + /* sess_build_folder_name */ NULL, + /* sess_create_folder */ NULL, + /* sess_delete_folder */ NULL, + /* sess_rename_folder */ NULL, + /* sess_check_folder */ check_folder, + /* sess_examine_folder */ NULL, + /* sess_select_folder */ NULL, + /* sess_expunge_folder */ expunge_folder, + /* sess_status_folder */ status_folder, + /* sess_messages_number */ messages_number, + /* sess_recent_number */ recent_number, + /* sess_unseen_number */ unseen_number, + /* sess_list_folders */ NULL, + /* sess_lsub_folders */ NULL, + /* sess_subscribe_folder */ NULL, + /* sess_unsubscribe_folder */ NULL, + + /* sess_append_message */ append_message, + /* sess_append_message_flags */ append_message_flags, + /* sess_copy_message */ NULL, + /* sess_move_message */ NULL, + + /* sess_get_message */ NULL, + /* sess_get_message_by_uid */ get_message_by_uid, + + /* sess_get_messages_list */ get_messages_list, + /* sess_get_envelopes_list */ get_envelopes_list, + /* sess_remove_message */ NULL, +#if 0 + /* sess_search_messages */ maildriver_generic_search_messages, +#endif + /* sess_login_sasl */ NULL +}; + +mailsession_driver * maildir_session_driver = &local_maildir_session_driver; + + +static int flags_store_process(struct maildir * md, + struct mail_flags_store * flags_store); + + +static inline struct maildir_session_state_data * get_data(mailsession * session) +{ + return session->sess_data; +} + +static struct maildir * get_maildir_session(mailsession * session) +{ + return get_data(session)->md_session; +} + +static int initialize(mailsession * session) +{ + struct maildir_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->md_session = NULL; + + data->md_flags_store = mail_flags_store_new(); + if (data->md_flags_store == NULL) + goto free; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free: + free(data); + err: + return MAIL_ERROR_MEMORY; +} + +static void uninitialize(mailsession * session) +{ + struct maildir_session_state_data * data; + + data = get_data(session); + + if (data->md_session != NULL) + flags_store_process(data->md_session, data->md_flags_store); + + mail_flags_store_free(data->md_flags_store); + if (data->md_session != NULL) + maildir_free(data->md_session); + + free(data); + + session->sess_data = NULL; +} + + +static int connect_path(mailsession * session, const char * path) +{ + struct maildir * md; + int res; + int r; + + if (get_maildir_session(session) != NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + md = maildir_new(path); + if (md == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = maildirdriver_maildir_error_to_mail_error(r); + goto free; + } + + get_data(session)->md_session = md; + + return MAIL_NO_ERROR; + + free: + maildir_free(md); + err: + return res; +} + +static int logout(mailsession * session) +{ + struct maildir * md; + + check_folder(session); + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + maildir_free(md); + get_data(session)->md_session = NULL; + + return MAIL_NO_ERROR; +} + +/* folders operations */ + +static int status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + int r; + struct maildir * md; + unsigned int i; + uint32_t messages; + uint32_t recent; + uint32_t unseen; + + check_folder(session); + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) + return maildirdriver_maildir_error_to_mail_error(r); + + messages = 0; + recent = 0; + unseen = 0; + for(i = 0 ; i < carray_count(md->mdir_msg_list) ; i ++) { + struct maildir_msg * msg; + + msg = carray_get(md->mdir_msg_list, i); + if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) + recent ++; + if ((msg->msg_flags & MAILDIR_FLAG_SEEN) == 0) + unseen ++; + messages ++; + } + + * result_messages = messages; + * result_recent = recent; + * result_unseen = unseen; + + return MAIL_NO_ERROR; +} + +static int messages_number(mailsession * session, const char * mb, + uint32_t * result) +{ + struct maildir * md; + int r; + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) + return maildirdriver_maildir_error_to_mail_error(r); + + * result = carray_count(md->mdir_msg_list); + + return MAIL_NO_ERROR; +} + +static int unseen_number(mailsession * session, const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = status_folder(session, mb, &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = unseen; + + return MAIL_NO_ERROR; +} + +static int recent_number(mailsession * session, const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + messages = 0; + recent = 0; + unseen = 0; + r = status_folder(session, mb, &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = recent; + + return MAIL_NO_ERROR; +} + + +/* messages operations */ + +static int append_message(mailsession * session, + const char * message, size_t size) +{ +#if 0 + struct maildir * md; + int r; + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + r = maildir_message_add(md, message, size); + if (r != MAILDIR_NO_ERROR) + return maildirdriver_maildir_error_to_mail_error(r); + + return MAIL_NO_ERROR; +#endif + + return append_message_flags(session, message, size, NULL); +} + +static int append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags) +{ + struct maildir * md; + int r; + char uid[PATH_MAX]; + chashdatum key; + chashdatum value; + uint32_t md_flags; + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + r = maildir_message_add_uid(md, message, size, + uid, sizeof(uid)); + if (r != MAILDIR_NO_ERROR) + return maildirdriver_maildir_error_to_mail_error(r); + + if (flags == NULL) + goto exit; + + key.data = uid; + key.len = (unsigned int) strlen(uid); + r = chash_get(md->mdir_msg_hash, &key, &value); + if (r < 0) + goto exit; + + md_flags = maildirdriver_flags_to_maildir_flags(flags->fl_flags); + + r = maildir_message_change_flags(md, uid, md_flags); + if (r != MAILDIR_NO_ERROR) + goto exit; + + return MAIL_NO_ERROR; + + exit: + return MAIL_NO_ERROR; +} + +static int get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + struct maildir * md; + int r; + struct mailmessage_list * env_list; + int res; + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = maildirdriver_maildir_error_to_mail_error(r); + goto err; + } + + r = maildir_get_messages_list(session, md, + maildir_message_driver, &env_list); + if (r != MAILDIR_NO_ERROR) { + res = r; + goto free_list; + } + + * result = env_list; + + return MAIL_NO_ERROR; + + free_list: + mailmessage_list_free(env_list); + err: + return res; +} + +static int get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + struct maildir * md; + unsigned int i; + int res; + + check_folder(session); + + md = get_maildir_session(session); + if (md == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = maildirdriver_maildir_error_to_mail_error(r); + goto err; + } + + r = maildriver_generic_get_envelopes_list(session, env_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i++) { + struct maildir_msg * md_msg; + mailmessage * msg; + uint32_t driver_flags; + clist * ext; + chashdatum key; + chashdatum value; + + msg = carray_get(env_list->msg_tab, i); + + key.data = msg->msg_uid; + key.len = (unsigned int) strlen(msg->msg_uid); + r = chash_get(md->mdir_msg_hash, &key, &value); + if (r < 0) + continue; + + md_msg = value.data; + + driver_flags = maildirdriver_maildir_flags_to_flags(md_msg->msg_flags); + + if (msg->msg_flags == NULL) { + ext = clist_new(); + if (ext == NULL) { + res = MAIL_ERROR_MEMORY; + continue; + } + + msg->msg_flags = mail_flags_new(driver_flags, ext); + if (msg->msg_flags == NULL) { + clist_free(ext); + res = MAIL_ERROR_MEMORY; + continue; + } + + if ((md_msg->msg_flags & MAILDIR_FLAG_NEW) != 0) { + mail_flags_store_set(get_data(session)->md_flags_store, msg); + } + } + else { + msg->msg_flags->fl_flags &= MAIL_FLAG_FORWARDED; + msg->msg_flags->fl_flags |= driver_flags; + } + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + +static int expunge_folder(mailsession * session) +{ + unsigned int i; + int r; + int res; + struct maildir * md; + + check_folder(session); + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = maildirdriver_maildir_error_to_mail_error(r); + goto err; + } + + for(i = 0 ; i < carray_count(md->mdir_msg_list) ; i++) { + struct maildir_msg * md_msg; + + md_msg = carray_get(md->mdir_msg_list, i); + + if ((md_msg->msg_flags & MAILDIR_FLAG_TRASHED) != 0) + maildir_message_remove(md, md_msg->msg_uid); + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + +static int flags_store_process(struct maildir * md, + struct mail_flags_store * flags_store) +{ + unsigned int i; + + if (carray_count(flags_store->fls_tab) == 0) + return MAIL_NO_ERROR; + + for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { + mailmessage * msg; + uint32_t md_flags; + + msg = carray_get(flags_store->fls_tab, i); + md_flags = maildirdriver_flags_to_maildir_flags(msg->msg_flags->fl_flags); + md_flags &= ~MAILDIR_FLAG_NEW; + + maildir_message_change_flags(md, msg->msg_uid, md_flags); + } + + mail_flags_store_clear(flags_store); + + return MAIL_NO_ERROR; +} + + + +static int check_folder(mailsession * session) +{ + struct mail_flags_store * flags_store; + struct maildir_session_state_data * data; + struct maildir * md; + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + data = get_data(session); + flags_store = data->md_flags_store; + + return flags_store_process(md, flags_store); +} + +static int get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result) +{ + int r; + struct maildir * md; + int res; + mailmessage * msg; + char * msg_filename; + struct stat stat_info; + + md = get_maildir_session(session); + + /* update maildir data */ + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = maildirdriver_maildir_error_to_mail_error(r); + goto err; + } + + msg_filename = maildir_message_get(md, uid); + if (msg_filename == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + r = stat(msg_filename, &stat_info); + free(msg_filename); + if (r < 0) { + res = MAIL_ERROR_INVAL; + goto err; + } + + /* create message */ + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailmessage_init(msg, session, maildir_message_driver, + 0, stat_info.st_size); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg); + res = r; + goto err; + } + + msg->msg_uid = strdup(uid); + if (msg->msg_uid == NULL) { + mailmessage_free(msg); + res = r; + goto err; + } + + * result = msg; + + return MAIL_NO_ERROR; + + err: + return res; +} diff --git a/Sources/libetpan/driver/implementation/maildir/maildirdriver.h b/Sources/libetpan/driver/implementation/maildir/maildirdriver.h new file mode 100644 index 00000000..1eef99c9 --- /dev/null +++ b/Sources/libetpan/driver/implementation/maildir/maildirdriver.h @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver.h,v 1.4 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MAILDIRDRIVER_H + +#define MAILDIRDRIVER_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * maildir_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/maildir/maildirdriver_cached.c b/Sources/libetpan/driver/implementation/maildir/maildirdriver_cached.c new file mode 100644 index 00000000..0600fa39 --- /dev/null +++ b/Sources/libetpan/driver/implementation/maildir/maildirdriver_cached.c @@ -0,0 +1,1163 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver_cached.c,v 1.22 2009/07/23 19:46:46 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "maildirdriver.h" + +#include +#include +#ifndef WIN32 +# include +# include +# include +#endif +#include +#include +#include +#include +#include + +#include "mail.h" +#include "maildir.h" +#include "maildriver_tools.h" +#include "maildirdriver_tools.h" +#include "maildirdriver_cached_message.h" +#include "mailmessage.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "mail_cache_db.h" +#include "libetpan-config.h" + +static int initialize(mailsession * session); + +static void uninitialize(mailsession * session); + +static int parameters(mailsession * session, + int id, void * value); + +static int connect_path(mailsession * session, const char * path); + +static int logout(mailsession * session); + +static int expunge_folder(mailsession * session); + +static int status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int recent_number(mailsession * session, const char * mb, + uint32_t * result); + +static int unseen_number(mailsession * session, const char * mb, + uint32_t * result); + +static int messages_number(mailsession * session, const char * mb, + uint32_t * result); + +static int append_message(mailsession * session, + const char * message, size_t size); + +static int append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); + +static int get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +static int check_folder(mailsession * session); + +static int get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result); + +static mailsession_driver local_maildir_cached_session_driver = { + /* sess_name */ "maildir-cached", + + /* sess_initialize */ initialize, + /* sess_uninitialize */ uninitialize, + + /* sess_parameters */ parameters, + + /* sess_connect_stream */ NULL, + /* sess_connect_path */ connect_path, + /* sess_starttls */ NULL, + /* sess_login */ NULL, + /* sess_logout */ logout, + /* sess_noop */ NULL, + + /* sess_build_folder_name */ NULL, + /* sess_create_folder */ NULL, + /* sess_delete_folder */ NULL, + /* sess_rename_folder */ NULL, + /* sess_check_folder */ check_folder, + /* sess_examine_folder */ NULL, + /* sess_select_folder */ NULL, + /* sess_expunge_folder */ expunge_folder, + /* sess_status_folder */ status_folder, + /* sess_messages_number */ messages_number, + /* sess_recent_number */ recent_number, + /* sess_unseen_number */ unseen_number, + /* sess_list_folders */ NULL, + /* sess_lsub_folders */ NULL, + /* sess_subscribe_folder */ NULL, + /* sess_unsubscribe_folder */ NULL, + + /* sess_append_message */ append_message, + /* sess_append_message_flags */ append_message_flags, + /* sess_copy_message */ NULL, + /* sess_move_message */ NULL, + + /* sess_get_message */ get_message, + /* sess_get_message_by_uid */ get_message_by_uid, + + /* sess_get_messages_list */ get_messages_list, + /* sess_get_envelopes_list */ get_envelopes_list, + /* sess_remove_message */ NULL, +#if 0 + /* sess_search_messages */ maildriver_generic_search_messages, +#endif + /* sess_login_sasl */ NULL +}; + +mailsession_driver * maildir_cached_session_driver = +&local_maildir_cached_session_driver; + + +static inline struct maildir_cached_session_state_data * +get_cached_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * get_ancestor(mailsession * session) +{ + return get_cached_data(session)->md_ancestor; +} + +static inline struct maildir_session_state_data * +get_ancestor_data(mailsession * session) +{ + return get_ancestor(session)->sess_data; +} + + +static struct maildir * get_maildir_session(mailsession * session) +{ + return get_ancestor_data(session)->md_session; +} + +static int initialize(mailsession * session) +{ + struct maildir_cached_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->md_ancestor = mailsession_new(maildir_session_driver); + if (data->md_ancestor == NULL) + goto free; + + data->md_flags_store = mail_flags_store_new(); + if (data->md_flags_store == NULL) + goto free_session; + + data->md_quoted_mb = NULL; + data->md_cache_directory[0] = '\0'; + data->md_flags_directory[0] = '\0'; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free_session: + mailsession_free(data->md_ancestor); + free: + free(data); + err: + return MAIL_ERROR_MEMORY; +} + +static void +free_quoted_mb(struct maildir_cached_session_state_data * maildir_cached_data) +{ + if (maildir_cached_data->md_quoted_mb != NULL) { + free(maildir_cached_data->md_quoted_mb); + maildir_cached_data->md_quoted_mb = NULL; + } +} + +static int +write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, struct mail_flags * flags); + +#define ENV_NAME "env.db" +#define FLAGS_NAME "flags.db" + +static int flags_store_process(char * flags_directory, char * quoted_mb, + struct mail_flags_store * flags_store) +{ + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + unsigned int i; + int r; + int res; + + if (carray_count(flags_store->fls_tab) == 0) + return MAIL_NO_ERROR; + + if (quoted_mb == NULL) + return MAIL_NO_ERROR; + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + flags_directory, MAIL_DIR_SEPARATOR, quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(flags_store->fls_tab, i); + + r = write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + if (r != MAIL_NO_ERROR) { + /* ignore errors */ + } + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + mail_flags_store_clear(flags_store); + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static void uninitialize(mailsession * session) +{ + struct maildir_cached_session_state_data * data; + + data = get_cached_data(session); + + flags_store_process(data->md_flags_directory, + data->md_quoted_mb, + data->md_flags_store); + + mail_flags_store_free(data->md_flags_store); + mailsession_free(data->md_ancestor); + free_quoted_mb(data); + free(data); + + session->sess_data = NULL; +} + + +static int parameters(mailsession * session, + int id, void * value) +{ + struct maildir_cached_session_state_data * data; + int r; + + data = get_cached_data(session); + + switch (id) { + case MAILDIRDRIVER_CACHED_SET_CACHE_DIRECTORY: + strncpy(data->md_cache_directory, value, PATH_MAX); + data->md_cache_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(data->md_cache_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + case MAILDIRDRIVER_CACHED_SET_FLAGS_DIRECTORY: + strncpy(data->md_flags_directory, value, PATH_MAX); + data->md_flags_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(data->md_flags_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + default: + return mailsession_parameters(data->md_ancestor, id, value); + } +} + + +static int get_cache_folder(mailsession * session, char ** result) +{ + struct maildir * md; + char * quoted_mb; + int res; + int r; + char key[PATH_MAX]; + struct maildir_cached_session_state_data * data; + + md = get_maildir_session(session); + data = get_cached_data(session); + + quoted_mb = maildriver_quote_mailbox(md->mdir_path); + if (quoted_mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(key, PATH_MAX, "%s/%s", data->md_cache_directory, quoted_mb); + r = generic_cache_create_dir(key); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_quoted_mb; + } + + snprintf(key, PATH_MAX, "%s/%s", data->md_flags_directory, quoted_mb); + r = generic_cache_create_dir(key); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_quoted_mb; + } + + * result = quoted_mb; + + return MAIL_NO_ERROR; + + free_quoted_mb: + free(quoted_mb); + err: + return res; +} + + +static int connect_path(mailsession * session, const char * path) +{ + int r; + int res; + char * quoted_mb; + + r = mailsession_connect_path(get_ancestor(session), path); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + quoted_mb = NULL; + r = get_cache_folder(session, "ed_mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto logout; + } + + get_cached_data(session)->md_quoted_mb = quoted_mb; + + return MAILDIR_NO_ERROR; + + logout: + mailsession_logout(get_ancestor(session)); + err: + return res; +} + +static int logout(mailsession * session) +{ + struct maildir_cached_session_state_data * data; + int r; + + data = get_cached_data(session); + + flags_store_process(data->md_flags_directory, + data->md_quoted_mb, data->md_flags_store); + + r = mailsession_logout(get_ancestor(session)); + if (r != MAIL_NO_ERROR) + return r; + + free_quoted_mb(get_cached_data(session)); + + return MAIL_NO_ERROR; +} + +static int status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + return mailsession_status_folder(get_ancestor(session), mb, + result_messages, result_recent, result_unseen); +} + +static int messages_number(mailsession * session, const char * mb, + uint32_t * result) +{ + return mailsession_messages_number(get_ancestor(session), mb, result); +} + +static int unseen_number(mailsession * session, const char * mb, + uint32_t * result) +{ + return mailsession_unseen_number(get_ancestor(session), mb, result); +} + +static int recent_number(mailsession * session, const char * mb, + uint32_t * result) +{ + return mailsession_recent_number(get_ancestor(session), mb, result); +} + + +static int append_message(mailsession * session, + const char * message, size_t size) +{ +#if 0 + return mailsession_append_message(get_ancestor(session), message, size); +#endif + return append_message_flags(session, message, size, NULL); +} + +static int append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags) +{ + struct maildir * md; + int r; + char uid[PATH_MAX]; + chashdatum key; + chashdatum value; + uint32_t md_flags; + struct mail_cache_db * cache_db_flags; + char filename_flags[PATH_MAX]; + MMAPString * mmapstr; + struct maildir_cached_session_state_data * data; + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + r = maildir_message_add_uid(md, message, size, + uid, sizeof(uid)); + if (r != MAILDIR_NO_ERROR) + return maildirdriver_maildir_error_to_mail_error(r); + + if (flags == NULL) + goto exit; + + data = get_cached_data(session); + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) + goto exit; + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) + goto close_db_flags; + + r = write_cached_flags(cache_db_flags, mmapstr, + uid, flags); + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + if (r != MAIL_NO_ERROR) + goto exit; + + key.data = uid; + key.len = (unsigned int) strlen(uid); + r = chash_get(md->mdir_msg_hash, &key, &value); + if (r < 0) + goto exit; + + md_flags = maildirdriver_flags_to_maildir_flags(flags->fl_flags); + + r = maildir_message_change_flags(md, uid, md_flags); + if (r != MAILDIR_NO_ERROR) + goto exit; + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + exit: + return MAIL_NO_ERROR; +} + +#define UID_NAME "uid.db" + +static int uid_clean_up(struct mail_cache_db * uid_db, + struct mailmessage_list * env_list) +{ + chash * hash_exist; + int res; + int r; + unsigned int i; + chashdatum key; + chashdatum value; + char key_str[PATH_MAX]; + + /* flush cache */ + + hash_exist = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL); + if (hash_exist == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + value.data = NULL; + value.len = 0; + + key.data = "max-uid"; + key.len = strlen("max-uid"); + r = chash_set(hash_exist, &key, &value, NULL); + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + value.data = NULL; + value.len = 0; + + key.data = msg->msg_uid; + key.len = (unsigned int) strlen(msg->msg_uid); + r = chash_set(hash_exist, &key, &value, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + snprintf(key_str, sizeof(key_str), "uid-%lu", + (unsigned long) msg->msg_index); + key.data = key_str; + key.len = (unsigned int) strlen(key_str); + r = chash_set(hash_exist, &key, &value, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + } + + mail_cache_db_clean_up(uid_db, hash_exist); + + chash_free(hash_exist); + + return MAIL_NO_ERROR; + + free: + chash_free(hash_exist); + err: + return res; +} + +static int get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + struct maildir * md; + int r; + struct mailmessage_list * env_list; + int res; + uint32_t max_uid; + char filename[PATH_MAX]; + struct mail_cache_db * uid_db; + void * value; + size_t value_len; + struct maildir_cached_session_state_data * data; + char key[PATH_MAX]; + unsigned int i; + + data = get_cached_data(session); + + md = get_maildir_session(session); + if (md == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + check_folder(session); + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = maildirdriver_maildir_error_to_mail_error(r); + goto err; + } + + r = maildir_get_messages_list(session, md, + maildir_cached_message_driver, &env_list); + if (r != MAILDIR_NO_ERROR) { + res = r; + goto err; + } + + /* read/write DB */ + + snprintf(filename, sizeof(filename), "%s%c%s%c%s", + data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb, + MAIL_DIR_SEPARATOR, UID_NAME); + + r = mail_cache_db_open_lock(filename, &uid_db); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + max_uid = 0; + r = mail_cache_db_get(uid_db, "max-uid", sizeof("max-uid") - 1, + &value, &value_len); + if (r == 0) { + memcpy(&max_uid, value, sizeof(max_uid)); + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + uint32_t indx; + + msg = carray_get(env_list->msg_tab, i); + + r = mail_cache_db_get(uid_db, msg->msg_uid, + strlen(msg->msg_uid), &value, &value_len); + if (r < 0) { + max_uid ++; + msg->msg_index = max_uid; + mail_cache_db_put(uid_db, msg->msg_uid, + strlen(msg->msg_uid), &msg->msg_index, sizeof(msg->msg_index)); + + snprintf(key, sizeof(key), "uid-%lu", (unsigned long) msg->msg_index); + mail_cache_db_put(uid_db, key, strlen(key), + msg->msg_uid, strlen(msg->msg_uid)); + } + else { + memcpy(&indx, value, sizeof(indx)); + msg->msg_index = indx; + } + } + + mail_cache_db_put(uid_db, "max-uid", sizeof("max-uid") - 1, + &max_uid, sizeof(max_uid)); + + uid_clean_up(uid_db, env_list); + + mail_cache_db_close_unlock(filename, uid_db); + + * result = env_list; + + return MAIL_NO_ERROR; + + free_list: + mailmessage_list_free(env_list); + err: + return res; +} + +static int +get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, + char * uid, + struct mail_flags ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mail_flags * flags; + int res; + + snprintf(keyname, PATH_MAX, "%s-flags", uid); + + r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = flags; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, char * uid, + struct mailimf_fields ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mailimf_fields * fields; + int res; + + snprintf(keyname, PATH_MAX, "%s-envelope", uid); + + r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = fields; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +write_cached_envelope(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, char * uid, + struct mailimf_fields * fields) +{ + int r; + char keyname[PATH_MAX]; + int res; + + snprintf(keyname, PATH_MAX, "%s-envelope", uid); + + r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, struct mail_flags * flags) +{ + int r; + char keyname[PATH_MAX]; + int res; + + snprintf(keyname, PATH_MAX, "%s-flags", uid); + + r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + +static int get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + unsigned int i; + int res; + struct maildir_cached_session_state_data * data; + char filename_env[PATH_MAX]; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_env; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + + data = get_cached_data(session); + + flags_store_process(data->md_flags_directory, + data->md_quoted_mb, data->md_flags_store); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(filename_env, PATH_MAX, "%s%c%s%c%s", + data->md_cache_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb, + MAIL_DIR_SEPARATOR, ENV_NAME); + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto free_mmapstr; + } + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto close_db_env; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i++) { + mailmessage * msg; + struct mailimf_fields * fields; + struct mail_flags * flags; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + r = get_cached_envelope(cache_db_env, mmapstr, session, + msg->msg_uid, &fields); + if (r == MAIL_NO_ERROR) { + msg->msg_cached = TRUE; + msg->msg_fields = fields; + } + } + + if (msg->msg_flags == NULL) { + r = get_cached_flags(cache_db_flags, mmapstr, + session, msg->msg_uid, &flags); + if (r == MAIL_NO_ERROR) { + msg->msg_flags = flags; + } + } + } + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + + r = mailsession_get_envelopes_list(get_ancestor(session), env_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto close_db_env; + } + + /* must write cache */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields != NULL) { + if (!msg->msg_cached) { + /* msg->msg_uid is the numerical UID of the message */ + r = write_cached_envelope(cache_db_env, mmapstr, + session, msg->msg_uid, msg->msg_fields); + } + } + + if (msg->msg_flags != NULL) { + r = write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + } + } + + /* flush cache */ + + maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list); + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + + mmap_string_free(mmapstr); + + return MAIL_NO_ERROR; + + close_db_env: + mail_cache_db_close_unlock(filename_env, cache_db_env); + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + +static int expunge_folder(mailsession * session) +{ + return mailsession_expunge_folder(get_ancestor(session)); +} + +static int check_folder(mailsession * session) +{ + struct maildir_cached_session_state_data * data; + + data = get_cached_data(session); + + flags_store_process(data->md_flags_directory, + data->md_quoted_mb, data->md_flags_store); + + return mailsession_check_folder(get_ancestor(session)); +} + +static int get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + struct maildir * md; + int res; + mailmessage * msg; + char filename[PATH_MAX]; + struct mail_cache_db * uid_db; + char * msg_filename; + struct stat stat_info; + char key_str[PATH_MAX]; + void * value; + size_t value_len; + char uid[PATH_MAX]; + struct maildir_cached_session_state_data * data; + int r; + + data = get_cached_data(session); + + md = get_maildir_session(session); + + /* a get_messages_list() should have been done once before */ + + /* read DB */ + + snprintf(filename, sizeof(filename), "%s%c%s%c%s", + data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb, + MAIL_DIR_SEPARATOR, UID_NAME); + + r = mail_cache_db_open_lock(filename, &uid_db); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(key_str, sizeof(key_str), "uid-%lu", (unsigned long) num); + + r = mail_cache_db_get(uid_db, key_str, strlen(key_str), &value, &value_len); + if (r < 0) { + res = MAIL_ERROR_INVAL; + goto close_db; + } + + if (value_len >= PATH_MAX) { + res = MAIL_ERROR_INVAL; + goto close_db; + } + + memcpy(uid, value, value_len); + uid[value_len] = '\0'; + + mail_cache_db_close_unlock(filename, uid_db); + + /* update maildir data */ + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = maildirdriver_maildir_error_to_mail_error(r); + goto err; + } + + msg_filename = maildir_message_get(md, uid); + if (msg_filename == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + r = stat(msg_filename, &stat_info); + free(msg_filename); + if (r < 0) { + res = MAIL_ERROR_INVAL; + goto err; + } + + /* create message */ + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailmessage_init(msg, session, maildir_cached_message_driver, + num, stat_info.st_size); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg); + res = r; + goto err; + } + + msg->msg_uid = strdup(uid); + if (msg->msg_uid == NULL) { + mailmessage_free(msg); + res = r; + goto err; + } + + * result = msg; + + return MAIL_NO_ERROR; + + close_db: + mail_cache_db_close_unlock(filename, uid_db); + err: + return res; +} + + +static int get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result) +{ + int r; + struct maildir * md; + int res; + mailmessage * msg; + char filename[PATH_MAX]; + struct mail_cache_db * uid_db; + char * msg_filename; + struct stat stat_info; + void * value; + size_t value_len; + struct maildir_cached_session_state_data * data; + uint32_t indx; + + data = get_cached_data(session); + + md = get_maildir_session(session); + + /* a get_messages_list() should have been done once before */ + + /* read DB */ + + snprintf(filename, sizeof(filename), "%s%c%s%c%s", + data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb, + MAIL_DIR_SEPARATOR, UID_NAME); + + r = mail_cache_db_open_lock(filename, &uid_db); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mail_cache_db_get(uid_db, uid, strlen(uid), &value, &value_len); + if (r < 0) { + res = MAIL_ERROR_INVAL; + goto close_db; + } + + memcpy(&indx, value, sizeof(indx)); + + mail_cache_db_close_unlock(filename, uid_db); + + /* update maildir data */ + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = maildirdriver_maildir_error_to_mail_error(r); + goto err; + } + + msg_filename = maildir_message_get(md, uid); + if (msg_filename == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + r = stat(msg_filename, &stat_info); + free(msg_filename); + if (r < 0) { + res = MAIL_ERROR_INVAL; + goto err; + } + + /* create message */ + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailmessage_init(msg, session, maildir_cached_message_driver, + indx, stat_info.st_size); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg); + res = r; + goto err; + } + + msg->msg_uid = strdup(uid); + if (msg->msg_uid == NULL) { + mailmessage_free(msg); + res = r; + goto err; + } + + * result = msg; + + return MAIL_NO_ERROR; + + close_db: + mail_cache_db_close_unlock(filename, uid_db); + err: + return res; +} diff --git a/Sources/libetpan/driver/implementation/maildir/maildirdriver_cached.h b/Sources/libetpan/driver/implementation/maildir/maildirdriver_cached.h new file mode 100644 index 00000000..e8d8a762 --- /dev/null +++ b/Sources/libetpan/driver/implementation/maildir/maildirdriver_cached.h @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver_cached.h,v 1.4 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MAILDIRDRIVER_CACHED_H + +#define MAILDIRDRIVER_CACHED_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * maildir_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/maildir/maildirdriver_cached_message.c b/Sources/libetpan/driver/implementation/maildir/maildirdriver_cached_message.c new file mode 100644 index 00000000..5385d207 --- /dev/null +++ b/Sources/libetpan/driver/implementation/maildir/maildirdriver_cached_message.c @@ -0,0 +1,344 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver_cached_message.c,v 1.11 2008/02/17 13:13:26 hoa Exp $ + */ +#define HAVE_CONFIG_H 1 + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "maildirdriver_message.h" + +#include "mailmessage_tools.h" +#include "maildirdriver.h" +#include "maildir.h" +#include "generic_cache.h" +#include "mail_cache_db.h" +#include "maildirdriver_tools.h" + +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_SYS_MMAN_H +# include +#endif +#ifdef WIN32 +# include "win_etpan.h" +#endif +#include +#include +#include +#include +#include + +static int get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +static int prefetch(mailmessage * msg_info); + +static void prefetch_free(struct generic_message_t * msg); + +static int initialize(mailmessage * msg_info); + +static void check(mailmessage * msg_info); + +static mailmessage_driver local_maildir_cached_message_driver = { + /* msg_name */ "maildir-cached", + + /* msg_initialize */ initialize, + /* msg_uninitialize */ mailmessage_generic_uninitialize, + + /* msg_flush */ mailmessage_generic_flush, + /* msg_check */ check, + + /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free, + + /* msg_fetch */ mailmessage_generic_fetch, + /* msg_fetch_header */ mailmessage_generic_fetch_header, + /* msg_fetch_body */ mailmessage_generic_fetch_header, + /* msg_fetch_size */ NULL, + /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure, + /* msg_fetch_section */ mailmessage_generic_fetch_section, + /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header, + /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime, + /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body, + /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope, + + /* msg_get_flags */ get_flags +}; + +mailmessage_driver * maildir_cached_message_driver = +&local_maildir_cached_message_driver; + +struct maildir_msg_data { + int fd; +}; + +#if 0 +static inline struct maildir_cached_session_state_data * +get_cached_session_data(mailmessage * msg) +{ + return msg->session->data; +} + +static inline mailsession * cached_session_get_ancestor(mailsession * session) +{ + return get_data(session)->session; +} + +static inline struct maildir_session_state_data * +cached_session_get_ancestor_data(mailsession * session) +{ + return get_ancestor(session)->data; +} + +static struct maildir * get_maildir_session(mailmessage * msg) +{ + return cached_session_get_ancestor_data(msg->session)->session; +} +#endif +static inline struct maildir_cached_session_state_data * +get_cached_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline struct maildir_cached_session_state_data * +cached_session_get_data(mailsession * s) +{ + return s->sess_data; +} + +static inline mailsession * cached_session_get_ancestor(mailsession * s) +{ + return cached_session_get_data(s)->md_ancestor; +} + +static inline struct maildir_session_state_data * +cached_session_get_ancestor_data(mailsession * s) +{ + return cached_session_get_ancestor(s)->sess_data; +} + +static inline struct maildir_session_state_data * +get_session_ancestor_data(mailmessage * msg) +{ + return cached_session_get_ancestor_data(msg->msg_session); +} + +static inline struct maildir * +cached_session_get_maildir_session(mailsession * session) +{ + return cached_session_get_ancestor_data(session)->md_session; +} + +static inline struct maildir * get_maildir_session(mailmessage * msg) +{ + return cached_session_get_maildir_session(msg->msg_session); +} + +static int prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int res; + struct maildir_msg_data * data; + char * filename; + int fd; + char * mapping; + struct maildir * md; + + md = get_maildir_session(msg_info); + + filename = maildir_message_get(md, msg_info->msg_uid); + if (filename == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fd = open(filename, O_RDONLY); + free(filename); + if (fd == -1) { + res = MAIL_ERROR_FILE; + goto err; + } + + mapping = mmap(NULL, msg_info->msg_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapping == (char *)MAP_FAILED) { + res = MAIL_ERROR_FILE; + goto close; + } + + data = malloc(sizeof(* data)); + if (data == NULL) { + res = MAIL_ERROR_MEMORY; + goto unmap; + } + + data->fd = fd; + + msg = msg_info->msg_data; + + msg->msg_data = data; + msg->msg_message = mapping; + msg->msg_length = msg_info->msg_size; + + return MAIL_NO_ERROR; + + unmap: + munmap(mapping, msg_info->msg_size); + close: + close(fd); + err: + return res; +} + +static void prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + struct maildir_msg_data * data; + + munmap(msg->msg_message, msg->msg_length); + msg->msg_message = NULL; + data = msg->msg_data; + close(data->fd); + free(data); + } +} + +static int initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + msg->msg_prefetch = prefetch; + msg->msg_prefetch_free = prefetch_free; + + return MAIL_NO_ERROR; +} + +static void check(mailmessage * msg_info) +{ + if (msg_info->msg_flags != NULL) { + mail_flags_store_set(get_session_ancestor_data(msg_info)->md_flags_store, msg_info); + + mail_flags_store_set(get_cached_session_data(msg_info)->md_flags_store, msg_info); + /* ignore errors */ + } +} + +#define FLAGS_NAME "flags.db" + +static int get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + struct mail_cache_db * cache_db_flags; + chashdatum key; + chashdatum value; + struct maildir * md; + struct mail_flags * flags; + struct maildir_cached_session_state_data * data; + struct maildir_msg * md_msg; + int r; + uint32_t driver_flags; + char filename_flags[PATH_MAX]; + char keyname[PATH_MAX]; + MMAPString * mmapstr; + + if (msg_info->msg_flags != NULL) { + * result = msg_info->msg_flags; + return MAIL_NO_ERROR; + } + + data = get_cached_session_data(msg_info); + flags = mail_flags_store_get(data->md_flags_store, + msg_info->msg_index); + if (flags != NULL) { + msg_info->msg_flags = flags; + * result = msg_info->msg_flags; + return MAIL_NO_ERROR; + } + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) + return MAIL_ERROR_FILE; + + snprintf(keyname, PATH_MAX, "%s-flags", msg_info->msg_uid); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + return MAIL_ERROR_MEMORY; + } + + r = generic_cache_flags_read(cache_db_flags, mmapstr, keyname, &flags); + mmap_string_free(mmapstr); + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + if (r != MAIL_NO_ERROR) { + flags = mail_flags_new_empty(); + if (flags == NULL) + return MAIL_ERROR_MEMORY; + } + + md = get_maildir_session(msg_info); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + key.data = msg_info->msg_uid; + key.len = (unsigned int) strlen(msg_info->msg_uid); + r = chash_get(md->mdir_msg_hash, &key, &value); + if (r < 0) + return MAIL_ERROR_MSG_NOT_FOUND; + + md_msg = value.data; + + driver_flags = maildirdriver_maildir_flags_to_flags(md_msg->msg_flags); + + flags->fl_flags = driver_flags; + msg_info->msg_flags = flags; + + * result = msg_info->msg_flags; + + return MAIL_NO_ERROR; +} diff --git a/Sources/libetpan/driver/implementation/maildir/maildirdriver_cached_message.h b/Sources/libetpan/driver/implementation/maildir/maildirdriver_cached_message.h new file mode 100644 index 00000000..731b72be --- /dev/null +++ b/Sources/libetpan/driver/implementation/maildir/maildirdriver_cached_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver_cached_message.h,v 1.3 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MAILDIRDRIVER_CACHED_MESSAGE_H + +#define MAILDIRDRIVER_CACHED_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * maildir_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/maildir/maildirdriver_message.c b/Sources/libetpan/driver/implementation/maildir/maildirdriver_message.c new file mode 100644 index 00000000..84e3e314 --- /dev/null +++ b/Sources/libetpan/driver/implementation/maildir/maildirdriver_message.c @@ -0,0 +1,267 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver_message.c,v 1.11 2008/02/17 13:13:26 hoa Exp $ + */ + +#define HAVE_CONFIG_H 1 + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "maildirdriver_message.h" + +#include "maildirdriver_tools.h" + +#include "mailmessage_tools.h" +#include "maildirdriver.h" +#include "maildir.h" +#include "generic_cache.h" + +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_SYS_MMAN_H +# include +#endif +#include +#include +#include +#include +#include +#ifdef WIN32 +# include "win_etpan.h" +#endif + +static int get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +static int prefetch(mailmessage * msg_info); + +static void prefetch_free(struct generic_message_t * msg); + +static int initialize(mailmessage * msg_info); + +static void check(mailmessage * msg_info); + +static mailmessage_driver local_maildir_message_driver = { + /* msg_name */ "maildir", + + /* msg_initialize */ initialize, + /* msg_uninitialize */ mailmessage_generic_uninitialize, + + /* msg_flush */ mailmessage_generic_flush, + /* msg_check */ check, + + /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free, + + /* msg_fetch */ mailmessage_generic_fetch, + /* msg_fetch_header */ mailmessage_generic_fetch_header, + /* msg_fetch_body */ mailmessage_generic_fetch_header, + /* msg_fetch_size */ NULL, + /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure, + /* msg_fetch_section */ mailmessage_generic_fetch_section, + /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header, + /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime, + /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body, + /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope, + + /* msg_get_flags */ get_flags +}; + +mailmessage_driver * maildir_message_driver = &local_maildir_message_driver; + +struct maildir_msg_data { + int fd; +}; + +static inline struct maildir_session_state_data * +get_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static struct maildir * get_maildir_session(mailmessage * msg) +{ + return get_session_data(msg)->md_session; +} + +static int prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int res; + struct maildir_msg_data * data; + char * filename; + int fd; + char * mapping; + struct maildir * md; + + md = get_maildir_session(msg_info); + + if (msg_info->msg_uid == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + filename = maildir_message_get(md, msg_info->msg_uid); + if (filename == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fd = open(filename, O_RDONLY); + free(filename); + if (fd == -1) { + res = MAIL_ERROR_FILE; + goto err; + } + + mapping = mmap(NULL, msg_info->msg_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapping == (char *)MAP_FAILED) { + res = MAIL_ERROR_FILE; + goto close; + } + + data = malloc(sizeof(* data)); + if (data == NULL) { + res = MAIL_ERROR_MEMORY; + goto unmap; + } + + data->fd = fd; + + msg = msg_info->msg_data; + + msg->msg_data = data; + msg->msg_message = mapping; + msg->msg_length = msg_info->msg_size; + + return MAIL_NO_ERROR; + + unmap: + munmap(mapping, msg_info->msg_size); + close: + close(fd); + err: + return res; +} + +static void prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + struct maildir_msg_data * data; + + munmap(msg->msg_message, msg->msg_length); + msg->msg_message = NULL; + data = msg->msg_data; + close(data->fd); + free(data); + } +} + +static int initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + msg->msg_prefetch = prefetch; + msg->msg_prefetch_free = prefetch_free; + + return MAIL_NO_ERROR; +} + +static void check(mailmessage * msg_info) +{ + if (msg_info->msg_flags != NULL) { + mail_flags_store_set(get_session_data(msg_info)->md_flags_store, + msg_info); + /* ignore errors */ + } +} + +static int get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + chashdatum key; + chashdatum value; + struct maildir * md; + struct mail_flags * flags; + struct maildir_session_state_data * data; + struct maildir_msg * md_msg; + int r; + uint32_t driver_flags; + clist * ext; + + if (msg_info->msg_flags != NULL) { + * result = msg_info->msg_flags; + return MAIL_NO_ERROR; + } + + data = get_session_data(msg_info); + flags = mail_flags_store_get(data->md_flags_store, + msg_info->msg_index); + if (flags != NULL) { + msg_info->msg_flags = flags; + * result = msg_info->msg_flags; + return MAIL_NO_ERROR; + } + + md = get_maildir_session(msg_info); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + key.data = msg_info->msg_uid; + key.len = (unsigned int) strlen(msg_info->msg_uid); + r = chash_get(md->mdir_msg_hash, &key, &value); + if (r < 0) + return MAIL_ERROR_MSG_NOT_FOUND; + + md_msg = value.data; + + driver_flags = maildirdriver_maildir_flags_to_flags(md_msg->msg_flags); + + ext = clist_new(); + if (ext == NULL) + return MAIL_ERROR_MEMORY; + + msg_info->msg_flags = mail_flags_new(driver_flags, ext); + + * result = msg_info->msg_flags; + + return MAIL_NO_ERROR; +} diff --git a/Sources/libetpan/driver/implementation/maildir/maildirdriver_message.h b/Sources/libetpan/driver/implementation/maildir/maildirdriver_message.h new file mode 100644 index 00000000..f5e35ecb --- /dev/null +++ b/Sources/libetpan/driver/implementation/maildir/maildirdriver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver_message.h,v 1.3 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MAILDIRDRIVER_MESSAGE_H + +#define MAILDIRDRIVER_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * maildir_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/maildir/maildirdriver_tools.c b/Sources/libetpan/driver/implementation/maildir/maildirdriver_tools.c new file mode 100644 index 00000000..4bff8db4 --- /dev/null +++ b/Sources/libetpan/driver/implementation/maildir/maildirdriver_tools.c @@ -0,0 +1,202 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver_tools.c,v 1.7 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailmessage.h" +#include "maildirdriver_tools.h" +#include "maildir.h" +#include "generic_cache.h" +#include +#include +#include +#include + +int maildirdriver_maildir_error_to_mail_error(int error) +{ + switch (error) { + case MAILDIR_NO_ERROR: + return MAIL_NO_ERROR; + + case MAILDIR_ERROR_CREATE: + return MAIL_ERROR_FILE; + + case MAILDIR_ERROR_DIRECTORY: + return MAIL_ERROR_FILE; + + case MAILDIR_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case MAILDIR_ERROR_FILE: + return MAIL_ERROR_FILE; + + case MAILDIR_ERROR_FOLDER: + return MAIL_ERROR_FOLDER; + + case MAILDIR_ERROR_NOT_FOUND: + return MAIL_ERROR_MSG_NOT_FOUND; + + default: + return MAIL_ERROR_INVAL; + } +} + + + +uint32_t maildirdriver_maildir_flags_to_flags(uint32_t md_flags) +{ + uint32_t flags; + + flags = 0; + if ((md_flags & MAILDIR_FLAG_NEW) != 0) + flags |= MAIL_FLAG_NEW; + + if ((md_flags & MAILDIR_FLAG_SEEN) != 0) + flags |= MAIL_FLAG_SEEN; + + if ((md_flags & MAILDIR_FLAG_REPLIED) != 0) + flags |= MAIL_FLAG_ANSWERED; + + if ((md_flags & MAILDIR_FLAG_FLAGGED) != 0) + flags |= MAIL_FLAG_FLAGGED; + + if ((md_flags & MAILDIR_FLAG_TRASHED) != 0) + flags |= MAIL_FLAG_DELETED; + + return flags; +} + +uint32_t maildirdriver_flags_to_maildir_flags(uint32_t flags) +{ + uint32_t md_flags; + + md_flags = 0; + if ((flags & MAIL_FLAG_NEW) != 0) + md_flags |= MAILDIR_FLAG_NEW; + + if ((flags & MAIL_FLAG_SEEN) != 0) + md_flags |= MAILDIR_FLAG_SEEN; + + if ((flags & MAIL_FLAG_ANSWERED) != 0) + md_flags |= MAILDIR_FLAG_REPLIED; + + if ((flags & MAIL_FLAG_FLAGGED) != 0) + md_flags |= MAILDIR_FLAG_FLAGGED; + + if ((flags & MAIL_FLAG_DELETED) != 0) + md_flags |= MAILDIR_FLAG_TRASHED; + + return md_flags; +} + + +int maildir_get_messages_list(mailsession * session, struct maildir * md, + mailmessage_driver * message_driver, + struct mailmessage_list ** result) +{ + unsigned int i; + struct mailmessage_list * env_list; + int r; + carray * tab; + int res; + + tab = carray_new(128); + if (tab == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < carray_count(md->mdir_msg_list) ; i++) { + struct maildir_msg * md_msg; + mailmessage * msg; + char * filename; + struct stat stat_info; + + md_msg = carray_get(md->mdir_msg_list, i); + + filename = maildir_message_get(md, md_msg->msg_uid); + r = stat(filename, &stat_info); + free(filename); + if (r < 0) + continue; + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = mailmessage_init(msg, session, message_driver, + i + 1, stat_info.st_size); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg); + res = r; + goto free_list; + } + + msg->msg_uid = strdup(md_msg->msg_uid); + if (msg->msg_uid == NULL) { + mailmessage_free(msg); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = carray_add(tab, msg, NULL); + if (r < 0) { + mailmessage_free(msg); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + env_list = mailmessage_list_new(tab); + if (env_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = env_list; + + return MAIL_NO_ERROR; + + free_list: + for(i = 0 ; i < carray_count(tab) ; i ++) + mailmessage_free(carray_get(tab, i)); + carray_free(tab); + err: + return res; +} diff --git a/Sources/libetpan/driver/implementation/maildir/maildirdriver_tools.h b/Sources/libetpan/driver/implementation/maildir/maildirdriver_tools.h new file mode 100644 index 00000000..29200146 --- /dev/null +++ b/Sources/libetpan/driver/implementation/maildir/maildirdriver_tools.h @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver_tools.h,v 1.3 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MAILDIRDRIVER_TOOLS_H + +#define MAILDIRDRIVER_TOOLS_H + +#include "maildriver_types.h" +#include "maildir.h" + +int maildirdriver_maildir_error_to_mail_error(int error); + +uint32_t maildirdriver_maildir_flags_to_flags(uint32_t md_flags); + +uint32_t maildirdriver_flags_to_maildir_flags(uint32_t flags); + +int maildir_get_messages_list(mailsession * session, struct maildir * md, + mailmessage_driver * message_driver, + struct mailmessage_list ** result); + +#endif diff --git a/Sources/libetpan/driver/implementation/maildir/maildirdriver_types.h b/Sources/libetpan/driver/implementation/maildir/maildirdriver_types.h new file mode 100644 index 00000000..b51ce2f0 --- /dev/null +++ b/Sources/libetpan/driver/implementation/maildir/maildirdriver_types.h @@ -0,0 +1,96 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver_types.h,v 1.6 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifndef MAILDIRDRIVER_TYPES_H + +#define MAILDIRDRIVER_TYPES_H + +#include + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct maildir_session_state_data { + struct maildir * md_session; + struct mail_flags_store * md_flags_store; +}; + +enum { + MAILDIRDRIVER_CACHED_SET_CACHE_DIRECTORY = 1, + MAILDIRDRIVER_CACHED_SET_FLAGS_DIRECTORY +}; + +struct maildir_cached_session_state_data { + mailsession * md_ancestor; + char * md_quoted_mb; + struct mail_flags_store * md_flags_store; + char md_cache_directory[PATH_MAX]; + char md_flags_directory[PATH_MAX]; +}; + +/* maildir storage */ + +/* + maildir_mailstorage is the state data specific to the maildir storage. + + - pathname is the path of the maildir storage. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache. + + - flags_directory is the location of the flags. +*/ + +struct maildir_mailstorage { + char * md_pathname; + + int md_cached; + char * md_cache_directory; + char * md_flags_directory; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/maildir/maildirstorage.c b/Sources/libetpan/driver/implementation/maildir/maildirstorage.c new file mode 100644 index 00000000..ba8714de --- /dev/null +++ b/Sources/libetpan/driver/implementation/maildir/maildirstorage.c @@ -0,0 +1,198 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirstorage.c,v 1.11 2008/02/17 13:13:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "maildirstorage.h" +#include "mailstorage.h" + +#include "mail.h" +#include "mailmessage.h" +#include "maildirdriver.h" +#include "maildirdriver_cached.h" +#include "maildriver.h" + +#include +#include + +/* maildir storage */ + +static int maildir_mailstorage_connect(struct mailstorage * storage); +static int +maildir_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result); +static void maildir_mailstorage_uninitialize(struct mailstorage * storage); + +static mailstorage_driver maildir_mailstorage_driver = { + /* sto_name */ "maildir", + /* sto_connect */ maildir_mailstorage_connect, + /* sto_get_folder_session */ maildir_mailstorage_get_folder_session, + /* sto_uninitialize */ maildir_mailstorage_uninitialize +}; + +LIBETPAN_EXPORT +int maildir_mailstorage_init(struct mailstorage * storage, + const char * md_pathname, int md_cached, + const char * md_cache_directory, const char * md_flags_directory) +{ + struct maildir_mailstorage * maildir_storage; + + maildir_storage = malloc(sizeof(* maildir_storage)); + if (maildir_storage == NULL) + goto err; + + maildir_storage->md_pathname = strdup(md_pathname); + if (maildir_storage->md_pathname == NULL) + goto free; + + maildir_storage->md_cached = md_cached; + + if (md_cached && (md_cache_directory != NULL) && + (md_flags_directory != NULL)) { + maildir_storage->md_cache_directory = strdup(md_cache_directory); + if (maildir_storage->md_cache_directory == NULL) + goto free_pathname; + + maildir_storage->md_flags_directory = strdup(md_flags_directory); + if (maildir_storage->md_flags_directory == NULL) + goto free_cache_directory; + } + else { + maildir_storage->md_cached = FALSE; + maildir_storage->md_cache_directory = NULL; + maildir_storage->md_flags_directory = NULL; + } + + storage->sto_data = maildir_storage; + storage->sto_driver = &maildir_mailstorage_driver; + + return MAIL_NO_ERROR; + + free_cache_directory: + free(maildir_storage->md_cache_directory); + free_pathname: + free(maildir_storage->md_pathname); + free: + free(maildir_storage); + err: + return MAIL_ERROR_MEMORY; +} + +static void maildir_mailstorage_uninitialize(struct mailstorage * storage) +{ + struct maildir_mailstorage * maildir_storage; + + maildir_storage = storage->sto_data; + if (maildir_storage->md_flags_directory != NULL) + free(maildir_storage->md_flags_directory); + if (maildir_storage->md_cache_directory != NULL) + free(maildir_storage->md_cache_directory); + free(maildir_storage->md_pathname); + free(maildir_storage); + + storage->sto_data = NULL; +} + +static int maildir_mailstorage_connect(struct mailstorage * storage) +{ + struct maildir_mailstorage * maildir_storage; + mailsession_driver * driver; + int r; + int res; + mailsession * session; + + maildir_storage = storage->sto_data; + + if (maildir_storage->md_cached) + driver = maildir_cached_session_driver; + else + driver = maildir_session_driver; + + session = mailsession_new(driver); + if (session == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if (maildir_storage->md_cached) { + r = mailsession_parameters(session, + MAILDIRDRIVER_CACHED_SET_CACHE_DIRECTORY, + maildir_storage->md_cache_directory); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + r = mailsession_parameters(session, + MAILDIRDRIVER_CACHED_SET_FLAGS_DIRECTORY, + maildir_storage->md_flags_directory); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + } + + r = mailsession_connect_path(session, maildir_storage->md_pathname); + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto free; + } + + storage->sto_session = session; + + return MAIL_NO_ERROR; + + free: + mailsession_free(session); + err: + return res; +} + +static int +maildir_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result) +{ + * result = storage->sto_session; + + return MAIL_NO_ERROR; +} + diff --git a/Sources/libetpan/driver/implementation/maildir/maildirstorage.h b/Sources/libetpan/driver/implementation/maildir/maildirstorage.h new file mode 100644 index 00000000..651872bf --- /dev/null +++ b/Sources/libetpan/driver/implementation/maildir/maildirstorage.h @@ -0,0 +1,70 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirstorage.h,v 1.7 2006/06/02 15:44:29 smarinier Exp $ + */ + +#ifndef MAILDIRSTORAGE_H + +#define MAILDIRSTORAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + maildir_mailstorage_init is the constructor for a maildir storage. + + @param storage this is the storage to initialize. + + @param pathname is the directory that contains the mailbox. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache + + @param flags_directory is the location of the flags +*/ + +LIBETPAN_EXPORT +int maildir_mailstorage_init(struct mailstorage * storage, + const char * md_pathname, int md_cached, + const char * md_cache_directory, const char * md_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/mbox/Makefile.am b/Sources/libetpan/driver/implementation/mbox/Makefile.am new file mode 100644 index 00000000..956324c6 --- /dev/null +++ b/Sources/libetpan/driver/implementation/mbox/Makefile.am @@ -0,0 +1,56 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +etpaninclude_HEADERS = \ + mboxdriver.h \ + mboxdriver_cached.h \ + mboxdriver_cached_message.h \ + mboxdriver_message.h \ + mboxdriver_types.h \ + mboxstorage.h + +AM_CPPFLAGS = -I$(top_builddir)/include \ + -I$(top_srcdir)/src/driver/interface \ + -I$(top_srcdir)/src/driver/tools \ + -I$(top_srcdir)/src/low-level/mbox \ + -I$(top_srcdir)/src/low-level/mime \ + -I$(top_srcdir)/src/low-level/imf \ + -I$(top_srcdir)/src/data-types + +noinst_LTLIBRARIES = libmbox.la + +libmbox_la_SOURCES = \ + mboxdriver.c \ + mboxdriver_cached.c \ + mboxdriver_cached_message.c \ + mboxdriver_message.c \ + mboxdriver_tools.h mboxdriver_tools.c \ + mboxstorage.c diff --git a/Sources/libetpan/driver/implementation/mbox/mboxdriver.c b/Sources/libetpan/driver/implementation/mbox/mboxdriver.c new file mode 100644 index 00000000..7c985d44 --- /dev/null +++ b/Sources/libetpan/driver/implementation/mbox/mboxdriver.c @@ -0,0 +1,527 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver.c,v 1.45 2008/02/17 13:13:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mboxdriver.h" + +#include +#include +#include +#ifdef WIN32 +# include "win_etpan.h" +#else +# include +# include +#endif +#include +#include +#include +#ifndef WIN32 +#include +#endif + +#include "mail.h" +#include "maildriver_tools.h" +#include "mailmbox.h" +#include "mboxdriver_tools.h" +#include "maildriver.h" +#include "carray.h" +#include "mboxdriver_message.h" +#include "mailmessage.h" + +static int mboxdriver_initialize(mailsession * session); + +static void mboxdriver_uninitialize(mailsession * session); + +static int mboxdriver_parameters(mailsession * session, + int id, void * value); + +static int mboxdriver_connect_path(mailsession * session, const char * path); + +static int mboxdriver_logout(mailsession * session); + +static int mboxdriver_expunge_folder(mailsession * session); + +static int mboxdriver_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int mboxdriver_messages_number(mailsession * session, const char * mb, + uint32_t * result); + +static int mboxdriver_append_message(mailsession * session, + const char * message, size_t size); + +static int mboxdriver_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); + +static int mboxdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int +mboxdriver_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +static int mboxdriver_remove_message(mailsession * session, uint32_t num); + +static int mboxdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int mboxdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static mailsession_driver local_mbox_session_driver = { + /* sess_name */ "mbox", + + /* sess_initialize */ mboxdriver_initialize, + /* sess_uninitialize */ mboxdriver_uninitialize, + + /* sess_parameters */ mboxdriver_parameters, + + /* sess_connect_stream */ NULL, + + /* sess_connect_path */ mboxdriver_connect_path, + /* sess_starttls */ NULL, + /* sess_login */ NULL, + /* sess_logout */ mboxdriver_logout, + /* sess_noop */ NULL, + + /* sess_build_folder_name */ NULL, + /* sess_create_folder */ NULL, + /* sess_delete_folder */ NULL, + /* sess_rename_folder */ NULL, + /* sess_check_folder */ NULL, + /* sess_examine_folder */ NULL, + /* sess_select_folder */ NULL, + /* sess_expunge_folder */ mboxdriver_expunge_folder, + /* sess_status_folder */ mboxdriver_status_folder, + /* sess_messages_number */ mboxdriver_messages_number, + /* sess_recent_number */ mboxdriver_messages_number, + /* sess_unseen_number */ mboxdriver_messages_number, + /* sess_list_folders */ NULL, + /* sess_lsub_folders */ NULL, + /* sess_subscribe_folder */ NULL, + /* sess_unsubscribe_folder */ NULL, + + /* sess_append_message */ mboxdriver_append_message, + /* sess_append_message_flags */ mboxdriver_append_message_flags, + /* sess_copy_message */ NULL, + /* sess_move_message */ NULL, + + /* sess_get_message */ mboxdriver_get_message, + /* sess_get_message_by_uid */ mboxdriver_get_message_by_uid, + + /* sess_get_messages_list */ mboxdriver_get_messages_list, + /* sess_get_envelopes_list */ mboxdriver_get_envelopes_list, + /* sess_remove_message */ mboxdriver_remove_message, +#if 0 + /* sess_search_messages */ maildriver_generic_search_messages, +#endif + /* sess_login_sasl */ NULL +}; + +mailsession_driver * mbox_session_driver = &local_mbox_session_driver; + +static inline struct mbox_session_state_data * get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline struct mailmbox_folder * get_mbox_session(mailsession * session) +{ + return get_data(session)->mbox_folder; +} + +static int mboxdriver_initialize(mailsession * session) +{ + struct mbox_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->mbox_folder = NULL; + + data->mbox_force_read_only = FALSE; + data->mbox_force_no_uid = TRUE; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + err: + return MAIL_ERROR_MEMORY; +} + +static void free_state(struct mbox_session_state_data * mbox_data) +{ + if (mbox_data->mbox_folder != NULL) { + mailmbox_done(mbox_data->mbox_folder); + mbox_data->mbox_folder = NULL; + } +} + +static void mboxdriver_uninitialize(mailsession * session) +{ + struct mbox_session_state_data * data; + + data = get_data(session); + + free_state(data); + + free(data); +} + +static int mboxdriver_parameters(mailsession * session, + int id, void * value) +{ + struct mbox_session_state_data * data; + + data = get_data(session); + + switch (id) { + case MBOXDRIVER_SET_READ_ONLY: + { + int * param; + + param = value; + + data->mbox_force_read_only = * param; + return MAIL_NO_ERROR; + } + + case MBOXDRIVER_SET_NO_UID: + { + int * param; + + param = value; + + data->mbox_force_no_uid = * param; + return MAIL_NO_ERROR; + } + } + + return MAIL_ERROR_INVAL; +} + + +static int mboxdriver_connect_path(mailsession * session, const char * path) +{ + struct mbox_session_state_data * mbox_data; + struct mailmbox_folder * folder; + int r; + + mbox_data = get_data(session); + + if (mbox_data->mbox_folder != NULL) + return MAIL_ERROR_BAD_STATE; + + r = mailmbox_init(path, + mbox_data->mbox_force_read_only, + mbox_data->mbox_force_no_uid, + 0, + &folder); + + if (r != MAILMBOX_NO_ERROR) + return mboxdriver_mbox_error_to_mail_error(r); + + mbox_data->mbox_folder = folder; + + return MAIL_NO_ERROR; +} + +static int mboxdriver_logout(mailsession * session) +{ + struct mbox_session_state_data * mbox_data; + + mbox_data = get_data(session); + + if (mbox_data->mbox_folder == NULL) + return MAIL_ERROR_BAD_STATE; + + free_state(mbox_data); + + mbox_data->mbox_folder = NULL; + + return MAIL_NO_ERROR; +} + +static int mboxdriver_expunge_folder(mailsession * session) +{ + int r; + struct mbox_session_state_data * mbox_data; + + mbox_data = get_data(session); + + if (mbox_data->mbox_folder == NULL) + return MAIL_ERROR_BAD_STATE; + + r = mailmbox_expunge(mbox_data->mbox_folder); + if (r != MAILMBOX_NO_ERROR) + return mboxdriver_mbox_error_to_mail_error(r); + + return MAIL_NO_ERROR; +} + +static int mboxdriver_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + uint32_t count; + int r; + + r = mboxdriver_messages_number(session, mb, &count); + if (r != MAIL_NO_ERROR) + return r; + + * result_messages = count; + * result_recent = count; + * result_unseen = count; + + return MAIL_NO_ERROR; +} + +static int mboxdriver_messages_number(mailsession * session, const char * mb, + uint32_t * result) +{ + struct mailmbox_folder * folder; + int r; + + folder = get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_STATUS; + + r = mailmbox_validate_read_lock(folder); + if (r != MAIL_NO_ERROR) + return r; + + mailmbox_read_unlock(folder); + + * result = carray_count(folder->mb_tab) - folder->mb_deleted_count; + + return MAILMBOX_NO_ERROR; +} + +/* messages operations */ + +static int mboxdriver_append_message(mailsession * session, + const char * message, size_t size) +{ + int r; + struct mailmbox_folder * folder; + + folder = get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_APPEND; + + r = mailmbox_append_message(folder, message, size); + + switch (r) { + case MAILMBOX_ERROR_FILE: + return MAIL_ERROR_DISKSPACE; + default: + return mboxdriver_mbox_error_to_mail_error(r); + } +} + +static int mboxdriver_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags) +{ + return mboxdriver_append_message(session, message, size); +} + +static int mboxdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + struct mailmbox_folder * folder; + int res; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + return mbox_get_messages_list(folder, session, mbox_message_driver, result); + + err: + return res; +} + +static int +mboxdriver_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + struct mailmbox_folder * folder; + unsigned int i; + int r; + int res; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + r = mailmbox_validate_read_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = mboxdriver_mbox_error_to_mail_error(r); + goto err; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailimf_fields * fields; + char * headers; + size_t headers_len; + size_t cur_token; + + msg = carray_get(env_list->msg_tab, i); + if (msg == NULL) + continue; + + if (msg->msg_fields != NULL) + continue; + + r = mailmbox_fetch_msg_headers_no_lock(folder, + msg->msg_index, &headers, &headers_len); + if (r != MAILMBOX_NO_ERROR) { + res = mboxdriver_mbox_error_to_mail_error(r); + goto unlock; + } + + cur_token = 0; + r = mailimf_envelope_fields_parse(headers, headers_len, + &cur_token, &fields); + + if (r != MAILIMF_NO_ERROR) + continue; + + msg->msg_fields = fields; + } + + mailmbox_read_unlock(folder); + + return MAIL_NO_ERROR; + + unlock: + mailmbox_read_unlock(folder); + err: + return res; +} + + +static int mboxdriver_remove_message(mailsession * session, uint32_t num) +{ + int r; + struct mailmbox_folder * folder; + + folder = get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_DELETE; + + r = mailmbox_delete_msg(folder, num); + + return mboxdriver_mbox_error_to_mail_error(r); +} + +static int mboxdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, mbox_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int mboxdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t num; + char * p; + chashdatum key; + chashdatum data; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + int r; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + num = (uint32_t) strtoul(uid, &p, 10); + if (p == uid || * p != '-') + return MAIL_ERROR_INVAL; + + folder = get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_BAD_STATE; + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r == 0) { + char * body_len_p = p + 1; + size_t body_len; + + info = data.data; + /* Check if the cached message has the same UID */ + body_len = strtoul(body_len_p, &p, 10); + if (p == body_len_p || * p != '\0') + return MAIL_ERROR_INVAL; + + if (body_len == info->msg_body_len) + return mboxdriver_get_message(session, num, result); + } + + return MAIL_ERROR_MSG_NOT_FOUND; +} diff --git a/Sources/libetpan/driver/implementation/mbox/mboxdriver.h b/Sources/libetpan/driver/implementation/mbox/mboxdriver.h new file mode 100644 index 00000000..150e1d1b --- /dev/null +++ b/Sources/libetpan/driver/implementation/mbox/mboxdriver.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver.h,v 1.14 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MBOXDRIVER_H + +#define MBOXDRIVER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +extern mailsession_driver * mbox_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/mbox/mboxdriver_cached.c b/Sources/libetpan/driver/implementation/mbox/mboxdriver_cached.c new file mode 100644 index 00000000..31eb842d --- /dev/null +++ b/Sources/libetpan/driver/implementation/mbox/mboxdriver_cached.c @@ -0,0 +1,1350 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver_cached.c,v 1.58 2010/04/05 14:43:48 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mboxdriver_cached.h" + +#include +#include +#ifdef WIN32 +# include "win_etpan.h" +#else +# include +# include +#endif +#include +#include +#include +#include +#include + +#include "mail.h" +#include "mail_cache_db.h" +#include "mboxdriver.h" +#include "mboxdriver_tools.h" +#include "maildriver_tools.h" +#include "mailmbox.h" +#include "maildriver.h" +#include "carray.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "mboxdriver_cached_message.h" +#include "libetpan-config.h" + +static int mboxdriver_cached_initialize(mailsession * session); + +static void mboxdriver_cached_uninitialize(mailsession * session); + +static int mboxdriver_cached_parameters(mailsession * session, + int id, void * value); + +static int mboxdriver_cached_connect_path(mailsession * session, const char * path); + +static int mboxdriver_cached_logout(mailsession * session); + +static int mboxdriver_cached_check_folder(mailsession * session); + +static int mboxdriver_cached_expunge_folder(mailsession * session); + +static int mboxdriver_cached_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); +static int mboxdriver_cached_messages_number(mailsession * session, const char * mb, + uint32_t * result); +static int mboxdriver_cached_recent_number(mailsession * session, const char * mb, + uint32_t * result); +static int mboxdriver_cached_unseen_number(mailsession * session, const char * mb, + uint32_t * result); + +static int mboxdriver_cached_append_message(mailsession * session, + const char * message, size_t size); + +static int mboxdriver_cached_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); + +static int +mboxdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int +mboxdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +static int mboxdriver_cached_remove_message(mailsession * session, + uint32_t num); + +static int mboxdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int mboxdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static mailsession_driver local_mbox_cached_session_driver = { + /* sess_name */ "mbox-cached", + + /* sess_initialize */ mboxdriver_cached_initialize, + /* sess_uninitialize */ mboxdriver_cached_uninitialize, + + /* sess_parameters */ mboxdriver_cached_parameters, + + /* sess_connect_stream */ NULL, + /* sess_connect_path */ mboxdriver_cached_connect_path, + /* sess_starttls */ NULL, + /* sess_login */ NULL, + /* sess_logout */ mboxdriver_cached_logout, + /* sess_noop */ NULL, + + /* sess_build_folder_name */ NULL, + /* sess_create_folder */ NULL, + /* sess_delete_folder */ NULL, + /* sess_rename_folder */ NULL, + /* sess_check_folder */ mboxdriver_cached_check_folder, + /* sess_examine_folder */ NULL, + /* sess_select_folder */ NULL, + /* sess_expunge_folder */ mboxdriver_cached_expunge_folder, + /* sess_status_folder */ mboxdriver_cached_status_folder, + /* sess_messages_number */ mboxdriver_cached_messages_number, + /* sess_recent_number */ mboxdriver_cached_recent_number, + /* sess_unseen_number */ mboxdriver_cached_unseen_number, + /* sess_list_folders */ NULL, + /* sess_lsub_folders */ NULL, + /* sess_subscribe_folder */ NULL, + /* sess_unsubscribe_folder */ NULL, + + /* sess_append_message */ mboxdriver_cached_append_message, + /* sess_append_message_flags */ mboxdriver_cached_append_message_flags, + + /* sess_copy_message */ NULL, + /* sess_move_message */ NULL, + + /* sess_get_message */ mboxdriver_cached_get_message, + /* sess_get_message_by_uid */ mboxdriver_cached_get_message_by_uid, + + /* sess_get_messages_list */ mboxdriver_cached_get_messages_list, + /* sess_get_envelopes_list */ mboxdriver_cached_get_envelopes_list, + /* sess_remove_message */ mboxdriver_cached_remove_message, +#if 0 + /* sess_search_messages */ maildriver_generic_search_messages, +#endif + /* sess_login_sasl */ NULL +}; + +mailsession_driver * mbox_cached_session_driver = +&local_mbox_cached_session_driver; + + +#define ENV_NAME "env.db" +#define FLAGS_NAME "flags.db" + + + +static int mbox_error_to_mail_error(int error) +{ + switch (error) { + case MAILMBOX_NO_ERROR: + return MAIL_NO_ERROR; + + case MAILMBOX_ERROR_PARSE: + return MAIL_ERROR_PARSE; + + case MAILMBOX_ERROR_INVAL: + return MAIL_ERROR_INVAL; + + case MAILMBOX_ERROR_FILE_NOT_FOUND: + return MAIL_ERROR_PARSE; + + case MAILMBOX_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case MAILMBOX_ERROR_TEMPORARY_FILE: + return MAIL_ERROR_PARSE; + + case MAILMBOX_ERROR_FILE: + return MAIL_ERROR_FILE; + + case MAILMBOX_ERROR_MSG_NOT_FOUND: + return MAIL_ERROR_MSG_NOT_FOUND; + + case MAILMBOX_ERROR_READONLY: + return MAIL_ERROR_READONLY; + + default: + return MAIL_ERROR_INVAL; + } +} + + + + +static inline struct mbox_cached_session_state_data * +get_cached_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * get_ancestor(mailsession * session) +{ + return get_cached_data(session)->mbox_ancestor; +} + +static inline struct mbox_session_state_data * +get_ancestor_data(mailsession * session) +{ + return get_ancestor(session)->sess_data; +} + +static inline struct mailmbox_folder * +get_mbox_session(mailsession * session) +{ + return get_ancestor_data(session)->mbox_folder; +} + +static int mboxdriver_cached_initialize(mailsession * session) +{ + struct mbox_cached_session_state_data * cached_data; + struct mbox_session_state_data * mbox_data; + + cached_data = malloc(sizeof(* cached_data)); + if (cached_data == NULL) + goto err; + + cached_data->mbox_flags_store = mail_flags_store_new(); + if (cached_data->mbox_flags_store == NULL) + goto free; + + cached_data->mbox_ancestor = mailsession_new(mbox_session_driver); + if (cached_data->mbox_ancestor == NULL) + goto free_store; + + cached_data->mbox_quoted_mb = NULL; + /* + UID must be enabled to take advantage of the cache + */ + mbox_data = cached_data->mbox_ancestor->sess_data; + mbox_data->mbox_force_no_uid = FALSE; + + session->sess_data = cached_data; + + return MAIL_NO_ERROR; + + free_store: + mail_flags_store_free(cached_data->mbox_flags_store); + free: + free(cached_data); + err: + return MAIL_ERROR_MEMORY; +} + +static void free_state(struct mbox_cached_session_state_data * mbox_data) +{ + if (mbox_data->mbox_quoted_mb) { + free(mbox_data->mbox_quoted_mb); + mbox_data->mbox_quoted_mb = NULL; + } +} + +static int mbox_flags_store_process(char * flags_directory, char * quoted_mb, + struct mail_flags_store * flags_store) +{ + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + unsigned int i; + int r; + int res; + + if (carray_count(flags_store->fls_tab) == 0) + return MAIL_NO_ERROR; + + if (quoted_mb == NULL) + return MAIL_NO_ERROR; + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + flags_directory, MAIL_DIR_SEPARATOR, quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(flags_store->fls_tab, i); + + r = mboxdriver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + if (r != MAIL_NO_ERROR) { + /* ignore errors */ + } + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + mail_flags_store_clear(flags_store); + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static void mboxdriver_cached_uninitialize(mailsession * session) +{ + struct mbox_cached_session_state_data * data; + + data = get_cached_data(session); + + mbox_flags_store_process(data->mbox_flags_directory, + data->mbox_quoted_mb, + data->mbox_flags_store); + + mail_flags_store_free(data->mbox_flags_store); + + free_state(data); + mailsession_free(data->mbox_ancestor); + free(data); + + session->sess_data = NULL; +} + +static int mboxdriver_cached_parameters(mailsession * session, + int id, void * value) +{ + struct mbox_cached_session_state_data * data; + int r; + + data = get_cached_data(session); + + switch (id) { + case MBOXDRIVER_CACHED_SET_CACHE_DIRECTORY: + strncpy(data->mbox_cache_directory, value, PATH_MAX); + data->mbox_cache_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(data->mbox_cache_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + case MBOXDRIVER_CACHED_SET_FLAGS_DIRECTORY: + strncpy(data->mbox_flags_directory, value, PATH_MAX); + data->mbox_flags_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(data->mbox_flags_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + case MBOXDRIVER_SET_NO_UID: + return MAIL_ERROR_INVAL; + + default: + return mailsession_parameters(data->mbox_ancestor, id, value); + } +} + + +static int get_cache_directory(mailsession * session, + const char * path, char ** result) +{ + char * quoted_mb; + char dirname[PATH_MAX]; + int res; + int r; + struct mbox_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + + quoted_mb = maildriver_quote_mailbox(path); + if (quoted_mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(dirname, PATH_MAX, "%s%c%s", + cached_data->mbox_cache_directory, MAIL_DIR_SEPARATOR, quoted_mb); + + r = generic_cache_create_dir(dirname); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + snprintf(dirname, PATH_MAX, "%s%c%s", + cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR, quoted_mb); + + r = generic_cache_create_dir(dirname); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + * result = quoted_mb; + + return MAIL_NO_ERROR; + + free: + free(quoted_mb); + err: + return res; +} + + + + +#define FILENAME_MAX_UID "max-uid" + +/* write max uid current value */ + +static int write_max_uid_value(mailsession * session) +{ + int r; + char filename[PATH_MAX]; + FILE * f; + int res; + +#if 0 + struct mbox_session_state_data * mbox_data; +#endif + struct mbox_cached_session_state_data * cached_data; + int fd; + + MMAPString * mmapstr; + size_t cur_token; + struct mailmbox_folder * folder; + + /* expunge the mailbox */ + +#if 0 + mbox_data = get_ancestor(session)->data; +#endif + folder = get_mbox_session(session); + + r = mailmbox_validate_write_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = mbox_error_to_mail_error(r); + goto err; + } + + r = mailmbox_expunge_no_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto unlock; + } + + cached_data = get_cached_data(session); + + snprintf(filename, PATH_MAX, "%s%c%s%c%s", + cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR, + cached_data->mbox_quoted_mb, MAIL_DIR_SEPARATOR, FILENAME_MAX_UID); + + fd = creat(filename, S_IRUSR | S_IWUSR); + if (fd < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + f = fdopen(fd, "w"); + if (f == NULL) { + close(fd); + res = MAIL_ERROR_FILE; + goto unlock; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close; + } + + r = mail_serialize_clear(mmapstr, &cur_token); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + r = mailimf_cache_int_write(mmapstr, &cur_token, + folder->mb_written_uid); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + r = (int) fwrite(mmapstr->str, 1, mmapstr->len, f); + if ((size_t) r != mmapstr->len) { + res = MAIL_ERROR_FILE; + goto free_mmapstr; + } + + mmap_string_free(mmapstr); + fclose(f); + mailmbox_write_unlock(folder); + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close: + fclose(f); + unlock: + mailmbox_read_unlock(folder); + err: + return res; +} + +static int read_max_uid_value(mailsession * session, uint32_t * result) +{ + int r; + char filename[PATH_MAX]; + FILE * f; + uint32_t written_uid; + int res; + + struct mbox_cached_session_state_data * cached_data; + + MMAPString * mmapstr; + size_t cur_token; + char buf[sizeof(uint32_t)]; + size_t read_size; + + cached_data = get_cached_data(session); + + snprintf(filename, PATH_MAX, "%s%c%s%c%s", + cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR, + cached_data->mbox_quoted_mb, MAIL_DIR_SEPARATOR, FILENAME_MAX_UID); + + f = fopen(filename, "r"); + if (f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + read_size = fread(buf, 1, sizeof(uint32_t), f); + + mmapstr = mmap_string_new_len(buf, read_size); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close; + } + + cur_token = 0; + + r = mailimf_cache_int_read(mmapstr, &cur_token, &written_uid); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + mmap_string_free(mmapstr); + fclose(f); + + * result = written_uid; + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close: + fclose(f); + err: + return res; +} + +static int mboxdriver_cached_connect_path(mailsession * session, const char * path) +{ + int r; + int res; + char * quoted_mb; + struct mbox_cached_session_state_data * cached_data; + struct mbox_session_state_data * ancestor_data; + struct mailmbox_folder * folder; + uint32_t written_uid; + + folder = get_mbox_session(session); + if (folder != NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + quoted_mb = NULL; + r = get_cache_directory(session, path, "ed_mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + cached_data = get_cached_data(session); + free_state(cached_data); + + cached_data->mbox_quoted_mb = quoted_mb; + + written_uid = 0; + r = read_max_uid_value(session, &written_uid); + /* ignore errors */ + + ancestor_data = get_ancestor_data(session); + + r = mailmbox_init(path, + ancestor_data->mbox_force_read_only, + ancestor_data->mbox_force_no_uid, + written_uid, + &folder); + + if (r != MAILMBOX_NO_ERROR) { + cached_data->mbox_quoted_mb = NULL; + + res = mboxdriver_mbox_error_to_mail_error(r); + goto free; + } + + ancestor_data->mbox_folder = folder; + + return MAIL_NO_ERROR; + + free: + free(quoted_mb); + err: + return res; +} + + +static int mboxdriver_cached_logout(mailsession * session) +{ + struct mbox_cached_session_state_data * cached_data; + int r; + + r = write_max_uid_value(session); + if (r != MAIL_NO_ERROR) + return r; + + cached_data = get_cached_data(session); + + mbox_flags_store_process(cached_data->mbox_flags_directory, + cached_data->mbox_quoted_mb, + cached_data->mbox_flags_store); + + r = mailsession_logout(get_ancestor(session)); + if (r != MAIL_NO_ERROR) + return r; + + free_state(cached_data); + + return MAIL_NO_ERROR; +} + +static int mboxdriver_cached_check_folder(mailsession * session) +{ + struct mbox_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + + mbox_flags_store_process(cached_data->mbox_flags_directory, + cached_data->mbox_quoted_mb, + cached_data->mbox_flags_store); + + return MAIL_NO_ERROR; +} + +static int mboxdriver_cached_expunge_folder(mailsession * session) +{ + struct mailmbox_folder * folder; + int res; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + struct mbox_cached_session_state_data * data; + int r; + unsigned int i; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + data = get_cached_data(session); + if (data->mbox_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mbox_flags_store_process(data->mbox_flags_directory, + data->mbox_quoted_mb, + data->mbox_flags_store); + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + data->mbox_flags_directory, MAIL_DIR_SEPARATOR, data->mbox_quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) { + struct mailmbox_msg_info * msg_info; + struct mail_flags * flags; + + msg_info = carray_get(folder->mb_tab, i); + if (msg_info == NULL) + continue; + + if (msg_info->msg_deleted) + continue; + + r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr, + session, msg_info->msg_uid, &flags); + if (r != MAIL_NO_ERROR) + continue; + + if (flags->fl_flags & MAIL_FLAG_DELETED) { + r = mailmbox_delete_msg(folder, msg_info->msg_uid); + } + + mail_flags_free(flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + return mailmbox_expunge(folder); + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int mboxdriver_cached_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + struct mailmbox_folder * folder; + int res; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + struct mbox_cached_session_state_data * data; + int r; + unsigned int i; + uint32_t recent; + uint32_t unseen; + uint32_t num; + + num = 0; + recent = 0; + unseen = 0; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + data = get_cached_data(session); + if (data->mbox_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + r = mailmbox_validate_read_lock(folder); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mailmbox_read_unlock(folder); + + mbox_flags_store_process(data->mbox_flags_directory, data->mbox_quoted_mb, + data->mbox_flags_store); + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + data->mbox_flags_directory, MAIL_DIR_SEPARATOR, data->mbox_quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) { + struct mailmbox_msg_info * msg_info; + struct mail_flags * flags; + + msg_info = carray_get(folder->mb_tab, i); + if (msg_info == NULL) + continue; + + if (msg_info->msg_deleted) + continue; + + r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr, + session, msg_info->msg_uid, &flags); + if (r != MAIL_NO_ERROR) { + recent ++; + unseen ++; + num ++; + continue; + } + + if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) { + recent ++; + } + if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) { + unseen ++; + } + + num ++; + + mail_flags_free(flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + * result_messages = num; + * result_recent = recent; + * result_unseen = unseen; + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int mboxdriver_cached_messages_number(mailsession * session, const char * mb, + uint32_t * result) +{ + return mailsession_messages_number(get_ancestor(session), mb, result); +} + + +static int mboxdriver_cached_recent_number(mailsession * session, const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = mboxdriver_cached_status_folder(session, mb, &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = recent; + + return MAIL_NO_ERROR; +} + +static int mboxdriver_cached_unseen_number(mailsession * session, const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = mboxdriver_cached_status_folder(session, mb, + &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = unseen; + + return MAIL_NO_ERROR; +} + +/* messages operations */ + +static int mboxdriver_cached_append_message(mailsession * session, + const char * message, size_t size) +{ + return mboxdriver_cached_append_message_flags(session, + message, size, NULL); +} + +static int mboxdriver_cached_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags) +{ + int r; + struct mailmbox_folder * folder; + struct mbox_cached_session_state_data * data; + unsigned int uid; + struct mailmbox_msg_info * msg_info; + chashdatum key; + chashdatum value; + struct mail_cache_db * cache_db_flags; + char filename_flags[PATH_MAX]; + MMAPString * mmapstr; + char keyname[PATH_MAX]; + + folder = get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_APPEND; + + r = mailmbox_append_message_uid(folder, message, size, &uid); + + switch (r) { + case MAILMBOX_ERROR_FILE: + return MAIL_ERROR_DISKSPACE; + case MAILMBOX_NO_ERROR: + break; + default: + return mboxdriver_mbox_error_to_mail_error(r); + } + + /* could store in flags store instead */ + + if (flags == NULL) + goto exit; + + key.data = &uid; + key.len = sizeof(uid); + r = chash_get(folder->mb_hash, &key, &value); + if (r < 0) + goto exit; + + msg_info = value.data; + + data = get_cached_data(session); + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + data->mbox_flags_directory, MAIL_DIR_SEPARATOR, data->mbox_quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) + goto exit; + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) + goto close_db_flags; + + snprintf(keyname, PATH_MAX, "%u-%lu", uid, + (unsigned long) msg_info->msg_body_len); + + r = mboxdriver_write_cached_flags(cache_db_flags, mmapstr, keyname, flags); + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + if (r != MAIL_NO_ERROR) + goto exit; + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + exit: + return MAIL_NO_ERROR; +} + +static int +mboxdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + struct mailmbox_folder * folder; + int res; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + return mbox_get_uid_messages_list(folder, + session, mbox_cached_message_driver, result); + + err: + return res; +} + +static int +get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mailimf_fields * fields; + int res; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + chashdatum key; + chashdatum data; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = data.data; + + snprintf(keyname, PATH_MAX, "%u-%lu-envelope", num, + (unsigned long) info->msg_body_len); + + r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = fields; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +write_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields * fields) +{ + int r; + char keyname[PATH_MAX]; + int res; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + chashdatum key; + chashdatum data; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = data.data; + + snprintf(keyname, PATH_MAX, "%u-%lu-envelope", num, + (unsigned long) info->msg_body_len); + + r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +mboxdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + unsigned int i; + struct mbox_cached_session_state_data * cached_data; + char filename_env[PATH_MAX]; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_env; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + int res; + struct mailmbox_folder * folder; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + cached_data = get_cached_data(session); + if (cached_data->mbox_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mbox_flags_store_process(cached_data->mbox_flags_directory, + cached_data->mbox_quoted_mb, + cached_data->mbox_flags_store); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(filename_env, PATH_MAX, "%s%c%s%c%s", + cached_data->mbox_cache_directory, MAIL_DIR_SEPARATOR, + cached_data->mbox_quoted_mb, + MAIL_DIR_SEPARATOR, ENV_NAME); + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto free_mmapstr; + } + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR, + cached_data->mbox_quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto close_db_env; + } + + /* fill with cached */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailimf_fields * fields; + struct mail_flags * flags; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + r = get_cached_envelope(cache_db_env, mmapstr, session, + msg->msg_index, &fields); + if (r == MAIL_NO_ERROR) { + msg->msg_cached = TRUE; + msg->msg_fields = fields; + } + } + + if (msg->msg_flags == NULL) { + r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr, + session, msg->msg_index, + &flags); + if (r == MAIL_NO_ERROR) { + msg->msg_flags = flags; + } + } + } + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + + r = mailsession_get_envelopes_list(get_ancestor(session), env_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + /* add flags */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_flags == NULL) + msg->msg_flags = mail_flags_new_empty(); + } + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto close_db_env; + } + + /* must write cache */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields != NULL) { + if (!msg->msg_cached) { + /* msg->msg_index is the numerical UID of the message */ + r = write_cached_envelope(cache_db_env, mmapstr, + session, msg->msg_index, msg->msg_fields); + } + } + + if (msg->msg_flags != NULL) { + r = mboxdriver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + } + } + + /* flush cache */ + + maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list); + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + + mmap_string_free(mmapstr); + + return MAIL_NO_ERROR; + + close_db_env: + mail_cache_db_close_unlock(filename_env, cache_db_env); + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + + +static int +mboxdriver_cached_remove_message(mailsession * session, uint32_t num) +{ + return mailsession_remove_message(get_ancestor(session), num); +} + +static int mboxdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, mbox_cached_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int mboxdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t num; + char * p; + chashdatum key; + chashdatum data; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + int r; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + num = (uint32_t) strtoul(uid, &p, 10); + if (p == uid || * p != '-') + return MAIL_ERROR_INVAL; + + folder = get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_BAD_STATE; + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r == 0) { + char * body_len_p = p + 1; + size_t body_len; + + info = data.data; + /* Check if the cached message has the same UID */ + body_len = strtoul(body_len_p, &p, 10); + if (p == body_len_p || * p != '\0') + return MAIL_ERROR_INVAL; + + if (body_len == info->msg_body_len) + return mboxdriver_cached_get_message(session, num, result); + } + + return MAIL_ERROR_MSG_NOT_FOUND; +} diff --git a/Sources/libetpan/driver/implementation/mbox/mboxdriver_cached.h b/Sources/libetpan/driver/implementation/mbox/mboxdriver_cached.h new file mode 100644 index 00000000..b1d724c5 --- /dev/null +++ b/Sources/libetpan/driver/implementation/mbox/mboxdriver_cached.h @@ -0,0 +1,54 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver_cached.h,v 1.11 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MBOXDRIVER_CACHED_H + +#define MBOXDRIVER_CACHED_H + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * mbox_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/mbox/mboxdriver_cached_message.c b/Sources/libetpan/driver/implementation/mbox/mboxdriver_cached_message.c new file mode 100644 index 00000000..b02878cc --- /dev/null +++ b/Sources/libetpan/driver/implementation/mbox/mboxdriver_cached_message.c @@ -0,0 +1,367 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver_cached_message.c,v 1.27 2008/02/17 13:13:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mboxdriver_cached_message.h" + +#include "mailmessage_tools.h" +#include "mboxdriver_tools.h" +#include "mboxdriver_cached.h" +#include "mboxdriver.h" +#include "mailmbox.h" +#include "mail_cache_db.h" +#include "generic_cache.h" + +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_SYS_MMAN_H +# include +#endif +#include +#include +#include +#include +#include + +static int mbox_prefetch(mailmessage * msg_info); + +static void mbox_prefetch_free(struct generic_message_t * msg); + +static int mbox_initialize(mailmessage * msg_info); + +static void mbox_uninitialize(mailmessage * msg_info); + +static void mbox_flush(mailmessage * msg_info); + +static void mbox_check(mailmessage * msg_info); + +static int mbox_fetch_size(mailmessage * msg_info, + size_t * result); + +static int mbox_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +static int mbox_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static mailmessage_driver local_mbox_cached_message_driver = { + /* msg_name */ "mbox-cached", + + /* msg_initialize */ mbox_initialize, + /* msg_uninitialize */ mbox_uninitialize, + + /* msg_flush */ mbox_flush, + /* msg_check */ mbox_check, + + /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free, + + /* msg_fetch */ mailmessage_generic_fetch, + /* msg_fetch_header */ mbox_fetch_header, + /* msg_fetch_body */ mailmessage_generic_fetch_body, + /* msg_fetch_size */ mbox_fetch_size, + /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure, + /* msg_fetch_section */ mailmessage_generic_fetch_section, + /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header, + /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime, + /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body, + /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope, + + /* msg_get_flags */ mbox_get_flags +}; + +mailmessage_driver * mbox_cached_message_driver = +&local_mbox_cached_message_driver; + +static inline struct mbox_cached_session_state_data * +get_cached_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline mailsession * get_ancestor_session(mailmessage * msg) +{ + return get_cached_session_data(msg)->mbox_ancestor; +} + +static inline struct mbox_session_state_data * +get_ancestor_session_data(mailmessage * msg) +{ + return get_ancestor_session(msg)->sess_data; +} + +static inline struct mailmbox_folder * +get_mbox_session(mailmessage * msg) +{ + return get_ancestor_session_data(msg)->mbox_folder; +} + +static int mbox_prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + r = mboxdriver_fetch_msg(get_ancestor_session(msg_info), + msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void mbox_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static int mbox_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + char static_uid[PATH_MAX]; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + int res; + chashdatum key; + chashdatum data; + + folder = get_mbox_session(msg_info); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + key.data = (char *) &msg_info->msg_index; + key.len = sizeof(msg_info->msg_index); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = (struct mailmbox_msg_info *) data.data; + + snprintf(static_uid, PATH_MAX, "%u-%lu", + msg_info->msg_index, (unsigned long) info->msg_body_len); + uid = strdup(static_uid); + if (uid == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + res = r; + goto err; + } + + msg = msg_info->msg_data; + + msg->msg_prefetch = mbox_prefetch; + msg->msg_prefetch_free = mbox_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static void mbox_uninitialize(mailmessage * msg_info) +{ + mailmessage_generic_uninitialize(msg_info); +} + +#define FLAGS_NAME "flags.db" + +static void mbox_flush(mailmessage * msg_info) +{ + mailmessage_generic_flush(msg_info); +} + +static void mbox_check(mailmessage * msg_info) +{ + if (msg_info->msg_flags != NULL) { + mail_flags_store_set(get_cached_session_data(msg_info)->mbox_flags_store, + msg_info); + /* ignore errors */ + } +} + + +static int mbox_fetch_size(mailmessage * msg_info, + size_t * result) +{ + int r; + size_t size; + + r = mboxdriver_fetch_size(get_ancestor_session(msg_info), + msg_info->msg_index, &size); + if (r != MAIL_NO_ERROR) + return r; + + * result = size; + + return MAIL_NO_ERROR; +} + +static int mbox_get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + int r; + struct mail_flags * flags; + struct mail_cache_db * cache_db_flags; + char filename_flags[PATH_MAX]; + int res; + struct mbox_cached_session_state_data * cached_data; + MMAPString * mmapstr; + struct mailmbox_folder * folder; + + if (msg_info->msg_flags != NULL) { + * result = msg_info->msg_flags; + + return MAIL_NO_ERROR; + } + + flags = mail_flags_store_get(get_cached_session_data(msg_info)->mbox_flags_store, + msg_info->msg_index); + + if (flags == NULL) { + folder = get_mbox_session(msg_info); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + cached_data = get_cached_session_data(msg_info); + if (cached_data->mbox_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->mbox_flags_directory, + cached_data->mbox_quoted_mb, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + if (msg_info->msg_index > folder->mb_written_uid) { + flags = mail_flags_new_empty(); + } + else { + r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr, + msg_info->msg_session, + msg_info->msg_index, &flags); + if (r != MAIL_NO_ERROR) { + flags = mail_flags_new_empty(); + if (flags == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + } + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + } + + msg_info->msg_flags = flags; + + * result = flags; + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int mbox_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + msg = msg_info->msg_data; + if (msg->msg_message != NULL) { + return mailmessage_generic_fetch_header(msg_info, result, result_len); + } + else { + r = mboxdriver_fetch_header(get_ancestor_session(msg_info), + msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; + } +} diff --git a/Sources/libetpan/driver/implementation/mbox/mboxdriver_cached_message.h b/Sources/libetpan/driver/implementation/mbox/mboxdriver_cached_message.h new file mode 100644 index 00000000..716247d2 --- /dev/null +++ b/Sources/libetpan/driver/implementation/mbox/mboxdriver_cached_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver_cached_message.h,v 1.6 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MBOXDRIVER_CACHED_MESSAGE_H + +#define MBOXDRIVER_CACHED_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * mbox_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/mbox/mboxdriver_message.c b/Sources/libetpan/driver/implementation/mbox/mboxdriver_message.c new file mode 100644 index 00000000..4c2d501f --- /dev/null +++ b/Sources/libetpan/driver/implementation/mbox/mboxdriver_message.c @@ -0,0 +1,233 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver_message.c,v 1.20 2008/02/17 13:13:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mboxdriver_message.h" + +#include "mailmessage_tools.h" +#include "mboxdriver_tools.h" +#include "mboxdriver.h" +#include "mailmbox.h" + +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_SYS_MMAN_H +# include +#endif +#include +#include +#include +#include +#include + +static int mbox_prefetch(mailmessage * msg_info); + +static void mbox_prefetch_free(struct generic_message_t * msg); + +static int mbox_initialize(mailmessage * msg_info); + +static int mbox_fetch_size(mailmessage * msg_info, + size_t * result); + +static int mbox_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static mailmessage_driver local_mbox_message_driver = { + /* msg_name */ "mbox", + + /* msg_initialize */ mbox_initialize, + /* msg_uninitialize */ mailmessage_generic_uninitialize, + + /* msg_flush */ mailmessage_generic_flush, + /* msg_check */ NULL, + + /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free, + + /* msg_fetch */ mailmessage_generic_fetch, + /* msg_fetch_header */ mbox_fetch_header, + /* msg_fetch_body */ mailmessage_generic_fetch_body, + /* msg_fetch_size */ mbox_fetch_size, + /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure, + /* msg_fetch_section */ mailmessage_generic_fetch_section, + /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header, + /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime, + /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body, + /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope, + + /* msg_get_flags */ NULL +}; + +mailmessage_driver * mbox_message_driver = &local_mbox_message_driver; + +static inline struct mbox_session_state_data * get_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline struct mailmbox_folder * get_mbox_session(mailmessage * msg) +{ + return get_data(msg)->mbox_folder; +} + + +static int mbox_prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + r = mboxdriver_fetch_msg(msg_info->msg_session, msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void mbox_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static int mbox_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + char static_uid[PATH_MAX]; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + int res; + chashdatum key; + chashdatum data; + + folder = get_mbox_session(msg_info); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + key.data = &msg_info->msg_index; + key.len = sizeof(msg_info->msg_index); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = data.data; + + snprintf(static_uid, PATH_MAX, "%u-%lu", + msg_info->msg_index, (unsigned long) info->msg_body_len); + uid = strdup(static_uid); + if (uid == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + res = r; + goto err; + } + + msg = msg_info->msg_data; + msg->msg_prefetch = mbox_prefetch; + msg->msg_prefetch_free = mbox_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int mbox_fetch_size(mailmessage * msg_info, + size_t * result) +{ + int r; + size_t size; + + r = mboxdriver_fetch_size(msg_info->msg_session, + msg_info->msg_index, &size); + if (r != MAIL_NO_ERROR) + return r; + + * result = size; + + return MAIL_NO_ERROR; +} + +static int mbox_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + msg = msg_info->msg_data; + if (msg->msg_message != NULL) { + return mailmessage_generic_fetch_header(msg_info, result, result_len); + } + else { + r = mboxdriver_fetch_header(msg_info->msg_session, msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; + } +} diff --git a/Sources/libetpan/driver/implementation/mbox/mboxdriver_message.h b/Sources/libetpan/driver/implementation/mbox/mboxdriver_message.h new file mode 100644 index 00000000..74bcbe59 --- /dev/null +++ b/Sources/libetpan/driver/implementation/mbox/mboxdriver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver_message.h,v 1.6 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MBOXDRIVER_MESSAGE_H + +#define MBOXDRIVER_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * mbox_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/mbox/mboxdriver_tools.c b/Sources/libetpan/driver/implementation/mbox/mboxdriver_tools.c new file mode 100644 index 00000000..e759c5d6 --- /dev/null +++ b/Sources/libetpan/driver/implementation/mbox/mboxdriver_tools.c @@ -0,0 +1,439 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver_tools.c,v 1.17 2008/02/20 22:15:50 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mboxdriver_tools.h" + +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif + +#include "maildriver_types.h" +#include "mailmbox.h" +#include "mboxdriver_cached.h" +#include "mboxdriver.h" +#include "generic_cache.h" +#include "mailmessage.h" +#include "imfcache.h" +#include "mail_cache_db.h" + +static inline struct mbox_session_state_data * +session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline struct mailmbox_folder * +session_get_mbox_session(mailsession * session) +{ + return session_get_data(session)->mbox_folder; +} + +static inline struct mbox_cached_session_state_data * +cached_session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * +cached_session_get_ancestor(mailsession * session) +{ + return cached_session_get_data(session)->mbox_ancestor; +} + +static inline struct mbox_session_state_data * +cached_session_get_ancestor_data(mailsession * session) +{ + return cached_session_get_ancestor(session)->sess_data; +} + +static inline struct mailmbox_folder * +cached_session_get_mbox_session(mailsession * session) +{ + return session_get_mbox_session(cached_session_get_ancestor(session)); +} + + +int mboxdriver_mbox_error_to_mail_error(int error) +{ + switch (error) { + case MAILMBOX_NO_ERROR: + return MAIL_NO_ERROR; + + case MAILMBOX_ERROR_PARSE: + return MAIL_ERROR_PARSE; + + case MAILMBOX_ERROR_INVAL: + return MAIL_ERROR_INVAL; + + case MAILMBOX_ERROR_FILE_NOT_FOUND: + return MAIL_ERROR_PARSE; + + case MAILMBOX_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case MAILMBOX_ERROR_TEMPORARY_FILE: + return MAIL_ERROR_PARSE; + + case MAILMBOX_ERROR_FILE: + return MAIL_ERROR_FILE; + + case MAILMBOX_ERROR_MSG_NOT_FOUND: + return MAIL_ERROR_MSG_NOT_FOUND; + + case MAILMBOX_ERROR_READONLY: + return MAIL_ERROR_READONLY; + + default: + return MAIL_ERROR_INVAL; + } +} + +int mboxdriver_fetch_msg(mailsession * session, uint32_t indx, + char ** result, size_t * result_len) +{ + int r; + char * msg_content; + size_t msg_length; + struct mailmbox_folder * folder; + + folder = session_get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_BAD_STATE; + + r = mailmbox_fetch_msg(folder, indx, &msg_content, &msg_length); + if (r != MAILMBOX_NO_ERROR) + return mboxdriver_mbox_error_to_mail_error(r); + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; +} + + +int mboxdriver_fetch_size(mailsession * session, uint32_t indx, + size_t * result) +{ + struct mailmbox_folder * folder; + int r; + char * data; + size_t len; + int res; + + folder = session_get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_FETCH; + goto err; + } + + r = mailmbox_validate_read_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = mboxdriver_mbox_error_to_mail_error(r); + goto err; + } + + r = mailmbox_fetch_msg_no_lock(folder, indx, &data, &len); + if (r != MAILMBOX_NO_ERROR) { + res = mboxdriver_mbox_error_to_mail_error(r); + goto unlock; + } + + mailmbox_read_unlock(folder); + + * result = len; + + return MAIL_NO_ERROR; + + unlock: + mailmbox_read_unlock(folder); + err: + return res; +} + +int +mboxdriver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, + uint32_t num, + struct mail_flags ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mail_flags * flags; + int res; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + chashdatum key; + chashdatum data; + + folder = cached_session_get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = data.data; + + snprintf(keyname, PATH_MAX, "%u-%lu-flags", num, + (unsigned long) info->msg_body_len); + + r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = flags; + + return MAIL_NO_ERROR; + + err: + return res; +} + +int +mboxdriver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, + struct mail_flags * flags) +{ + int r; + char keyname[PATH_MAX]; + int res; + + snprintf(keyname, PATH_MAX, "%s-flags", uid); + + r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +int mboxdriver_fetch_header(mailsession * session, uint32_t indx, + char ** result, size_t * result_len) +{ + int r; + char * msg_content; + size_t msg_length; + struct mailmbox_folder * folder; + + folder = session_get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_BAD_STATE; + + r = mailmbox_fetch_msg_headers(folder, indx, &msg_content, &msg_length); + if (r != MAILMBOX_NO_ERROR) + return mboxdriver_mbox_error_to_mail_error(r); + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; +} + +int mbox_get_locked_messages_list(struct mailmbox_folder * folder, + mailsession * session, + mailmessage_driver * driver, + int (* lock)(struct mailmbox_folder *), + int (* unlock)(struct mailmbox_folder *), + struct mailmessage_list ** result) +{ + struct mailmessage_list * env_list; + unsigned int i; + int r; + int res; + carray * tab; + + tab = carray_new(128); + if (tab == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = lock(folder); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) { + struct mailmbox_msg_info * msg_info; + mailmessage * msg; + + msg_info = carray_get(folder->mb_tab, i); + if (msg_info == NULL) + continue; + + if (msg_info->msg_deleted) + continue; + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto unlock; + } + + r = mailmessage_init(msg, session, driver, msg_info->msg_uid, + msg_info->msg_size - msg_info->msg_start_len); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlock; + } + + r = carray_add(tab, msg, NULL); + if (r < 0) { + mailmessage_free(msg); + res = MAIL_ERROR_MEMORY; + goto unlock; + } + } + + env_list = mailmessage_list_new(tab); + if (env_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto unlock; + } + + unlock(folder); + + * result = env_list; + + return MAIL_NO_ERROR; + + unlock: + unlock(folder); + free: + for(i = 0 ; i < carray_count(tab) ; i ++) + mailmessage_free(carray_get(tab, i)); + carray_free(tab); + err: + return res; +} + +static int release_read_mbox(struct mailmbox_folder * folder) +{ + int r; + + r = mailmbox_read_unlock(folder); + return mboxdriver_mbox_error_to_mail_error(r); +} + +static int acquire_read_mbox(struct mailmbox_folder * folder) +{ + int r; + + r = mailmbox_validate_read_lock(folder); + return mboxdriver_mbox_error_to_mail_error(r); +} + +static int release_write_mbox(struct mailmbox_folder * folder) +{ + int r; + + r = mailmbox_write_unlock(folder); + return mboxdriver_mbox_error_to_mail_error(r); +} + +static int acquire_write_mbox(struct mailmbox_folder * folder) +{ + int r; + int res; + + r = mailmbox_validate_write_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = mboxdriver_mbox_error_to_mail_error(r); + goto err; + } + + if (folder->mb_written_uid < folder->mb_max_uid) { + r = mailmbox_expunge_no_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = mboxdriver_mbox_error_to_mail_error(r); + goto unlock; + } + } + + return MAIL_NO_ERROR; + + unlock: + mailmbox_write_unlock(folder); + err: + return res; +} + +/* get message list with all valid written UID */ + +int mbox_get_uid_messages_list(struct mailmbox_folder * folder, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result) +{ + return mbox_get_locked_messages_list(folder, session, driver, + acquire_write_mbox, release_write_mbox, result); +} + + +/* get message list */ + +int mbox_get_messages_list(struct mailmbox_folder * folder, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result) +{ + return mbox_get_locked_messages_list(folder, session, driver, + acquire_read_mbox, release_read_mbox, result); +} diff --git a/Sources/libetpan/driver/implementation/mbox/mboxdriver_tools.h b/Sources/libetpan/driver/implementation/mbox/mboxdriver_tools.h new file mode 100644 index 00000000..c9db2d31 --- /dev/null +++ b/Sources/libetpan/driver/implementation/mbox/mboxdriver_tools.h @@ -0,0 +1,85 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver_tools.h,v 1.11 2008/02/20 22:15:50 hoa Exp $ + */ + +#ifndef MBOXDRIVER_TOOLS_H + +#define MBOXDRIVER_TOOLS_H + +#include "mail_cache_db_types.h" +#include "mboxdriver_types.h" +#include "mailmbox.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int mboxdriver_mbox_error_to_mail_error(int error); + +int mboxdriver_fetch_msg(mailsession * session, uint32_t indx, + char ** result, size_t * result_len); + +int mboxdriver_fetch_size(mailsession * session, uint32_t indx, + size_t * result); + +int +mboxdriver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, + uint32_t num, + struct mail_flags ** result); + +int +mboxdriver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, struct mail_flags * flags); + +int mbox_get_uid_messages_list(struct mailmbox_folder * folder, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result); + +int mbox_get_messages_list(struct mailmbox_folder * folder, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result); + +int mboxdriver_fetch_header(mailsession * session, uint32_t indx, + char ** result, size_t * result_len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/mbox/mboxdriver_types.h b/Sources/libetpan/driver/implementation/mbox/mboxdriver_types.h new file mode 100644 index 00000000..d8a3764b --- /dev/null +++ b/Sources/libetpan/driver/implementation/mbox/mboxdriver_types.h @@ -0,0 +1,107 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver_types.h,v 1.7 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifndef MBOXDRIVER_TYPES_H + +#define MBOXDRIVER_TYPES_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* mbox driver */ + +enum { + MBOXDRIVER_SET_READ_ONLY = 1, + MBOXDRIVER_SET_NO_UID +}; + +struct mbox_session_state_data { + struct mailmbox_folder * mbox_folder; + int mbox_force_read_only; + int mbox_force_no_uid; +}; + +/* cached version */ + +enum { + /* the mapping of the parameters should be the same as for mbox */ + MBOXDRIVER_CACHED_SET_READ_ONLY = 1, + MBOXDRIVER_CACHED_SET_NO_UID, + /* cache specific */ + MBOXDRIVER_CACHED_SET_CACHE_DIRECTORY, + MBOXDRIVER_CACHED_SET_FLAGS_DIRECTORY +}; + +struct mbox_cached_session_state_data { + mailsession * mbox_ancestor; + char * mbox_quoted_mb; + char mbox_cache_directory[PATH_MAX]; + char mbox_flags_directory[PATH_MAX]; + struct mail_flags_store * mbox_flags_store; +}; + +/* mbox storage */ + +/* + mbox_mailstorage is the state data specific to the mbox storage. + + - pathname is the filename that contains the mailbox. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache. + + - flags_directory is the location of the flags. +*/ + +struct mbox_mailstorage { + char * mbox_pathname; + + int mbox_cached; + char * mbox_cache_directory; + char * mbox_flags_directory; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/mbox/mboxstorage.c b/Sources/libetpan/driver/implementation/mbox/mboxstorage.c new file mode 100644 index 00000000..8a95617b --- /dev/null +++ b/Sources/libetpan/driver/implementation/mbox/mboxstorage.c @@ -0,0 +1,197 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxstorage.c,v 1.14 2008/02/17 13:13:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mboxstorage.h" + +#include "mail.h" +#include "mailmessage.h" +#include "mboxdriver.h" +#include "mboxdriver_cached.h" +#include "maildriver.h" + +#include +#include + +/* mbox storage */ + +static int mbox_mailstorage_connect(struct mailstorage * storage); +static int +mbox_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result); +static void mbox_mailstorage_uninitialize(struct mailstorage * storage); + +static mailstorage_driver mbox_mailstorage_driver = { + /* sto_name */ "mbox", + /* sto_connect */ mbox_mailstorage_connect, + /* sto_get_folder_session */ mbox_mailstorage_get_folder_session, + /* sto_uninitialize */ mbox_mailstorage_uninitialize +}; + +LIBETPAN_EXPORT +int mbox_mailstorage_init(struct mailstorage * storage, + const char * mbox_pathname, int mbox_cached, + const char * mbox_cache_directory, const char * mbox_flags_directory) +{ + struct mbox_mailstorage * mbox_storage; + + mbox_storage = malloc(sizeof(* mbox_storage)); + if (mbox_storage == NULL) + goto err; + + mbox_storage->mbox_pathname = strdup(mbox_pathname); + if (mbox_storage->mbox_pathname == NULL) + goto free; + + mbox_storage->mbox_cached = mbox_cached; + + if (mbox_cached && (mbox_cache_directory != NULL) && + (mbox_flags_directory != NULL)) { + mbox_storage->mbox_cache_directory = strdup(mbox_cache_directory); + if (mbox_storage->mbox_cache_directory == NULL) + goto free_pathname; + + mbox_storage->mbox_flags_directory = strdup(mbox_flags_directory); + if (mbox_storage->mbox_flags_directory == NULL) + goto free_cache_directory; + } + else { + mbox_storage->mbox_cached = FALSE; + mbox_storage->mbox_cache_directory = NULL; + mbox_storage->mbox_flags_directory = NULL; + } + + storage->sto_data = mbox_storage; + storage->sto_driver = &mbox_mailstorage_driver; + + return MAIL_NO_ERROR; + + free_cache_directory: + free(mbox_storage->mbox_cache_directory); + free_pathname: + free(mbox_storage->mbox_pathname); + free: + free(mbox_storage); + err: + return MAIL_ERROR_MEMORY; +} + +static void mbox_mailstorage_uninitialize(struct mailstorage * storage) +{ + struct mbox_mailstorage * mbox_storage; + + mbox_storage = storage->sto_data; + if (mbox_storage->mbox_flags_directory != NULL) + free(mbox_storage->mbox_flags_directory); + if (mbox_storage->mbox_cache_directory != NULL) + free(mbox_storage->mbox_cache_directory); + free(mbox_storage->mbox_pathname); + free(mbox_storage); + + storage->sto_data = NULL; +} + +static int mbox_mailstorage_connect(struct mailstorage * storage) +{ + struct mbox_mailstorage * mbox_storage; + mailsession_driver * driver; + int r; + int res; + mailsession * session; + + mbox_storage = storage->sto_data; + + if (mbox_storage->mbox_cached) + driver = mbox_cached_session_driver; + else + driver = mbox_session_driver; + + session = mailsession_new(driver); + if (session == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if (mbox_storage->mbox_cached) { + r = mailsession_parameters(session, + MBOXDRIVER_CACHED_SET_CACHE_DIRECTORY, + mbox_storage->mbox_cache_directory); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + r = mailsession_parameters(session, + MBOXDRIVER_CACHED_SET_FLAGS_DIRECTORY, + mbox_storage->mbox_flags_directory); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + } + + r = mailsession_connect_path(session, mbox_storage->mbox_pathname); + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto free; + } + + storage->sto_session = session; + + return MAIL_NO_ERROR; + + free: + mailsession_free(session); + err: + return res; +} + +static int +mbox_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result) +{ + * result = storage->sto_session; + + return MAIL_NO_ERROR; +} + diff --git a/Sources/libetpan/driver/implementation/mbox/mboxstorage.h b/Sources/libetpan/driver/implementation/mbox/mboxstorage.h new file mode 100644 index 00000000..51831baa --- /dev/null +++ b/Sources/libetpan/driver/implementation/mbox/mboxstorage.h @@ -0,0 +1,70 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxstorage.h,v 1.8 2006/06/02 15:44:29 smarinier Exp $ + */ + +#ifndef MBOXSTORAGE_H + +#define MBOXSTORAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mbox_mailstorage_init is the constructor for a mbox storage. + + @param storage this is the storage to initialize. + + @param pathname is the filename that contains the mailbox. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache + + @param flags_directory is the location of the flags +*/ + +LIBETPAN_EXPORT +int mbox_mailstorage_init(struct mailstorage * storage, + const char * mb_pathname, int mb_cached, + const char * mb_cache_directory, const char * mb_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/mh/Makefile.am b/Sources/libetpan/driver/implementation/mh/Makefile.am new file mode 100644 index 00000000..1f0c7c73 --- /dev/null +++ b/Sources/libetpan/driver/implementation/mh/Makefile.am @@ -0,0 +1,56 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +etpaninclude_HEADERS = \ + mhdriver.h \ + mhdriver_cached.h \ + mhdriver_cached_message.h \ + mhdriver_message.h \ + mhdriver_types.h \ + mhstorage.h + +AM_CPPFLAGS = -I$(top_builddir)/include \ + -I$(top_srcdir)/src/driver/interface \ + -I$(top_srcdir)/src/driver/tools \ + -I$(top_srcdir)/src/low-level/mh \ + -I$(top_srcdir)/src/low-level/mime \ + -I$(top_srcdir)/src/low-level/imf \ + -I$(top_srcdir)/src/data-types + +noinst_LTLIBRARIES = libmh.la + +libmh_la_SOURCES = \ + mhdriver.c \ + mhdriver_cached.c \ + mhdriver_cached_message.c \ + mhdriver_message.c \ + mhdriver_tools.h mhdriver_tools.c \ + mhstorage.c diff --git a/Sources/libetpan/driver/implementation/mh/mhdriver.c b/Sources/libetpan/driver/implementation/mh/mhdriver.c new file mode 100644 index 00000000..0df36822 --- /dev/null +++ b/Sources/libetpan/driver/implementation/mh/mhdriver.c @@ -0,0 +1,894 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver.c,v 1.38 2008/02/20 22:15:50 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mhdriver.h" + +#include +#include +#ifdef WIN32 +# include "win_etpan.h" +#else +# include +# include +# include +#endif +#include +#include +#include +#include +#include + +#include "mailmh.h" +#include "maildriver_tools.h" +#include "mhdriver_tools.h" +#include "mhdriver_message.h" +#include "mailmessage.h" + +static int mhdriver_initialize(mailsession * session); + +static void mhdriver_uninitialize(mailsession * session); + +static int mhdriver_connect_path(mailsession * session, const char * path); +static int mhdriver_logout(mailsession * session); + +static int mhdriver_build_folder_name(mailsession * session, const char * mb, + const char * name, char ** result); +static int mhdriver_create_folder(mailsession * session, const char * mb); + +static int mhdriver_delete_folder(mailsession * session, const char * mb); + +static int mhdriver_rename_folder(mailsession * session, const char * mb, + const char * new_name); + +static int mhdriver_select_folder(mailsession * session, const char * mb); + +static int mhdriver_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int mhdriver_messages_number(mailsession * session, const char * mb, + uint32_t * result); + +static int mhdriver_list_folders(mailsession * session, const char * mb, + struct mail_list ** result); + +static int mhdriver_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result); + +static int mhdriver_subscribe_folder(mailsession * session, const char * mb); + +static int mhdriver_unsubscribe_folder(mailsession * session, const char * mb); + +static int mhdriver_append_message(mailsession * session, + const char * message, size_t size); +static int mhdriver_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); +static int mhdriver_copy_message(mailsession * session, + uint32_t num, const char * mb); + +static int mhdriver_remove_message(mailsession * session, uint32_t num); + +static int mhdriver_move_message(mailsession * session, + uint32_t num, const char * mb); + +static int mhdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int mhdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int mhdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static mailsession_driver local_mh_session_driver = { + /* sess_name */ "mh", + + /* sess_initialize */ mhdriver_initialize, + /* sess_uninitialize */ mhdriver_uninitialize, + + /* sess_parameters */ NULL, + + /* sess_connect_stream */ NULL, + /* sess_connect_path */ mhdriver_connect_path, + /* sess_starttls */ NULL, + /* sess_login */ NULL, + /* sess_logout */ mhdriver_logout, + /* sess_noop */ NULL, + + /* sess_build_folder_name */ mhdriver_build_folder_name, + /* sess_create_folder */ mhdriver_create_folder, + /* sess_delete_folder */ mhdriver_delete_folder, + /* sess_rename_folder */ mhdriver_rename_folder, + /* sess_check_folder */ NULL, + /* sess_examine_folder */ NULL, + /* sess_select_folder */ mhdriver_select_folder, + /* sess_expunge_folder */ NULL, + /* sess_status_folder */ mhdriver_status_folder, + /* sess_messages_number */ mhdriver_messages_number, + /* sess_recent_number */ mhdriver_messages_number, + /* sess_unseen_number */ mhdriver_messages_number, + /* sess_list_folders */ mhdriver_list_folders, + /* sess_lsub_folders */ mhdriver_lsub_folders, + /* sess_subscribe_folder */ mhdriver_subscribe_folder, + /* sess_unsubscribe_folder */ mhdriver_unsubscribe_folder, + + /* sess_append_message */ mhdriver_append_message, + /* sess_append_message_flags */ mhdriver_append_message_flags, + /* sess_copy_message */ mhdriver_copy_message, + /* sess_move_message */ mhdriver_move_message, + + /* sess_get_message */ mhdriver_get_message, + /* sess_get_message_by_uid */ mhdriver_get_message_by_uid, + + /* sess_get_messages_list */ mhdriver_get_messages_list, + /* sess_get_envelopes_list */ maildriver_generic_get_envelopes_list, + /* sess_remove_message */ mhdriver_remove_message, +#if 0 + /* sess_search_messages */ maildriver_generic_search_messages, +#endif + /* sess_login_sasl */ NULL +}; + +mailsession_driver * mh_session_driver = &local_mh_session_driver; + +static inline struct mh_session_state_data * get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline struct mailmh * get_mh_session(mailsession * session) +{ + return get_data(session)->mh_session; +} + +static inline struct mailmh_folder * get_mh_cur_folder(mailsession * session) +{ + return get_data(session)->mh_cur_folder; +} + +static int add_to_list(mailsession * session, const char * mb) +{ + char * new_mb; + struct mh_session_state_data * data; + int r; + + data = get_data(session); + + new_mb = strdup(mb); + if (new_mb == NULL) + return -1; + + r = clist_append(data->mh_subscribed_list, new_mb); + if (r < 0) { + free(new_mb); + return -1; + } + + return 0; +} + +static int remove_from_list(mailsession * session, const char * mb) +{ + clistiter * cur; + struct mh_session_state_data * data; + + data = get_data(session); + + for(cur = clist_begin(data->mh_subscribed_list) ; + cur != NULL ; cur = clist_next(cur)) { + char * cur_name; + + cur_name = clist_content(cur); + if (strcmp(cur_name, mb) == 0) { + clist_delete(data->mh_subscribed_list, cur); + free(cur_name); + return 0; + } + } + + return -1; +} + +static int mhdriver_initialize(mailsession * session) +{ + struct mh_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->mh_session = NULL; + data->mh_cur_folder = NULL; + + data->mh_subscribed_list = clist_new(); + if (data->mh_subscribed_list == NULL) + goto free; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free: + free(data); + err: + return MAIL_ERROR_MEMORY; +} + +static void mhdriver_uninitialize(mailsession * session) +{ + struct mh_session_state_data * data; + + data = get_data(session); + + if (data->mh_session != NULL) + mailmh_free(data->mh_session); + + clist_foreach(data->mh_subscribed_list, (clist_func) free, NULL); + clist_free(data->mh_subscribed_list); + + free(data); + + session->sess_data = NULL; +} + + +static int mhdriver_connect_path(mailsession * session, const char * path) +{ + struct mailmh * mh; + + if (get_mh_session(session) != NULL) + return MAIL_ERROR_BAD_STATE; + + mh = mailmh_new(path); + if (mh == NULL) + return MAIL_ERROR_MEMORY; + + get_data(session)->mh_session = mh; + + return MAIL_NO_ERROR; +} + +static int mhdriver_logout(mailsession * session) +{ + struct mailmh * mh; + + mh = get_mh_session(session); + + if (mh == NULL) + return MAIL_ERROR_BAD_STATE; + + mailmh_free(mh); + get_data(session)->mh_session = NULL; + + return MAIL_NO_ERROR; +} + +/* folders operations */ + +static int mhdriver_build_folder_name(mailsession * session, const char * mb, + const char * name, char ** result) +{ + char * folder_name; + + folder_name = malloc(strlen(mb) + 2 + strlen(name)); + if (folder_name == NULL) + return MAIL_ERROR_MEMORY; + + strcpy(folder_name, mb); + strcat(folder_name, "/"); + strcat(folder_name, name); + + * result = folder_name; + + return MAIL_NO_ERROR; +} + +static int get_parent(mailsession * session, const char * mb, + struct mailmh_folder ** result_folder, + const char ** result_name) +{ + const char * name; + size_t length; + size_t i; + char * parent_name; + struct mailmh_folder * parent; + struct mailmh * mh; + + mh = get_mh_session(session); + if (mh == NULL) + return MAIL_ERROR_BAD_STATE; + + length = strlen(mb); + if (length > 0) { + i = length - 1; + while (1) { + if (i == 0) + return MAIL_ERROR_INVAL; + if (mb[i] == '/') + break; + i --; + } + name = mb + i + 1; + } + else { + return MAIL_ERROR_INVAL; + } + + parent_name = malloc(i + 1); + /* strndup(mb, i) */ + if (parent_name == NULL) + return MAIL_ERROR_MEMORY; + + strncpy(parent_name, mb, i); + parent_name[i] = '\0'; + + parent = mailmh_folder_find(mh->mh_main, parent_name); + free(parent_name); + if (parent == NULL) + return MAIL_ERROR_FOLDER_NOT_FOUND; + + * result_folder = parent; + * result_name = name; + + return MAIL_NO_ERROR; +} + +static int mhdriver_create_folder(mailsession * session, const char * mb) +{ + int r; + struct mailmh_folder * parent; + const char * name; + + r = get_parent(session, mb, &parent, &name); + if (r != MAIL_NO_ERROR) + return r; + + r = mailmh_folder_add_subfolder(parent, name); + + return mhdriver_mh_error_to_mail_error(r); +} + +static int mhdriver_delete_folder(mailsession * session, const char * mb) +{ + int r; + struct mailmh_folder * folder; + struct mailmh * mh; + + mh = get_mh_session(session); + if (mh == NULL) + return MAIL_ERROR_BAD_STATE; + + folder = mailmh_folder_find(mh->mh_main, mb); + if (folder == NULL) + return MAIL_ERROR_FOLDER_NOT_FOUND; + + if (get_mh_cur_folder(session) == folder) + get_data(session)->mh_cur_folder = NULL; + + r = mailmh_folder_remove_subfolder(folder); + + return mhdriver_mh_error_to_mail_error(r); +} + +static int mhdriver_rename_folder(mailsession * session, const char * mb, + const char * new_name) +{ + struct mailmh_folder * src_folder; + struct mailmh_folder * dst_folder; + const char * name; + struct mailmh * mh; + int r; + + r = get_parent(session, new_name, &dst_folder, &name); + if (r != MAIL_NO_ERROR) + return r; + + mh = get_mh_session(session); + if (mh == NULL) + return MAIL_ERROR_BAD_STATE; + + src_folder = mailmh_folder_find(mh->mh_main, mb); + if (src_folder == NULL) + return MAIL_ERROR_FOLDER_NOT_FOUND; + + if (get_mh_cur_folder(session) == src_folder) + get_data(session)->mh_cur_folder = NULL; + + r = mailmh_folder_rename_subfolder(src_folder, dst_folder, name); + + return mhdriver_mh_error_to_mail_error(r); +} + +static int mhdriver_select_folder(mailsession * session, const char * mb) +{ + struct mailmh_folder * folder; + struct mailmh * mh; + int r; + + mh = get_mh_session(session); + if (mh == NULL) + return MAIL_ERROR_BAD_STATE; + + r = mailmh_folder_update(mh->mh_main); + + folder = mailmh_folder_find(mh->mh_main, mb); + if (folder == NULL) + return MAIL_ERROR_FOLDER_NOT_FOUND; + + get_data(session)->mh_cur_folder = folder; + r = mailmh_folder_update(folder); + + return mhdriver_mh_error_to_mail_error(r); +} + +static int mhdriver_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + uint32_t count; + int r; + + r = mhdriver_messages_number(session, mb, &count); + if (r != MAIL_NO_ERROR) + return r; + + * result_messages = count; + * result_recent = count; + * result_unseen = count; + + return MAIL_NO_ERROR; +} + +static int mhdriver_messages_number(mailsession * session, const char * mb, + uint32_t * result) +{ + struct mailmh_folder * folder; + uint32_t count; + struct mailmh * mh; + unsigned int i; + + mh = get_mh_session(session); + if (mh == NULL) + return MAIL_ERROR_BAD_STATE; + + if (mb != NULL) { + folder = mailmh_folder_find(mh->mh_main, mb); + if (folder == NULL) + return MAIL_ERROR_FOLDER_NOT_FOUND; + } + else { + folder = get_mh_cur_folder(session); + if (folder == NULL) + return MAIL_ERROR_BAD_STATE; + } + + mailmh_folder_update(folder); + count = 0; + for (i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++) { + struct mailmh_msg_info * msg_info; + + msg_info = carray_get(folder->fl_msgs_tab, i); + if (msg_info != NULL) + count ++; + } + + * result = count; + + return MAIL_NO_ERROR; +} + + +static int get_list_folders(struct mailmh_folder * folder, clist ** result) +{ + unsigned int i; + clist * list; + char * new_filename; + int res; + int r; + + list = * result; + + new_filename = strdup(folder->fl_filename); + if (new_filename == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + r = mailmh_folder_update(folder); + + switch (r) { + case MAILMH_NO_ERROR: + break; + + default: + res = mhdriver_mh_error_to_mail_error(r); + free(new_filename); + goto free; + } + + r = clist_append(list, new_filename); + if (r < 0) { + free(new_filename); + res = MAIL_ERROR_MEMORY; + goto free; + } + + if (folder->fl_subfolders_tab != NULL) { + for(i = 0 ; i < carray_count(folder->fl_subfolders_tab) ; i++) { + struct mailmh_folder * subfolder; + + subfolder = carray_get(folder->fl_subfolders_tab, i); + + r = get_list_folders(subfolder, &list); + if (r != MAIL_NO_ERROR) { + free(new_filename); + res = MAIL_ERROR_MEMORY; + goto free; + } + } + } + + * result = list; + + free(new_filename); + return MAIL_NO_ERROR; + + free: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + return res; +} + + +static int mhdriver_list_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + clist * list; + int r; + struct mailmh * mh; + struct mail_list * ml; + + mh = get_mh_session(session); + + if (mh == NULL) + return MAIL_ERROR_BAD_STATE; + + list = clist_new(); + if (list == NULL) + return MAIL_ERROR_MEMORY; + + r = get_list_folders(mh->mh_main, &list); + if (r != MAIL_NO_ERROR) + return r; + + ml = mail_list_new(list); + if (ml == NULL) + goto free; + + * result = ml; + + return MAIL_NO_ERROR; + + free: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + return MAIL_ERROR_MEMORY; +} + +static int mhdriver_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + clist * subscribed; + clist * lsub_result; + clistiter * cur; + struct mail_list * lsub; + size_t length; + int r; + + length = strlen(mb); + + subscribed = get_data(session)->mh_subscribed_list; + + lsub_result = clist_new(); + if (lsub_result == NULL) + return MAIL_ERROR_MEMORY; + + for(cur = clist_begin(subscribed) ; cur != NULL ; + cur = clist_next(cur)) { + char * cur_mb; + char * new_mb; + + cur_mb = clist_content(cur); + + if (strncmp(mb, cur_mb, length) == 0) { + new_mb = strdup(cur_mb); + if (new_mb == NULL) + goto free_list; + + r = clist_append(lsub_result, new_mb); + if (r < 0) { + free(new_mb); + goto free_list; + } + } + } + + lsub = mail_list_new(lsub_result); + if (lsub == NULL) + goto free_list; + + * result = lsub; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(lsub_result, (clist_func) free, NULL); + clist_free(lsub_result); + return MAIL_ERROR_MEMORY; +} + +static int mhdriver_subscribe_folder(mailsession * session, const char * mb) +{ + int r; + + r = add_to_list(session, mb); + if (r < 0) + return MAIL_ERROR_SUBSCRIBE; + + return MAIL_NO_ERROR; +} + +static int mhdriver_unsubscribe_folder(mailsession * session, const char * mb) +{ + int r; + + r = remove_from_list(session, mb); + if (r < 0) + return MAIL_ERROR_UNSUBSCRIBE; + + return MAIL_NO_ERROR; +} + +/* messages operations */ + +static int mhdriver_append_message(mailsession * session, + const char * message, size_t size) +{ + int r; + struct mailmh_folder * folder; + + folder = get_mh_cur_folder(session); + if (folder == NULL) + return MAIL_ERROR_BAD_STATE; + + r = mailmh_folder_add_message(folder, message, size); + + switch (r) { + case MAILMH_ERROR_FILE: + return MAIL_ERROR_DISKSPACE; + + default: + return mhdriver_mh_error_to_mail_error(r); + } +} + +static int mhdriver_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags) +{ + return mhdriver_append_message(session, message, size); +} + +static int mhdriver_copy_message(mailsession * session, + uint32_t num, const char * mb) +{ + int fd; + int r; + struct mailmh_folder * folder; + struct mailmh * mh; + int res; + + mh = get_mh_session(session); + if (mh == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + folder = get_mh_cur_folder(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + r = mailmh_folder_get_message_fd(folder, num, O_RDONLY, &fd); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + folder = mailmh_folder_find(mh->mh_main, mb); + if (folder == NULL) { + res = MAIL_ERROR_FOLDER_NOT_FOUND; + goto close; + } + + r = mailmh_folder_add_message_file(folder, fd); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_COPY; + goto close; + } + + close(fd); + + return MAIL_NO_ERROR; + + close: + close(fd); + err: + return res; +} + +static int mhdriver_remove_message(mailsession * session, uint32_t num) +{ + int r; + struct mailmh_folder * folder; + + folder = get_mh_cur_folder(session); + if (folder == NULL) + return MAIL_ERROR_DELETE; + + r = mailmh_folder_remove_message(folder, num); + + return mhdriver_mh_error_to_mail_error(r); +} + +static int mhdriver_move_message(mailsession * session, + uint32_t num, const char * mb) +{ + int r; + struct mailmh_folder * src_folder; + struct mailmh_folder * dest_folder; + struct mailmh * mh; + + mh = get_mh_session(session); + if (mh == NULL) + return MAIL_ERROR_BAD_STATE; + + src_folder = get_mh_cur_folder(session); + if (src_folder == NULL) + return MAIL_ERROR_BAD_STATE; + + dest_folder = mailmh_folder_find(mh->mh_main, mb); + if (dest_folder == NULL) + return MAIL_ERROR_FOLDER_NOT_FOUND; + + r = mailmh_folder_move_message(dest_folder, src_folder, num); + + return mhdriver_mh_error_to_mail_error(r); +} + + +static int mhdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + struct mailmh_folder * folder; + int res; + + folder = get_mh_cur_folder(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mailmh_folder_update(folder); + return mh_get_messages_list(folder, session, mh_message_driver, result); + + err: + return res; +} + +static int mhdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, mh_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int mhdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t indx; + char *p; + struct mailmh_msg_info * mh_msg_info; + struct mh_session_state_data * mh_data; + chashdatum key; + chashdatum data; + int r; + time_t mtime; + char * mtime_p; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + indx = (uint32_t) strtoul(uid, &p, 10); + if (p == uid || * p != '-') + return MAIL_ERROR_INVAL; + + mh_data = session->sess_data; + key.data = &indx; + key.len = sizeof(indx); + r = chash_get(mh_data->mh_cur_folder->fl_msgs_hash, &key, &data); + if (r < 0) + return MAIL_ERROR_MSG_NOT_FOUND; + + mh_msg_info = data.data; + + mtime_p = p + 1; + + mtime = strtoul(mtime_p, &p, 10); + if ((* p == '-') && (mtime == mh_msg_info->msg_mtime)) { + size_t size; + char *size_p; + + size_p = p + 1; + size = strtoul(size_p, &p, 10); + if ((* p == '\0') && (size == mh_msg_info->msg_size)) + return mhdriver_get_message(session, indx, result); + } + else if (* p != '-') { + return MAIL_ERROR_INVAL; + } + + return MAIL_ERROR_MSG_NOT_FOUND; +} diff --git a/Sources/libetpan/driver/implementation/mh/mhdriver.h b/Sources/libetpan/driver/implementation/mh/mhdriver.h new file mode 100644 index 00000000..fc173cee --- /dev/null +++ b/Sources/libetpan/driver/implementation/mh/mhdriver.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver.h,v 1.12 2004/11/21 21:53:33 hoa Exp $ + */ + +#ifndef MHDRIVER_H + +#define MHDRIVER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * mh_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/mh/mhdriver_cached.c b/Sources/libetpan/driver/implementation/mh/mhdriver_cached.c new file mode 100644 index 00000000..0cc0cf15 --- /dev/null +++ b/Sources/libetpan/driver/implementation/mh/mhdriver_cached.c @@ -0,0 +1,1317 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver_cached.c,v 1.52 2010/04/05 14:43:48 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mhdriver_cached.h" + +#include +#include +#ifdef WIN32 +# include "win_etpan.h" +#else +# include +# include +# include +#endif +#include +#include +#include +#include +#include + +#include "mail.h" +#include "mail_cache_db.h" + +#include "generic_cache.h" +#include "imfcache.h" +#include "mhdriver.h" + +#include "mhdriver_cached_message.h" +#include "mailmh.h" +#include "maildriver_tools.h" +#include "mhdriver_tools.h" +#include "mailmessage.h" + +static int mhdriver_cached_initialize(mailsession * session); + +static void mhdriver_cached_uninitialize(mailsession * session); + +static int mhdriver_cached_parameters(mailsession * session, + int id, void * value); + +static int mhdriver_cached_connect_path(mailsession * session, const char * path); +static int mhdriver_cached_logout(mailsession * session); + +static int mhdriver_cached_build_folder_name(mailsession * session, const char * mb, + const char * name, char ** result); +static int mhdriver_cached_create_folder(mailsession * session, const char * mb); + +static int mhdriver_cached_delete_folder(mailsession * session, const char * mb); + +static int mhdriver_cached_rename_folder(mailsession * session, const char * mb, + const char * new_name); + +static int mhdriver_cached_check_folder(mailsession * session); + +static int mhdriver_cached_select_folder(mailsession * session, const char * mb); + +static int mhdriver_cached_expunge_folder(mailsession * session); + +static int mhdriver_cached_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int mhdriver_cached_messages_number(mailsession * session, const char * mb, + uint32_t * result); +static int mhdriver_cached_recent_number(mailsession * session, const char * mb, + uint32_t * result); +static int mhdriver_cached_unseen_number(mailsession * session, const char * mb, + uint32_t * result); + +static int mhdriver_cached_list_folders(mailsession * session, const char * mb, + struct mail_list ** result); + +static int mhdriver_cached_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result); + +static int mhdriver_cached_subscribe_folder(mailsession * session, const char * mb); + +static int mhdriver_cached_unsubscribe_folder(mailsession * session, + const char * mb); + +static int mhdriver_cached_append_message(mailsession * session, + const char * message, size_t size); +static int mhdriver_cached_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); +static int mhdriver_cached_copy_message(mailsession * session, + uint32_t num, const char * mb); + +static int mhdriver_cached_remove_message(mailsession * session, + uint32_t num); + +static int mhdriver_cached_move_message(mailsession * session, + uint32_t num, const char * mb); + +static int +mhdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int +mhdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +static int mhdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int mhdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static mailsession_driver local_mh_cached_session_driver = { + /* sess_name */ "mh-cached", + + /* sess_initialize */ mhdriver_cached_initialize, + /* sess_uninitialize */ mhdriver_cached_uninitialize, + + /* sess_parameters */ mhdriver_cached_parameters, + + /* sess_connect_stream */ NULL, + /* sess_connect_path */ mhdriver_cached_connect_path, + /* sess_starttls */ NULL, + /* sess_login */ NULL, + /* sess_logout */ mhdriver_cached_logout, + /* sess_noop */ NULL, + + /* sess_build_folder_name */ mhdriver_cached_build_folder_name, + /* sess_create_folder */ mhdriver_cached_create_folder, + /* sess_delete_folder */ mhdriver_cached_delete_folder, + /* sess_rename_folder */ mhdriver_cached_rename_folder, + /* sess_check_folder */ mhdriver_cached_check_folder, + /* sess_examine_folder */ NULL, + /* sess_select_folder */ mhdriver_cached_select_folder, + /* sess_expunge_folder */ mhdriver_cached_expunge_folder, + /* sess_status_folder */ mhdriver_cached_status_folder, + /* sess_messages_number */ mhdriver_cached_messages_number, + /* sess_recent_number */ mhdriver_cached_recent_number, + /* sess_unseen_number */ mhdriver_cached_unseen_number, + /* sess_list_folders */ mhdriver_cached_list_folders, + /* sess_lsub_folders */ mhdriver_cached_lsub_folders, + /* sess_subscribe_folder */ mhdriver_cached_subscribe_folder, + /* sess_unsubscribe_folder */ mhdriver_cached_unsubscribe_folder, + + /* sess_append_message */ mhdriver_cached_append_message, + /* sess_append_message_flags */ mhdriver_cached_append_message_flags, + /* sess_copy_message */ mhdriver_cached_copy_message, + /* sess_move_message */ mhdriver_cached_move_message, + + /* sess_get_message */ mhdriver_cached_get_message, + /* sess_get_message_by_uid */ mhdriver_cached_get_message_by_uid, + + /* sess_get_messages_list */ mhdriver_cached_get_messages_list, + /* sess_get_envelopes_list */ mhdriver_cached_get_envelopes_list, + /* sess_remove_message */ mhdriver_cached_remove_message, +#if 0 + /* sess_search_messages */ maildriver_generic_search_messages, +#endif + /* sess_login_sasl */ NULL +}; + +mailsession_driver * mh_cached_session_driver = +&local_mh_cached_session_driver; + +#define ENV_NAME "env.db" +#define FLAGS_NAME "flags.db" + + +static inline struct mh_cached_session_state_data * +get_cached_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * get_ancestor(mailsession * session) +{ + return get_cached_data(session)->mh_ancestor; +} + +static inline struct mh_session_state_data * +get_ancestor_data(mailsession * session) +{ + return get_ancestor(session)->sess_data; +} + +static inline struct mailmh * +get_mh_session(mailsession * session) +{ + return get_ancestor_data(session)->mh_session; +} + +static inline struct mailmh_folder * +get_mh_cur_folder(mailsession * session) +{ + return get_ancestor_data(session)->mh_cur_folder; +} + + +#define FILENAME_MAX_UID "max-uid" + +/* write max uid current value */ + +static int write_max_uid_value(mailsession * session) +{ + int r; + char filename[PATH_MAX]; + FILE * f; + int res; + struct mh_cached_session_state_data * cached_data; + struct mh_session_state_data * ancestor_data; + int fd; + + MMAPString * mmapstr; + size_t cur_token; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + if (cached_data->mh_quoted_mb == NULL) + return MAIL_ERROR_BAD_STATE; + + snprintf(filename, PATH_MAX, "%s/%s/%s", + cached_data->mh_cache_directory, + cached_data->mh_quoted_mb, FILENAME_MAX_UID); + + fd = creat(filename, S_IRUSR | S_IWUSR); + if (fd < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + f = fdopen(fd, "w"); + if (f == NULL) { + close(fd); + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close; + } + + r = mail_serialize_clear(mmapstr, &cur_token); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + r = mailimf_cache_int_write(mmapstr, &cur_token, + ancestor_data->mh_cur_folder->fl_max_index); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + r = (int) fwrite(mmapstr->str, 1, mmapstr->len, f); + if ((size_t) r != mmapstr->len) { + res = MAIL_ERROR_FILE; + goto free_mmapstr; + } + + mmap_string_free(mmapstr); + fclose(f); + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close: + fclose(f); + err: + return res; +} + +static int read_max_uid_value(mailsession * session) +{ + int r; + char filename[PATH_MAX]; + FILE * f; + uint32_t written_uid; + int res; + struct mh_cached_session_state_data * cached_data; + struct mh_session_state_data * ancestor_data; + + MMAPString * mmapstr; + size_t cur_token; + char buf[sizeof(uint32_t)]; + size_t read_size; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + snprintf(filename, PATH_MAX, "%s/%s/%s", + cached_data->mh_cache_directory, + cached_data->mh_quoted_mb, FILENAME_MAX_UID); + + f = fopen(filename, "r"); + if (f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + read_size = fread(buf, 1, sizeof(uint32_t), f); + + mmapstr = mmap_string_new_len(buf, read_size); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close; + } + + cur_token = 0; + + r = mailimf_cache_int_read(mmapstr, &cur_token, &written_uid); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + mmap_string_free(mmapstr); + fclose(f); + + if (written_uid > ancestor_data->mh_cur_folder->fl_max_index) + ancestor_data->mh_cur_folder->fl_max_index = written_uid; + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close: + fclose(f); + err: + return res; +} + + +static int mhdriver_cached_initialize(mailsession * session) +{ + struct mh_cached_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->mh_flags_store = mail_flags_store_new(); + if (data->mh_flags_store == NULL) + goto free; + + data->mh_ancestor = mailsession_new(mh_session_driver); + if (data->mh_ancestor == NULL) + goto free_store; + + data->mh_quoted_mb = NULL; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free_store: + mail_flags_store_free(data->mh_flags_store); + free: + free(data); + err: + return MAIL_ERROR_MEMORY; +} + +static void free_state(struct mh_cached_session_state_data * mh_data) +{ + if (mh_data->mh_quoted_mb) { + free(mh_data->mh_quoted_mb); + mh_data->mh_quoted_mb = NULL; + } +} + +static int mh_flags_store_process(char * flags_directory, char * quoted_mb, + struct mail_flags_store * flags_store) +{ + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + unsigned int i; + int r; + int res; + + if (carray_count(flags_store->fls_tab) == 0) + return MAIL_NO_ERROR; + + if (quoted_mb == NULL) + return MAIL_NO_ERROR; + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + flags_directory, quoted_mb, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(flags_store->fls_tab, i); + + r = mhdriver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + mail_flags_store_clear(flags_store); + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static void mhdriver_cached_uninitialize(mailsession * session) +{ + struct mh_cached_session_state_data * data; + + data = get_cached_data(session); + + mh_flags_store_process(data->mh_flags_directory, data->mh_quoted_mb, + data->mh_flags_store); + + mail_flags_store_free(data->mh_flags_store); + + free_state(data); + mailsession_free(data->mh_ancestor); + free(data); + + session->sess_data = NULL; +} + +static int mhdriver_cached_parameters(mailsession * session, + int id, void * value) +{ + struct mh_cached_session_state_data * cached_data; + int r; + + cached_data = get_cached_data(session); + + switch (id) { + case MHDRIVER_CACHED_SET_CACHE_DIRECTORY: + strncpy(cached_data->mh_cache_directory, value, PATH_MAX); + cached_data->mh_cache_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(cached_data->mh_cache_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + case MHDRIVER_CACHED_SET_FLAGS_DIRECTORY: + strncpy(cached_data->mh_flags_directory, value, PATH_MAX); + cached_data->mh_flags_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(cached_data->mh_flags_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + } + + return MAIL_ERROR_INVAL; +} + +static int mhdriver_cached_connect_path(mailsession * session, const char * path) +{ + return mailsession_connect_path(get_ancestor(session), path); +} + +static int mhdriver_cached_logout(mailsession * session) +{ + struct mh_cached_session_state_data * cached_data; + + write_max_uid_value(session); + + cached_data = get_cached_data(session); + + mh_flags_store_process(cached_data->mh_flags_directory, + cached_data->mh_quoted_mb, + cached_data->mh_flags_store); + + return mailsession_logout(get_ancestor(session)); +} + +static int mhdriver_cached_check_folder(mailsession * session) +{ + struct mh_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + + mh_flags_store_process(cached_data->mh_flags_directory, + cached_data->mh_quoted_mb, + cached_data->mh_flags_store); + + return MAIL_NO_ERROR; +} + +/* folders operations */ + +static int mhdriver_cached_build_folder_name(mailsession * session, const char * mb, + const char * name, char ** result) +{ + return mailsession_build_folder_name(get_ancestor(session), + mb, name, result); +} + +static int mhdriver_cached_create_folder(mailsession * session, const char * mb) +{ + return mailsession_create_folder(get_ancestor(session), mb); +} + +static int mhdriver_cached_delete_folder(mailsession * session, const char * mb) +{ + return mailsession_delete_folder(get_ancestor(session), mb); +} + +static int mhdriver_cached_rename_folder(mailsession * session, const char * mb, + const char * new_name) +{ + return mailsession_rename_folder(get_ancestor(session), mb, new_name); +} + +static int get_cache_directory(mailsession * session, + const char * path, char ** result) +{ + char * quoted_mb; + char dirname[PATH_MAX]; + int res; + int r; + struct mh_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + + quoted_mb = maildriver_quote_mailbox(path); + if (quoted_mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(dirname, PATH_MAX, "%s/%s", + cached_data->mh_cache_directory, quoted_mb); + + r = generic_cache_create_dir(dirname); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + snprintf(dirname, PATH_MAX, "%s/%s", + cached_data->mh_flags_directory, quoted_mb); + + r = generic_cache_create_dir(dirname); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + * result = quoted_mb; + + return MAIL_NO_ERROR; + + free: + free(quoted_mb); + err: + return res; +} + +static int mhdriver_cached_select_folder(mailsession * session, const char * mb) +{ + int r; + int res; + char * quoted_mb; + struct mh_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + + mh_flags_store_process(cached_data->mh_flags_directory, + cached_data->mh_quoted_mb, + cached_data->mh_flags_store); + + quoted_mb = NULL; + r = get_cache_directory(session, mb, "ed_mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = mailsession_select_folder(get_ancestor(session), mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + r = write_max_uid_value(session); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + free_state(cached_data); + cached_data->mh_quoted_mb = quoted_mb; + + return read_max_uid_value(session); + + free: + free(quoted_mb); + err: + return res; +} + +static int mhdriver_cached_expunge_folder(mailsession * session) +{ + struct mailmh_folder * folder; + int res; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + struct mh_cached_session_state_data * cached_data; + unsigned int i; + int r; + + cached_data = get_cached_data(session); + if (cached_data->mh_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mh_flags_store_process(cached_data->mh_flags_directory, + cached_data->mh_quoted_mb, + cached_data->mh_flags_store); + + folder = get_mh_cur_folder(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->mh_flags_directory, cached_data->mh_quoted_mb, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) { + struct mailmh_msg_info * mh_info; + struct mail_flags * flags; + + mh_info = carray_get(folder->fl_msgs_tab, i); + if (mh_info == NULL) + continue; + + r = mhdriver_get_cached_flags(cache_db_flags, mmapstr, + session, mh_info->msg_index, &flags); + if (r != MAIL_NO_ERROR) + continue; + + if (flags->fl_flags & MAIL_FLAG_DELETED) { + r = mailmh_folder_remove_message(folder, mh_info->msg_index); + } + + mail_flags_free(flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + mailmh_folder_update(folder); + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + + +static int mhdriver_cached_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, + uint32_t * result_recent, + uint32_t * result_unseen) +{ + struct mailmh_folder * folder; + int res; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + struct mh_cached_session_state_data * cached_data; + unsigned int i; + int r; + uint32_t count; + uint32_t recent; + uint32_t unseen; + + r = mhdriver_cached_select_folder(session, mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + count = 0; + recent = 0; + unseen = 0; + + folder = get_mh_cur_folder(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + cached_data = get_cached_data(session); + if (cached_data->mh_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->mh_flags_directory, + cached_data->mh_quoted_mb, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) { + struct mailmh_msg_info * mh_info; + struct mail_flags * flags; + + mh_info = carray_get(folder->fl_msgs_tab, i); + if (mh_info == NULL) + continue; + + count ++; + + r = mhdriver_get_cached_flags(cache_db_flags, mmapstr, + session, mh_info->msg_index, + &flags); + + if (r != MAIL_NO_ERROR) { + recent ++; + unseen ++; + continue; + } + + if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) { + recent ++; + } + if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) { + unseen ++; + } + mail_flags_free(flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + * result_messages = count; + * result_recent = recent; + * result_unseen = unseen; + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int mhdriver_cached_messages_number(mailsession * session, const char * mb, + uint32_t * result) +{ + return mailsession_messages_number(get_ancestor(session), mb, result); +} + +static int mhdriver_cached_recent_number(mailsession * session, const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = mhdriver_cached_status_folder(session, mb, &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = recent; + + return MAIL_NO_ERROR; +} + + +static int mhdriver_cached_unseen_number(mailsession * session, const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = mhdriver_cached_status_folder(session, mb, &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = recent; + + return MAIL_NO_ERROR; +} + + +static int mhdriver_cached_list_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + return mailsession_list_folders(get_ancestor(session), mb, result); +} + +static int mhdriver_cached_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + return mailsession_lsub_folders(get_ancestor(session), mb, result); +} + +static int mhdriver_cached_subscribe_folder(mailsession * session, const char * mb) +{ + return mailsession_subscribe_folder(get_ancestor(session), mb); +} + +static int mhdriver_cached_unsubscribe_folder(mailsession * session, + const char * mb) +{ + return mailsession_unsubscribe_folder(get_ancestor(session), mb); +} + +/* messages operations */ + +static int mhdriver_cached_append_message(mailsession * session, + const char * message, size_t size) +{ + return mhdriver_cached_append_message_flags(session, + message, size, NULL); +} + +static int mhdriver_cached_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags) +{ + int r; + struct mailmh_folder * folder; + struct mailmh_msg_info * msg_info; + chashdatum key; + chashdatum value; + uint32_t uid; + struct mh_cached_session_state_data * data; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + char keyname[PATH_MAX]; + + folder = get_mh_cur_folder(session); + if (folder == NULL) + return MAIL_ERROR_BAD_STATE; + + r = mailmh_folder_add_message_uid(folder, + message, size, &uid); + + switch (r) { + case MAILMH_ERROR_FILE: + return MAIL_ERROR_DISKSPACE; + + case MAILMH_NO_ERROR: + break; + + default: + return mhdriver_mh_error_to_mail_error(r); + } + + if (flags == NULL) + goto exit; + + key.data = &uid; + key.len = sizeof(uid); + r = chash_get(folder->fl_msgs_hash, &key, &value); + if (r < 0) + return MAIL_ERROR_CACHE_MISS; + + msg_info = value.data; + + data = get_cached_data(session); + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + data->mh_flags_directory, data->mh_quoted_mb, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) + goto exit; + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) + goto close_db_flags; + + snprintf(keyname, PATH_MAX, "%u-%lu-%lu-flags", + uid, (unsigned long) msg_info->msg_mtime, + (unsigned long) msg_info->msg_size); + + r = mhdriver_write_cached_flags(cache_db_flags, mmapstr, keyname, flags); + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + if (r != MAIL_NO_ERROR) + goto exit; + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + exit: + return MAIL_NO_ERROR; +} + +static int mhdriver_cached_copy_message(mailsession * session, + uint32_t num, const char * mb) +{ + return mailsession_copy_message(get_ancestor(session), num, mb); +} + +static int mhdriver_cached_remove_message(mailsession * session, uint32_t num) +{ + return mailsession_remove_message(get_ancestor(session), num); +} + +static int mhdriver_cached_move_message(mailsession * session, + uint32_t num, const char * mb) +{ + return mailsession_move_message(get_ancestor(session), num, mb); +} + +static int +mhdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + struct mailmh_folder * folder; + int res; + + folder = get_mh_cur_folder(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + return mh_get_messages_list(folder, session, + mh_cached_message_driver, result); + + err: + return res; +} + + + +static int +get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mailimf_fields * fields; + int res; + struct mailmh_folder * folder; + struct mailmh_msg_info * msg_info; + chashdatum key; + chashdatum data; + + folder = get_mh_cur_folder(session); + + key.data = # + key.len = sizeof(num); + r = chash_get(folder->fl_msgs_hash, &key, &data); + if (r < 0) + return MAIL_ERROR_CACHE_MISS; + msg_info = data.data; + + snprintf(keyname, PATH_MAX, "%u-%lu-%lu-envelope", + num, (unsigned long) msg_info->msg_mtime, + (unsigned long) msg_info->msg_size); + + r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = fields; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +write_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields * fields) +{ + int r; + char keyname[PATH_MAX]; + int res; + struct mailmh_folder * folder; + chashdatum key; + chashdatum data; + struct mailmh_msg_info * msg_info; + + folder = get_mh_cur_folder(session); + key.data = # + key.len = sizeof(num); + r = chash_get(folder->fl_msgs_hash, &key, &data); + if (r < 0) + return MAIL_ERROR_CACHE_MISS; + msg_info = data.data; + + snprintf(keyname, PATH_MAX, "%u-%lu-%lu-envelope", + num, (unsigned long) msg_info->msg_mtime, + (unsigned long) msg_info->msg_size); + + r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +mhdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + unsigned int i; + char filename_env[PATH_MAX]; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_env; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + int res; + struct mh_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + if (cached_data->mh_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mh_flags_store_process(cached_data->mh_flags_directory, + cached_data->mh_quoted_mb, + cached_data->mh_flags_store); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(filename_env, PATH_MAX, "%s/%s/%s", + cached_data->mh_cache_directory, + cached_data->mh_quoted_mb, ENV_NAME); + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto free_mmapstr; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->mh_flags_directory, cached_data->mh_quoted_mb, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto close_db_env; + } + + /* fill with cached */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailimf_fields * fields; + struct mail_flags * flags; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + r = get_cached_envelope(cache_db_env, mmapstr, + msg->msg_session, msg->msg_index, &fields); + if (r == MAIL_NO_ERROR) { + msg->msg_cached = TRUE; + msg->msg_fields = fields; + } + } + + if (msg->msg_flags == NULL) { + r = mhdriver_get_cached_flags(cache_db_flags, mmapstr, + session, msg->msg_index, &flags); + if (r == MAIL_NO_ERROR) { + msg->msg_flags = flags; + } + } + } + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + + r = mailsession_get_envelopes_list(get_ancestor(session), env_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto close_db_env; + } + + /* add flags */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_flags == NULL) + msg->msg_flags = mail_flags_new_empty(); + } + + /* must write cache */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields != NULL) { + if (!msg->msg_cached) { + r = write_cached_envelope(cache_db_env, mmapstr, + session, msg->msg_index, msg->msg_fields); + } + } + + if (msg->msg_flags != NULL) { + r = mhdriver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + } + } + + /* flush cache */ + + maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list); + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + + mmap_string_free(mmapstr); + + return MAIL_NO_ERROR; + + close_db_env: + mail_cache_db_close_unlock(filename_env, cache_db_env); + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + +static int mhdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, mh_cached_message_driver, num, 0); + if (r != MAIL_NO_ERROR) + return r; + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int mhdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t indx; + char *p; + struct mailmh_msg_info * mh_msg_info; + struct mailmh_folder * folder; + time_t mtime; + char * mtime_p; + chashdatum key; + chashdatum data; + int r; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + indx = (uint32_t) strtoul(uid, &p, 10); + if (p == uid || * p != '-') + return MAIL_ERROR_INVAL; + + folder = get_mh_cur_folder(session); + + mh_msg_info = NULL; + key.data = &indx; + key.len = sizeof(indx); + r = chash_get(folder->fl_msgs_hash, &key, &data); + if (r < 0) + return MAIL_ERROR_MSG_NOT_FOUND; + + mh_msg_info = data.data; + + mtime_p = p + 1; + + mtime = strtoul(mtime_p, &p, 10); + if ((* p == '-') && (mtime == mh_msg_info->msg_mtime)) { + size_t size; + char *size_p; + + size_p = p + 1; + size = strtoul(size_p, &p, 10); + if ((* p == '\0') && (size == mh_msg_info->msg_size)) + return mhdriver_cached_get_message(session, indx, result); + } + else if (*p != '-') { + return MAIL_ERROR_INVAL; + } + + return MAIL_ERROR_MSG_NOT_FOUND; +} diff --git a/Sources/libetpan/driver/implementation/mh/mhdriver_cached.h b/Sources/libetpan/driver/implementation/mh/mhdriver_cached.h new file mode 100644 index 00000000..de330c80 --- /dev/null +++ b/Sources/libetpan/driver/implementation/mh/mhdriver_cached.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver_cached.h,v 1.10 2004/11/21 21:53:33 hoa Exp $ + */ + +#ifndef MHDRIVER_CACHED_H + +#define MHDRIVER_CACHED_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * mh_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/mh/mhdriver_cached_message.c b/Sources/libetpan/driver/implementation/mh/mhdriver_cached_message.c new file mode 100644 index 00000000..55a6b10f --- /dev/null +++ b/Sources/libetpan/driver/implementation/mh/mhdriver_cached_message.c @@ -0,0 +1,344 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver_cached_message.c,v 1.26 2008/02/17 13:13:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mhdriver_message.h" + +#include "mailmessage_tools.h" +#include "mhdriver_tools.h" +#include "mhdriver_cached.h" +#include "mailmh.h" +#include "generic_cache.h" + +#include "mail_cache_db.h" + +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_SYS_MMAN_H +# include +#endif +#include +#include +#include +#include +#include + +static int mh_prefetch(mailmessage * msg_info); + +static void mh_prefetch_free(struct generic_message_t * msg); + +static int mh_initialize(mailmessage * msg_info); + +static int mh_fetch_size(mailmessage * msg_info, + size_t * result); + +static int mh_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +static void mh_uninitialize(mailmessage * msg_info); + +static void mh_flush(mailmessage * msg_info); + +static void mh_check(mailmessage * msg_info); + +static int mh_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static mailmessage_driver local_mh_cached_message_driver = { + /* msg_name */ "mh-cached", + + /* msg_initialize */ mh_initialize, + /* msg_uninitialize */ mh_uninitialize, + + /* msg_flush */ mh_flush, + /* msg_check */ mh_check, + + /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free, + + /* msg_fetch */ mailmessage_generic_fetch, + /* msg_fetch_header */ mh_fetch_header, + /* msg_fetch_body */ mailmessage_generic_fetch_body, + /* msg_fetch_size */ mh_fetch_size, + /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure, + /* msg_fetch_section */ mailmessage_generic_fetch_section, + /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header, + /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime, + /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body, + /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope, + + /* msg_get_flags */ mh_get_flags +}; + +mailmessage_driver * mh_cached_message_driver = +&local_mh_cached_message_driver; + +static inline struct mh_cached_session_state_data * +get_cached_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline mailsession * get_ancestor_session(mailmessage * msg) +{ + return get_cached_session_data(msg)->mh_ancestor; +} + +static inline struct mh_session_state_data * +get_ancestor_session_data(mailmessage * msg) +{ + return get_ancestor_session(msg)->sess_data; +} + +static inline struct mailmh * +get_mh_session(mailmessage * msg) +{ + return get_ancestor_session_data(msg)->mh_session; +} + +static inline struct mailmh_folder * +get_mh_cur_folder(mailmessage * msg) +{ + return get_ancestor_session_data(msg)->mh_cur_folder; +} + +static int mh_prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + r = mhdriver_fetch_message(get_ancestor_session(msg_info), + msg_info->msg_index, &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void mh_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static int mh_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + char static_uid[PATH_MAX]; + struct mailmh_msg_info * mh_msg_info; + chashdatum key; + chashdatum data; + struct mailmh_folder * folder; + + folder = get_mh_cur_folder(msg_info); + + key.data = &msg_info->msg_index; + key.len = sizeof(msg_info->msg_index); + r = chash_get(folder->fl_msgs_hash, &key, &data); + if (r < 0) + return MAIL_ERROR_INVAL; + + mh_msg_info = data.data; + + snprintf(static_uid, PATH_MAX, "%u-%lld-%zu", msg_info->msg_index, + (long long)mh_msg_info->msg_mtime, mh_msg_info->msg_size); + uid = strdup(static_uid); + if (uid == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + return r; + } + + msg = msg_info->msg_data; + msg->msg_prefetch = mh_prefetch; + msg->msg_prefetch_free = mh_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; +} + +static void mh_uninitialize(mailmessage * msg_info) +{ + mailmessage_generic_uninitialize(msg_info); +} + + +#define FLAGS_NAME "flags.db" + +static void mh_flush(mailmessage * msg_info) +{ + mailmessage_generic_flush(msg_info); +} + +static void mh_check(mailmessage * msg_info) +{ + if (msg_info->msg_flags != NULL) { + mail_flags_store_set(get_cached_session_data(msg_info)->mh_flags_store, + msg_info); + /* ignore errors */ + } +} + +static int mh_fetch_size(mailmessage * msg_info, + size_t * result) +{ + int r; + size_t size; + + r = mhdriver_fetch_size(get_ancestor_session(msg_info), + msg_info->msg_index, &size); + if (r != MAIL_NO_ERROR) + return r; + + * result = size; + + return MAIL_NO_ERROR; +} + +static int mh_get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + int r; + struct mail_flags * flags; + struct mail_cache_db * cache_db_flags; + char filename_flags[PATH_MAX]; + int res; + struct mh_cached_session_state_data * cached_data; + MMAPString * mmapstr; + + if (msg_info->msg_flags != NULL) { + * result = msg_info->msg_flags; + + return MAIL_NO_ERROR; + } + + cached_data = get_cached_session_data(msg_info); + + flags = mail_flags_store_get(cached_data->mh_flags_store, + msg_info->msg_index); + + if (flags == NULL) { + if (cached_data->mh_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->mh_flags_directory, + cached_data->mh_quoted_mb, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + r = mhdriver_get_cached_flags(cache_db_flags, mmapstr, + msg_info->msg_session, msg_info->msg_index, &flags); + if (r != MAIL_NO_ERROR) { + flags = mail_flags_new_empty(); + if (flags == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + } + + msg_info->msg_flags = flags; + + * result = flags; + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int mh_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + msg = msg_info->msg_data; + if (msg->msg_message != NULL) { + return mailmessage_generic_fetch_header(msg_info, result, result_len); + } + else { + r = mhdriver_fetch_header(get_ancestor_session(msg_info), + msg_info->msg_index, &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; + } +} diff --git a/Sources/libetpan/driver/implementation/mh/mhdriver_cached_message.h b/Sources/libetpan/driver/implementation/mh/mhdriver_cached_message.h new file mode 100644 index 00000000..8b407c36 --- /dev/null +++ b/Sources/libetpan/driver/implementation/mh/mhdriver_cached_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver_cached_message.h,v 1.6 2004/11/21 21:53:33 hoa Exp $ + */ + +#ifndef MHDRIVER_CACHED_MESSAGE_H + +#define MHDRIVER_CACHED_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * mh_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/mh/mhdriver_message.c b/Sources/libetpan/driver/implementation/mh/mhdriver_message.c new file mode 100644 index 00000000..b2265099 --- /dev/null +++ b/Sources/libetpan/driver/implementation/mh/mhdriver_message.c @@ -0,0 +1,221 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver_message.c,v 1.23 2008/02/17 13:13:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mhdriver_message.h" + +#include "mailmessage_tools.h" +#include "mhdriver_tools.h" +#include "mhdriver.h" +#include "mailmh.h" + +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_SYS_MMAN_H +# include +#endif +#include +#include +#include +#include +#include + +static int mh_prefetch(mailmessage * msg_info); + +static void mh_prefetch_free(struct generic_message_t * msg); + +static int mh_initialize(mailmessage * msg_info); + +static int mh_fetch_size(mailmessage * msg_info, + size_t * result); + +static int mh_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static mailmessage_driver local_mh_message_driver = { + /* msg_name */ "mh", + + /* msg_initialize */ mh_initialize, + /* msg_uninitialize */ mailmessage_generic_uninitialize, + + /* msg_flush */ mailmessage_generic_flush, + /* msg_check */ NULL, + + /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free, + + /* msg_fetch */ mailmessage_generic_fetch, + /* msg_fetch_header */ mh_fetch_header, + /* msg_fetch_body */ mailmessage_generic_fetch_body, + /* msg_fetch_size */ mh_fetch_size, + /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure, + /* msg_fetch_section */ mailmessage_generic_fetch_section, + /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header, + /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime, + /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body, + /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope, + + /* msg_get_flags */ NULL +}; + +mailmessage_driver * mh_message_driver = &local_mh_message_driver; + +static int mh_prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + r = mhdriver_fetch_message(msg_info->msg_session, msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void mh_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static inline struct mh_session_state_data * get_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline struct mailmh_folder * get_mh_cur_folder(mailmessage * msg) +{ + return get_data(msg)->mh_cur_folder; +} + +static int mh_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + char static_uid[PATH_MAX]; + struct mailmh_msg_info * mh_msg_info; + chashdatum key; + chashdatum value; + + key.data = &msg_info->msg_index; + key.len = sizeof(msg_info->msg_index); + r = chash_get(get_mh_cur_folder(msg_info)->fl_msgs_hash, &key, &value); + if (r < 0) + return MAIL_ERROR_INVAL; + + mh_msg_info = value.data; + + snprintf(static_uid, PATH_MAX, "%u-%lu-%lu", msg_info->msg_index, + (unsigned long) mh_msg_info->msg_mtime, + (unsigned long) mh_msg_info->msg_size); + uid = strdup(static_uid); + if (uid == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + return r; + } + + msg = msg_info->msg_data; + msg->msg_prefetch = mh_prefetch; + msg->msg_prefetch_free = mh_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; +} + + +static int mh_fetch_size(mailmessage * msg_info, + size_t * result) +{ + int r; + size_t size; + + r = mhdriver_fetch_size(msg_info->msg_session, msg_info->msg_index, &size); + if (r != MAIL_NO_ERROR) + return r; + + * result = size; + + return MAIL_NO_ERROR; +} + + + + +static int mh_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + msg = msg_info->msg_data; + if (msg->msg_message != NULL) { + + r = mailmessage_generic_fetch_header(msg_info, result, result_len); + return r; + } + else { + r = mhdriver_fetch_header(msg_info->msg_session, msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; + } +} diff --git a/Sources/libetpan/driver/implementation/mh/mhdriver_message.h b/Sources/libetpan/driver/implementation/mh/mhdriver_message.h new file mode 100644 index 00000000..8b86b560 --- /dev/null +++ b/Sources/libetpan/driver/implementation/mh/mhdriver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver_message.h,v 1.6 2004/11/21 21:53:33 hoa Exp $ + */ + +#ifndef MHDRIVER_MESSAGE_H + +#define MHDRIVER_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * mh_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/mh/mhdriver_tools.c b/Sources/libetpan/driver/implementation/mh/mhdriver_tools.c new file mode 100644 index 00000000..ed70ec3b --- /dev/null +++ b/Sources/libetpan/driver/implementation/mh/mhdriver_tools.c @@ -0,0 +1,493 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver_tools.c,v 1.27 2008/02/20 22:15:50 hoa Exp $ + */ +#define HAVE_CONFIG_H 1 + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mhdriver_tools.h" + +#include "mailmessage.h" +#include "mhdriver.h" +#include "mhdriver_cached.h" +#include "maildriver_types.h" +#include "mailmh.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "mail_cache_db.h" + +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_SYS_MMAN_H +# include +#endif +#include +#include +#include +#include +#include +#ifdef WIN32 +# include "win_etpan.h" +#endif + +int mhdriver_mh_error_to_mail_error(int error) +{ + switch (error) { + case MAILMH_NO_ERROR: + return MAIL_NO_ERROR; + + case MAILMH_ERROR_FOLDER: + return MAIL_ERROR_FOLDER; + + case MAILMH_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case MAILMH_ERROR_FILE: + return MAIL_ERROR_FILE; + + case MAILMH_ERROR_COULD_NOT_ALLOC_MSG: + return MAIL_ERROR_APPEND; + + case MAILMH_ERROR_RENAME: + return MAIL_ERROR_RENAME; + + case MAILMH_ERROR_MSG_NOT_FOUND: + return MAIL_ERROR_MSG_NOT_FOUND; + + default: + return MAIL_ERROR_INVAL; + } +} + + +static inline struct mh_session_state_data * get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline struct mailmh_folder * get_mh_cur_folder(mailsession * session) +{ + return get_data(session)->mh_cur_folder; +} + +static inline struct mh_cached_session_state_data * +cached_get_data(mailsession * session) +{ + return session->sess_data; +} + + +static inline mailsession * cached_get_ancestor(mailsession * session) +{ + return cached_get_data(session)->mh_ancestor; +} + +static inline struct mh_session_state_data * +cached_get_ancestor_data(mailsession * session) +{ + return get_data(cached_get_ancestor(session)); +} + +static inline struct mailmh_folder * +cached_get_mh_cur_folder(mailsession * session) +{ + return get_mh_cur_folder(cached_get_ancestor(session)); +} + +int mhdriver_fetch_message(mailsession * session, uint32_t indx, + char ** result, size_t * result_len) +{ + size_t size; + size_t cur_token; + struct mailmh_folder * folder; + int fd; + MMAPString * mmapstr; + char * str; + int res; + int r; + + folder = get_mh_cur_folder(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + r = mailmh_folder_get_message_fd(folder, indx, O_RDONLY, &fd); + + switch (r) { + case MAILMH_NO_ERROR: + break; + + default: + res = mhdriver_mh_error_to_mail_error(r); + goto close; + } + + r = mhdriver_fetch_size(session, indx, &size); + + switch (r) { + case MAILMH_NO_ERROR: + break; + + default: + res = mhdriver_mh_error_to_mail_error(r); + goto close; + } + + str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); + if (str == (char *)MAP_FAILED) { + res = MAIL_ERROR_FETCH; + goto close; + } + + /* strip "From " header for broken implementations */ + /* XXX - called twice, make a function */ + cur_token = 0; + if (size > 5) { + if (strncmp("From ", str, 5) == 0) { + cur_token += 5; + + while (1) { + if (str[cur_token] == '\n') { + cur_token ++; + break; + } + if (cur_token >= size) + break; + cur_token ++; + } + } + } + + mmapstr = mmap_string_new_len(str + cur_token, size - cur_token); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto unmap; + } + + if (mmap_string_ref(mmapstr) != 0) { + res = MAIL_ERROR_MEMORY; + goto free_str; + } + + munmap(str, size); + close(fd); + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + free_str: + mmap_string_free(mmapstr); + unmap: + munmap(str, size); + close: + close(fd); + err: + return res; +} + + +int mhdriver_fetch_header(mailsession * session, uint32_t indx, + char ** result, size_t * result_len) +{ + size_t size; + size_t cur_token; + size_t begin; + struct mailmh_folder * folder; + int fd; + MMAPString * mmapstr; + char * str; + int res; + int r; + + folder = get_mh_cur_folder(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + r = mailmh_folder_get_message_fd(folder, indx, O_RDONLY, &fd); + + switch (r) { + case MAILMH_NO_ERROR: + break; + + default: + res = mhdriver_mh_error_to_mail_error(r); + goto close; + } + + r = mhdriver_fetch_size(session, indx, &size); + + switch (r) { + case MAILMH_NO_ERROR: + break; + + default: + res = mhdriver_mh_error_to_mail_error(r); + goto close; + } + + str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); + if (str == (char *)MAP_FAILED) { + res = MAIL_ERROR_FETCH; + goto close; + } + + /* strip "From " header for broken implementations */ + cur_token = 0; + if (size > 5) { + if (strncmp("From ", str, 5) == 0) { + cur_token += 5; + + while (1) { + if (str[cur_token] == '\n') { + cur_token ++; + break; + } + if (cur_token >= size) + break; + cur_token ++; + } + } + } + + begin = cur_token; + + while (1) { + r = mailimf_ignore_field_parse(str, size, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + mailimf_crlf_parse(str, size, &cur_token); + + mmapstr = mmap_string_new_len(str + begin, cur_token - begin); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto unmap; + } + + if (mmap_string_ref(mmapstr) != 0) { + res = MAIL_ERROR_MEMORY; + goto free_str; + } + + munmap(str, size); + close(fd); + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + free_str: + mmap_string_free(mmapstr); + unmap: + munmap(str, size); + close: + close(fd); + err: + return res; +} + + +int mhdriver_fetch_size(mailsession * session, uint32_t indx, + size_t * result) +{ + struct mailmh_folder * folder; + int r; + struct stat buf; + char * name; + + folder = get_mh_cur_folder(session); + if (folder == NULL) + return MAIL_ERROR_FETCH; + + r = mailmh_folder_get_message_filename(folder, indx, &name); + + switch (r) { + case MAILMH_NO_ERROR: + break; + + default: + return mhdriver_mh_error_to_mail_error(r); + } + + r = stat(name, &buf); + free(name); + if (r == -1) + return MAIL_ERROR_FETCH; + + * result = buf.st_size; + + return MAIL_NO_ERROR; +} + +int +mhdriver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, + uint32_t num, + struct mail_flags ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mail_flags * flags; + int res; + struct mailmh_msg_info * msg_info; + chashdatum key; + chashdatum data; + struct mailmh_folder * folder; + + folder = cached_get_mh_cur_folder(session); + key.data = # + key.len = sizeof(num); + r = chash_get(folder->fl_msgs_hash, &key, &data); + if (r < 0) + return MAIL_ERROR_CACHE_MISS; + msg_info = data.data; + + snprintf(keyname, PATH_MAX, "%u-%lu-%lu-flags", + num, (unsigned long) msg_info->msg_mtime, + (unsigned long) msg_info->msg_size); + + r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = flags; + + return MAIL_NO_ERROR; + + err: + return res; +} + +int +mhdriver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, + struct mail_flags * flags) +{ + int r; + char keyname[PATH_MAX]; + int res; + + snprintf(keyname, PATH_MAX, "%s-flags", uid); + + r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + +int mh_get_messages_list(struct mailmh_folder * folder, + mailsession * session, mailmessage_driver * driver, + struct mailmessage_list ** result) +{ + unsigned int i; + struct mailmessage_list * env_list; + int r; + carray * tab; + int res; + + tab = carray_new(128); + if (tab == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) { + struct mailmh_msg_info * mh_info; + mailmessage * msg; + + mh_info = carray_get(folder->fl_msgs_tab, i); + if (mh_info == NULL) + continue; + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = mailmessage_init(msg, session, driver, + mh_info->msg_index, mh_info->msg_size); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = carray_add(tab, msg, NULL); + if (r < 0) { + mailmessage_free(msg); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + env_list = mailmessage_list_new(tab); + if (env_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = env_list; + + return MAIL_NO_ERROR; + + free_list: + for(i = 0 ; i < carray_count(tab) ; i ++) + mailmessage_free(carray_get(tab, i)); + carray_free(tab); + err: + return res; +} diff --git a/Sources/libetpan/driver/implementation/mh/mhdriver_tools.h b/Sources/libetpan/driver/implementation/mh/mhdriver_tools.h new file mode 100644 index 00000000..420ff52b --- /dev/null +++ b/Sources/libetpan/driver/implementation/mh/mhdriver_tools.h @@ -0,0 +1,80 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver_tools.h,v 1.11 2008/02/20 22:15:50 hoa Exp $ + */ + +#ifndef MHDRIVER_TOOLS_H + +#define MHDRIVER_TOOLS_H + +#include "maildriver_types.h" +#include "mail_cache_db_types.h" +#include "mailmh.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int mhdriver_mh_error_to_mail_error(int error); + +int mhdriver_fetch_message(mailsession * session, uint32_t indx, + char ** result, size_t * result_len); + +int mhdriver_fetch_header(mailsession * session, uint32_t indx, + char ** result, size_t * result_len); + +int mhdriver_fetch_size(mailsession * session, uint32_t indx, + size_t * result); + +int +mhdriver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, + uint32_t num, + struct mail_flags ** result); + +int +mhdriver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, + struct mail_flags * flags); + +int mh_get_messages_list(struct mailmh_folder * folder, + mailsession * session, mailmessage_driver * driver, + struct mailmessage_list ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/mh/mhdriver_types.h b/Sources/libetpan/driver/implementation/mh/mhdriver_types.h new file mode 100644 index 00000000..f8bb3c39 --- /dev/null +++ b/Sources/libetpan/driver/implementation/mh/mhdriver_types.h @@ -0,0 +1,100 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver_types.h,v 1.8 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifndef MHDRIVER_TYPES_H + +#define MHDRIVER_TYPES_H + +#include + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct mh_session_state_data { + struct mailmh * mh_session; + + struct mailmh_folder * mh_cur_folder; + + clist * mh_subscribed_list; +}; + +enum { + MHDRIVER_CACHED_SET_CACHE_DIRECTORY = 1, + MHDRIVER_CACHED_SET_FLAGS_DIRECTORY +}; + +struct mh_cached_session_state_data { + mailsession * mh_ancestor; + char * mh_quoted_mb; + char mh_cache_directory[PATH_MAX]; + char mh_flags_directory[PATH_MAX]; + struct mail_flags_store * mh_flags_store; +}; + +/* mh storage */ + +/* + mh_mailstorage is the state data specific to the MH storage. + + - pathname is the root path of the MH storage. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache. + + - flags_directory is the location of the flags. +*/ + +struct mh_mailstorage { + char * mh_pathname; + + int mh_cached; + char * mh_cache_directory; + char * mh_flags_directory; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/mh/mhstorage.c b/Sources/libetpan/driver/implementation/mh/mhstorage.c new file mode 100644 index 00000000..d66e8b8a --- /dev/null +++ b/Sources/libetpan/driver/implementation/mh/mhstorage.c @@ -0,0 +1,197 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhstorage.c,v 1.14 2008/02/17 13:13:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mhstorage.h" + +#include "mhdriver.h" +#include "mhdriver_cached.h" +#include "mail.h" + +#include +#include + +/* mh storage */ + +static int mh_mailstorage_connect(struct mailstorage * storage); +static int mh_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result); +static void mh_mailstorage_uninitialize(struct mailstorage * storage); + +static mailstorage_driver mh_mailstorage_driver = { + /* sto_name */ "mh", + /* sto_connect */ mh_mailstorage_connect, + /* sto_get_folder_session */ mh_mailstorage_get_folder_session, + /* sto_uninitialize */ mh_mailstorage_uninitialize +}; + +LIBETPAN_EXPORT +int mh_mailstorage_init(struct mailstorage * storage, + const char * mh_pathname, int mh_cached, + const char * mh_cache_directory, const char * mh_flags_directory) +{ + struct mh_mailstorage * mh_storage; + + mh_storage = malloc(sizeof(* mh_storage)); + if (mh_storage == NULL) + goto err; + + mh_storage->mh_pathname = strdup(mh_pathname); + if (mh_storage->mh_pathname == NULL) + goto free; + + mh_storage->mh_cached = mh_cached; + + if (mh_cached && (mh_cache_directory != NULL) && + (mh_flags_directory != NULL)) { + mh_storage->mh_cache_directory = strdup(mh_cache_directory); + if (mh_storage->mh_cache_directory == NULL) + goto free_pathname; + mh_storage->mh_flags_directory = strdup(mh_flags_directory); + if (mh_storage->mh_flags_directory == NULL) + goto free_cache_directory; + } + else { + mh_storage->mh_cached = FALSE; + mh_storage->mh_cache_directory = NULL; + mh_storage->mh_flags_directory = NULL; + } + + storage->sto_data = mh_storage; + storage->sto_driver = &mh_mailstorage_driver; + + return MAIL_NO_ERROR; + + free_cache_directory: + free(mh_storage->mh_cache_directory); + free_pathname: + free(mh_storage->mh_pathname); + free: + free(mh_storage); + err: + return MAIL_ERROR_MEMORY; +} + +static void mh_mailstorage_uninitialize(struct mailstorage * storage) +{ + struct mh_mailstorage * mh_storage; + + mh_storage = storage->sto_data; + if (mh_storage->mh_flags_directory != NULL) + free(mh_storage->mh_flags_directory); + if (mh_storage->mh_cache_directory != NULL) + free(mh_storage->mh_cache_directory); + free(mh_storage->mh_pathname); + free(mh_storage); + + storage->sto_data = NULL; +} + +static int mh_mailstorage_connect(struct mailstorage * storage) +{ + struct mh_mailstorage * mh_storage; + mailsession_driver * driver; + int r; + int res; + mailsession * session; + + mh_storage = storage->sto_data; + + if (mh_storage->mh_cached) + driver = mh_cached_session_driver; + else + driver = mh_session_driver; + + session = mailsession_new(driver); + if (session == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if (mh_storage->mh_cached) { + r = mailsession_parameters(session, + MHDRIVER_CACHED_SET_CACHE_DIRECTORY, + mh_storage->mh_cache_directory); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + r = mailsession_parameters(session, + MHDRIVER_CACHED_SET_FLAGS_DIRECTORY, + mh_storage->mh_flags_directory); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + } + + r = mailsession_connect_path(session, mh_storage->mh_pathname); + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto free; + } + + storage->sto_session = session; + + return MAIL_NO_ERROR; + + free: + mailsession_free(session); + err: + return res; +} + +static int mh_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result) +{ + int r; + + r = mailsession_select_folder(storage->sto_session, pathname); + if (r != MAIL_NO_ERROR) + return r; + + * result = storage->sto_session; + + return MAIL_NO_ERROR; +} diff --git a/Sources/libetpan/driver/implementation/mh/mhstorage.h b/Sources/libetpan/driver/implementation/mh/mhstorage.h new file mode 100644 index 00000000..e722bcf2 --- /dev/null +++ b/Sources/libetpan/driver/implementation/mh/mhstorage.h @@ -0,0 +1,68 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhstorage.h,v 1.8 2006/06/02 15:44:29 smarinier Exp $ + */ + +#ifndef MHSTORAGE_H + +#define MHSTORAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mh_mailstorage_init is the constructor for a MH storage + + @param pathname is the filename the root path of the MH storage. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache. + + @param flags_directory is the location of the flags. +*/ + +LIBETPAN_EXPORT +int mh_mailstorage_init(struct mailstorage * storage, + const char * mh_pathname, int mh_cached, + const char * mh_cache_directory, const char * mh_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/mime-message/Makefile.am b/Sources/libetpan/driver/implementation/mime-message/Makefile.am new file mode 100644 index 00000000..fd1dce7c --- /dev/null +++ b/Sources/libetpan/driver/implementation/mime-message/Makefile.am @@ -0,0 +1,42 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +etpaninclude_HEADERS = \ + mime_message_driver.h + +AM_CPPFLAGS = -I$(top_builddir)/include \ + -I$(top_srcdir)/src/driver/interface \ + -I$(top_srcdir)/src/data-types + +noinst_LTLIBRARIES = libmime-message.la + +libmime_message_la_SOURCES = \ + mime_message_driver.c diff --git a/Sources/libetpan/driver/implementation/mime-message/mime_message_driver.c b/Sources/libetpan/driver/implementation/mime-message/mime_message_driver.c new file mode 100644 index 00000000..8c6428b5 --- /dev/null +++ b/Sources/libetpan/driver/implementation/mime-message/mime_message_driver.c @@ -0,0 +1,511 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mime_message_driver.c,v 1.13 2008/02/17 13:13:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mime_message_driver.h" + +#include "libetpan-config.h" + +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_SYS_MMAN_H +# include +#endif +#include +#include + +#include "mailmessage.h" +#include "mailmessage_tools.h" +#include "maildriver_tools.h" + +int mime_message_set_tmpdir(mailmessage * msg, char * tmpdir) +{ + /* not used now */ + return MAIL_NO_ERROR; +} + +void mime_message_detach_mime(mailmessage * msg) +{ + msg->msg_mime = NULL; +} + +mailmessage * mime_message_init(struct mailmime * mime) +{ + mailmessage * msg; + int r; + + msg = mailmessage_new(); + if (msg == NULL) + goto err; + + r = mailmessage_init(msg, NULL, mime_message_driver, 0, 0); + if (r != MAIL_NO_ERROR) + goto free; + + if (mime != NULL) { + mailmime_free(msg->msg_mime); + msg->msg_mime = mime; + } + + return msg; + + free: + mailmessage_free(msg); + err: + return NULL; +} + +static int initialize(mailmessage * msg) +{ + struct mailmime * mime; + int res; + + mime = mailmime_new_message_data(NULL); + if (mime == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + msg->msg_mime = mime; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static void uninitialize(mailmessage * msg) +{ + /* tmp dir name */ + if (msg->msg_data != NULL) + free(msg->msg_data); + + if (msg->msg_mime != NULL) + mailmime_free(msg->msg_mime); + msg->msg_mime = NULL; +} + +static void flush(mailmessage * msg) +{ + /* do nothing */ +} + +static void check(mailmessage * msg) +{ + /* do nothing */ +} + +static void fetch_result_free(mailmessage * msg_info, char * content) +{ + mmap_string_unref(content); +} + +static int body_to_mmapstr(char * data, size_t size, + char ** result, size_t * result_len) +{ + MMAPString * mmapstr; + size_t cur_token; + int res; + int r; + + cur_token = 0; + + /* skip header */ + + while (1) { + r = mailimf_ignore_field_parse(data, size, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + + r = mailimf_crlf_parse(data, size, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = maildriver_imf_error_to_mail_error(r); + goto err; + } + + mmapstr = mmap_string_new_len(data + cur_token, size - cur_token); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r != 0) { + mmap_string_free(mmapstr); + res = MAIL_ERROR_MEMORY; + + goto err; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int body_body_to_mmapstr(char * data, size_t size, + char ** result, size_t * result_len) +{ + size_t cur_token; + int res; + int r; + + cur_token = 0; + + /* skip header */ + + /* MIME header */ + + while (1) { + r = mailimf_ignore_field_parse(data, size, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + + r = mailimf_crlf_parse(data, size, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = maildriver_imf_error_to_mail_error(r); + goto err; + } + + return body_to_mmapstr(data + cur_token, size - cur_token, + result, result_len); + + err: + return res; +} + + +static int fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + int r; + int res; + int col; + MMAPString * str; + + if (msg_info->msg_mime == NULL) + return MAIL_ERROR_INVAL; + + str = mmap_string_new(""); + if (str == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + col = 0; + r = mailmime_write_mem(str, &col, mime); + if (r != MAILIMF_NO_ERROR) { + res = maildriver_imf_error_to_mail_error(r); + goto free; + } + + if (mime->mm_parent == NULL) { + r = mmap_string_ref(str); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + * result = str->str; + * result_len = str->len; + + r = MAIL_NO_ERROR; + } + else { + r = body_to_mmapstr(str->str, str->len, result, result_len); + if (r == MAIL_NO_ERROR) { + mmap_string_free(str); + } + } + + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + return MAIL_NO_ERROR; + + free: + mmap_string_free(str); + err: + return res; +} + + +static int fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + int r; + int res; + int col; + MMAPString * str; + + if (msg_info->msg_mime == NULL) + return MAIL_ERROR_INVAL; + + str = mmap_string_new(""); + if (str == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + col = 0; + if (mime->mm_type == MAILMIME_MESSAGE) { + if (mime->mm_data.mm_message.mm_fields != NULL) { + r = mailimf_fields_write_mem(str, &col, mime->mm_data.mm_message.mm_fields); + if (r != MAILIMF_NO_ERROR) { + res = maildriver_imf_error_to_mail_error(r); + goto free; + } + mailimf_string_write_mem(str, &col, "\r\n", 2); + } + } + + r = mmap_string_ref(str); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + * result = str->str; + * result_len = str->len; + + return MAIL_NO_ERROR; + + free: + mmap_string_free(str); + err: + return res; +} + + +static int fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + int r; + int res; + int col; + MMAPString * str; + + if (msg_info->msg_mime == NULL) + return MAIL_ERROR_INVAL; + + str = mmap_string_new(""); + if (str == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + col = 0; + if (mime->mm_content_type != NULL) { + r = mailmime_content_write_mem(str, &col, mime->mm_content_type); + if (r != MAILIMF_NO_ERROR) { + res = maildriver_imf_error_to_mail_error(r); + goto free; + } + } + if (mime->mm_mime_fields != NULL) { + r = mailmime_fields_write_mem(str, &col, mime->mm_mime_fields); + if (r != MAILIMF_NO_ERROR) { + res = maildriver_imf_error_to_mail_error(r); + goto free; + } + } + mailimf_string_write_mem(str, &col, "\r\n", 2); + + r = mmap_string_ref(str); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + * result = str->str; + * result_len = str->len; + + return MAIL_NO_ERROR; + + free: + mmap_string_free(str); + err: + return res; +} + + + +static int fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + int r; + int res; + int col; + MMAPString * str; + + if (msg_info->msg_mime == NULL) + return MAIL_ERROR_INVAL; + + str = mmap_string_new(""); + if (str == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + col = 0; + if (mime->mm_mime_fields != NULL) { + r = mailmime_write_mem(str, &col, mime); + if (r != MAILIMF_NO_ERROR) { + res = maildriver_imf_error_to_mail_error(r); + goto free; + } + } + + if (mime->mm_type == MAILMIME_MESSAGE) + r = body_body_to_mmapstr(str->str, str->len, result, result_len); + else + r = body_to_mmapstr(str->str, str->len, result, result_len); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + mmap_string_free(str); + + return MAIL_NO_ERROR; + + free: + mmap_string_free(str); + err: + return res; +} + + +static int get_bodystructure(mailmessage * msg_info, + struct mailmime ** result) +{ + if (msg_info->msg_mime == NULL) + return MAIL_ERROR_INVAL; + + * result = msg_info->msg_mime; + + return MAIL_NO_ERROR; +} + + +static int fetch(mailmessage * msg_info, + char ** result, size_t * result_len) +{ + return fetch_section(msg_info, msg_info->msg_mime, result, result_len); +} + +static int fetch_header(mailmessage * msg_info, + char ** result, size_t * result_len) +{ + return fetch_section_header(msg_info, + msg_info->msg_mime, result, result_len); +} + +static int fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len) +{ + return fetch_section_body(msg_info, msg_info->msg_mime, result, result_len); +} + + +static int fetch_size(mailmessage * msg_info, + size_t * result) +{ + char * msg; + int r; + + msg = NULL; + r = fetch(msg_info, &msg, result); + if (r != MAIL_NO_ERROR) { + return r; + } + + fetch_result_free(msg_info, msg); + + return MAIL_NO_ERROR; +} + + +static mailmessage_driver local_mime_message_driver = { + /* msg_name */ "mime", + + /* msg_initialize */ initialize, + /* msg_uninitialize */ uninitialize, + + /* msg_flush */ flush, + /* msg_check */ check, + + /* msg_fetch_result_free */ fetch_result_free, + + /* msg_fetch */ fetch, + /* msg_fetch_header */ fetch_header, + /* msg_fetch_body */ fetch_body, + /* msg_fetch_size */ fetch_size, + /* msg_get_bodystructure */ get_bodystructure, + /* msg_fetch_section */ fetch_section, + /* msg_fetch_section_header */ fetch_section_header, + /* msg_fetch_section_mime */ fetch_section_mime, + /* msg_fetch_section_body */ fetch_section_body, + /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope, + + /* msg_get_flags */ NULL +}; + +mailmessage_driver * mime_message_driver = &local_mime_message_driver; diff --git a/Sources/libetpan/driver/implementation/mime-message/mime_message_driver.h b/Sources/libetpan/driver/implementation/mime-message/mime_message_driver.h new file mode 100644 index 00000000..2ad587ec --- /dev/null +++ b/Sources/libetpan/driver/implementation/mime-message/mime_message_driver.h @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mime_message_driver.h,v 1.5 2004/12/13 23:18:28 hoa Exp $ + */ + +#ifndef MIME_MESSAGE_DRIVER_H + +#define MIME_MESSAGE_DRIVER_H + +#include + +#define LIBETPAN_MIME_MESSAGE + +extern mailmessage_driver * mime_message_driver; + +mailmessage * mime_message_init(struct mailmime * mime); + +void mime_message_detach_mime(mailmessage * msg); + +/* deprecated */ +int mime_message_set_tmpdir(mailmessage * msg, char * tmpdir); + +#endif diff --git a/Sources/libetpan/driver/implementation/nntp/Makefile.am b/Sources/libetpan/driver/implementation/nntp/Makefile.am new file mode 100644 index 00000000..f89e4e19 --- /dev/null +++ b/Sources/libetpan/driver/implementation/nntp/Makefile.am @@ -0,0 +1,56 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +etpaninclude_HEADERS = \ + nntpdriver.h \ + nntpdriver_cached.h \ + nntpdriver_cached_message.h \ + nntpdriver_message.h \ + nntpdriver_types.h \ + nntpstorage.h + +AM_CPPFLAGS = -I$(top_builddir)/include \ + -I$(top_srcdir)/src/driver/interface \ + -I$(top_srcdir)/src/driver/tools \ + -I$(top_srcdir)/src/low-level/nntp \ + -I$(top_srcdir)/src/low-level/mime \ + -I$(top_srcdir)/src/low-level/imf \ + -I$(top_srcdir)/src/data-types + +noinst_LTLIBRARIES = libnntp.la + +libnntp_la_SOURCES = \ + nntpdriver.c \ + nntpdriver_cached.c \ + nntpdriver_cached_message.c \ + nntpdriver_message.c \ + nntpdriver_tools.h nntpdriver_tools.c \ + nntpstorage.c diff --git a/Sources/libetpan/driver/implementation/nntp/nntpdriver.c b/Sources/libetpan/driver/implementation/nntp/nntpdriver.c new file mode 100644 index 00000000..21527df1 --- /dev/null +++ b/Sources/libetpan/driver/implementation/nntp/nntpdriver.c @@ -0,0 +1,1187 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver.c,v 1.53 2009/08/29 18:36:31 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "nntpdriver.h" + +#include +#include + +#include "mail.h" +#include "mailmessage.h" +#include "nntpdriver_tools.h" +#include "maildriver_tools.h" +#include "nntpdriver_message.h" + +static int nntpdriver_initialize(mailsession * session); + +static void nntpdriver_uninitialize(mailsession * session); + +static int nntpdriver_parameters(mailsession * session, + int id, void * value); + +static int nntpdriver_connect_stream(mailsession * session, mailstream * s); + +static int nntpdriver_login(mailsession * session, + const char * userid, const char * password); + +static int nntpdriver_logout(mailsession * session); + +static int nntpdriver_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, + uint32_t * result_recent, + uint32_t * result_unseen); + +static int nntpdriver_messages_number(mailsession * session, const char * mb, + uint32_t * result); + +static int nntpdriver_append_message(mailsession * session, + const char * message, size_t size); + +static int nntpdriver_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); + +static int +nntpdriver_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + + +static int nntpdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int nntpdriver_list_folders(mailsession * session, const char * mb, + struct mail_list ** result); + +static int nntpdriver_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result); + +static int nntpdriver_subscribe_folder(mailsession * session, const char * mb); + +static int nntpdriver_unsubscribe_folder(mailsession * session, const char * mb); + +static int nntpdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int nntpdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static int nntpdriver_noop(mailsession * session); + +static mailsession_driver local_nntp_session_driver = { + /* sess_name */ "nntp", + + /* sess_initialize */ nntpdriver_initialize, + /* sess_uninitialize */ nntpdriver_uninitialize, + + /* sess_parameters */ nntpdriver_parameters, + + /* sess_connect_stream */ nntpdriver_connect_stream, + /* sess_connect_path */ NULL, + /* sess_starttls */ NULL, + /* sess_login */ nntpdriver_login, + /* sess_logout */ nntpdriver_logout, + /* sess_noop */ nntpdriver_noop, + + /* sess_build_folder_name */ NULL, + /* sess_create_folder */ NULL, + /* sess_delete_folder */ NULL, + /* sess_rename_folder */ NULL, + /* sess_check_folder */ NULL, + /* sess_examine_folder */ NULL, + /* sess_select_folder */ nntpdriver_select_folder, + /* sess_expunge_folder */ NULL, + /* sess_status_folder */ nntpdriver_status_folder, + /* sess_messages_number */ nntpdriver_messages_number, + /* sess_recent_number */ nntpdriver_messages_number, + /* sess_unseen_number */ nntpdriver_messages_number, + /* sess_list_folders */ nntpdriver_list_folders, + /* sess_lsub_folders */ nntpdriver_lsub_folders, + /* sess_subscribe_folder */ nntpdriver_subscribe_folder, + /* sess_unsubscribe_folder */ nntpdriver_unsubscribe_folder, + + /* sess_append_message */ nntpdriver_append_message, + /* sess_append_message_flags */ nntpdriver_append_message_flags, + /* sess_copy_message */ NULL, + /* sess_move_message */ NULL, + + /* sess_get_message */ nntpdriver_get_message, + /* sess_get_message_by_uid */ nntpdriver_get_message_by_uid, + + /* sess_get_messages_list */ nntpdriver_get_messages_list, + /* sess_get_envelopes_list */ nntpdriver_get_envelopes_list, + /* sess_remove_message */ NULL, +#if 0 + /* sess_search_messages */ maildriver_generic_search_messages, +#endif + /* sess_login_sasl */ NULL +}; + + +mailsession_driver * nntp_session_driver = &local_nntp_session_driver; + +static inline struct nntp_session_state_data * +get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline newsnntp * get_nntp_session(mailsession * session) +{ + return get_data(session)->nntp_session; +} + +static int nntpdriver_initialize(mailsession * session) +{ + struct nntp_session_state_data * data; + newsnntp * nntp; + + nntp = newsnntp_new(0, NULL); + if (nntp == NULL) + goto err; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto free; + + data->nntp_session = nntp; + + data->nntp_userid = NULL; + data->nntp_password = NULL; + + data->nntp_group_info = NULL; + data->nntp_group_name = NULL; + + data->nntp_subscribed_list = clist_new(); + if (data->nntp_subscribed_list == NULL) + goto free_data; + + data->nntp_max_articles = 0; + + data->nntp_mode_reader = FALSE; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free_data: + free(data); + free: + newsnntp_free(nntp); + err: + return MAIL_ERROR_MEMORY; +} + +static void nntpdriver_uninitialize(mailsession * session) +{ + struct nntp_session_state_data * data; + + data = get_data(session); + + clist_foreach(data->nntp_subscribed_list, (clist_func) free, NULL); + clist_free(data->nntp_subscribed_list); + + if (data->nntp_group_info != NULL) + newsnntp_group_free(data->nntp_group_info); + + if (data->nntp_group_name != NULL) + free(data->nntp_group_name); + + if (data->nntp_userid != NULL) + free(data->nntp_userid); + + if (data->nntp_password != NULL) + free(data->nntp_password); + + newsnntp_free(data->nntp_session); + free(data); + + session->sess_data = NULL; +} + + +static int nntpdriver_parameters(mailsession * session, + int id, void * value) +{ + struct nntp_session_state_data * data; + + data = get_data(session); + + switch (id) { + case NNTPDRIVER_SET_MAX_ARTICLES: + { + uint32_t * param; + + param = value; + + data->nntp_max_articles = * param; + return MAIL_NO_ERROR; + } + } + + return MAIL_ERROR_INVAL; +} + + +static int add_to_list(mailsession * session, const char * mb) +{ + char * new_mb; + int r; + struct nntp_session_state_data * data; + + data = get_data(session); + + new_mb = strdup(mb); + if (new_mb == NULL) + return -1; + + r = clist_append(data->nntp_subscribed_list, new_mb); + if (r < 0) { + free(new_mb); + return -1; + } + + return 0; +} + +static int remove_from_list(mailsession * session, const char * mb) +{ + clistiter * cur; + struct nntp_session_state_data * data; + + data = get_data(session); + + for(cur = clist_begin(data->nntp_subscribed_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * cur_name; + + cur_name = clist_content(cur); + if (strcmp(cur_name, mb) == 0) { + clist_delete(data->nntp_subscribed_list, cur); + free(cur_name); + return 0; + } + } + + return -1; +} + + +static int nntpdriver_connect_stream(mailsession * session, mailstream * s) +{ + int r; + + r = newsnntp_connect(get_nntp_session(session), s); + + switch (r) { + case NEWSNNTP_NO_ERROR: + return MAIL_NO_ERROR_NON_AUTHENTICATED; + + default: + return nntpdriver_nntp_error_to_mail_error(r); + } +} + +static int nntpdriver_login(mailsession * session, + const char * userid, const char * password) +{ + struct nntp_session_state_data * data; + char * new_userid; + char * new_password; + + data = get_data(session); + + if (userid != NULL) { + new_userid = strdup(userid); + if (new_userid == NULL) + goto err; + } + else + new_userid = NULL; + + if (password != NULL) { + new_password = strdup(password); + if (new_password == NULL) + goto free_uid; + } + else + new_password = NULL; + + data->nntp_userid = new_userid; + data->nntp_password = new_password; + + return MAIL_NO_ERROR; + + free_uid: + if (new_userid != NULL) + free(new_userid); + err: + return MAIL_ERROR_MEMORY; +} + +static int nntpdriver_logout(mailsession * session) +{ + int r; + + r = newsnntp_quit(get_nntp_session(session)); + + return nntpdriver_nntp_error_to_mail_error(r); +} + + +static int nntpdriver_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, + uint32_t * result_recent, + uint32_t * result_unseen) +{ + uint32_t count; + int r; + + r = nntpdriver_select_folder(session, mb); + if (r != MAIL_NO_ERROR) + return r; + + r = nntpdriver_messages_number(session, mb, &count); + if (r != MAIL_NO_ERROR) + return r; + + * result_messages = count; + * result_recent = count; + * result_unseen = count; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_messages_number(mailsession * session, const char * mb, + uint32_t * result) +{ + int r; + struct nntp_session_state_data * data; + + if (mb != NULL) { + r = nntpdriver_select_folder(session, mb); + if (r != MAIL_NO_ERROR) + return r; + } + + data = get_data(session); + + if (data->nntp_group_info == NULL) + return MAIL_ERROR_FOLDER_NOT_FOUND; + + * result = data->nntp_group_info->grp_last - + data->nntp_group_info->grp_first + 1; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_list_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + int r; + clist * group_list; + newsnntp * nntp; + clistiter * cur; + char * new_mb; + int done; + clist * list; + struct mail_list * ml; + int res; + + nntp = get_nntp_session(session); + + new_mb = NULL; + if ((mb != NULL) && (*mb != '\0')) { + new_mb = malloc(strlen(mb) + 3); + if (new_mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + strcpy(new_mb, mb); + strcat(new_mb, ".*"); + } + + done = FALSE; + do { + if (new_mb != NULL) + r = newsnntp_list_active(nntp, new_mb, &group_list); + else + r = newsnntp_list(nntp, &group_list); + + switch (r) { + case NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME: + r = nntpdriver_authenticate_user(session); + if (r != MAIL_NO_ERROR) { + if (new_mb != NULL) + free(new_mb); + res = r; + goto err; + } + break; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + r = nntpdriver_authenticate_password(session); + if (r != MAIL_NO_ERROR) { + if (new_mb != NULL) + free(new_mb); + res = r; + goto err; + } + break; + + case NEWSNNTP_NO_ERROR: + if (new_mb != NULL) + free(new_mb); + done = TRUE; + break; + + default: + if (new_mb != NULL) + free(new_mb); + return nntpdriver_nntp_error_to_mail_error(r); + } + } + while (!done); + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(cur = clist_begin(group_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct newsnntp_group_info * info; + char * new_name; + + info = clist_content(cur); + new_name = strdup(info->grp_name); + if (new_name == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, new_name); + if (r < 0) { + free(new_name); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + ml = mail_list_new(list); + if (ml == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + newsnntp_list_free(group_list); + + * result = ml; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + newsnntp_list_free(group_list); + err: + return res; +} + +static int nntpdriver_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + clist * subscribed; + clist * lsub_result; + clistiter * cur; + struct mail_list * lsub; + size_t length; + int res; + int r; + struct nntp_session_state_data * data; + + length = strlen(mb); + + data = get_data(session); + + subscribed = data->nntp_subscribed_list; + lsub_result = clist_new(); + if (lsub_result == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(cur = clist_begin(subscribed) ; cur != NULL ; + cur = clist_next(cur)) { + char * cur_mb; + char * new_mb; + + cur_mb = clist_content(cur); + + if (strncmp(mb, cur_mb, length) == 0) { + new_mb = strdup(cur_mb); + if (new_mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(lsub_result, new_mb); + if (r < 0) { + free(new_mb); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + lsub = mail_list_new(lsub_result); + if (lsub == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = lsub; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(lsub_result, (clist_func) free, NULL); + clist_free(lsub_result); + err: + return res; +} + +static int nntpdriver_subscribe_folder(mailsession * session, const char * mb) +{ + int r; + + r = add_to_list(session, mb); + if (r < 0) + return MAIL_ERROR_SUBSCRIBE; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_unsubscribe_folder(mailsession * session, const char * mb) +{ + int r; + + r = remove_from_list(session, mb); + if (r < 0) + return MAIL_ERROR_UNSUBSCRIBE; + + return MAIL_NO_ERROR; +} + + + +/* messages operations */ + +static int nntpdriver_append_message(mailsession * session, + const char * message, size_t size) +{ + int r; + + do { + r = newsnntp_post(get_nntp_session(session), message, size); + switch (r) { + case NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME: + r = nntpdriver_authenticate_user(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + r = nntpdriver_authenticate_password(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + default: + return nntpdriver_nntp_error_to_mail_error(r); + } + } + while (1); +} + +static int nntpdriver_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags) +{ + return nntpdriver_append_message(session, message, size); +} + + +static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, + struct mailimf_fields ** result); + + +static int +nntpdriver_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + newsnntp * nntp; + int r; + struct nntp_session_state_data * data; + clist * list; + int done; + clistiter * cur; + uint32_t first_seq; + unsigned int i; + + nntp = get_nntp_session(session); + + data = get_data(session); + + if (data->nntp_group_info == NULL) + return MAIL_ERROR_BAD_STATE; + + first_seq = data->nntp_group_info->grp_first; + + if (carray_count(env_list->msg_tab) > 0) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, 0); + + first_seq = msg->msg_index; + } + + if (carray_count(env_list->msg_tab) > 0) { + i = carray_count(env_list->msg_tab) - 1; + while (1) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields != NULL) { + first_seq = msg->msg_index + 1; + break; + } + + if (i == 0) + break; + + i --; + } + } + + if (first_seq > data->nntp_group_info->grp_last) { + list = NULL; + } + else { + done = FALSE; + do { + r = newsnntp_xover_range(nntp, first_seq, + data->nntp_group_info->grp_last, &list); + + switch (r) { + case NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME: + r = nntpdriver_authenticate_user(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + r = nntpdriver_authenticate_password(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_NO_ERROR: + done = TRUE; + break; + + default: + return nntpdriver_nntp_error_to_mail_error(r); + } + } + while (!done); + } + +#if 0 + i = 0; + j = 0; + + if (list != NULL) { + for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) { + struct newsnntp_xover_resp_item * item; + struct mailimf_fields * fields; + + item = clist_content(cur); + + while (i < carray_count(env_list->msg_tab)) { + mailmessage * info; + + info = carray_get(env_list->msg_tab, i); + + if (item->ovr_article == info->msg_index) { + + if (info->fields == NULL) { + r = xover_resp_to_fields(item, &fields); + if (r == MAIL_NO_ERROR) { + info->fields = fields; + } + + info->size = item->ovr_size; + + carray_set(env_list->msg_tab, j, info); + j ++; + i ++; + break; + } + else { + carray_set(env_list->msg_tab, j, info); + j ++; + } + } + else { + if (info->fields != NULL) { + carray_set(env_list->msg_tab, j, info); + j ++; + } + else { + if (info->flags != NULL) { + info->flags->flags &= ~MAIL_FLAG_NEW; + info->flags->flags |= MAIL_FLAG_SEEN | MAIL_FLAG_DELETED; + mailmessage_check(info); + } + mailmessage_free(info); + carray_set(env_list->msg_tab, i, NULL); + } + } + + i ++; + } + } + } + + while (i < carray_count(env_list->msg_tab)) { + mailmessage * info; + + info = carray_get(env_list->msg_tab, i); + if (info->fields != NULL) { + carray_set(env_list->msg_tab, j, info); + j ++; + } + else { + if (info->flags != NULL) { + info->flags->flags &= ~MAIL_FLAG_NEW; + info->flags->flags |= MAIL_FLAG_SEEN | MAIL_FLAG_DELETED; + mailmessage_check(info); + } + mailmessage_free(info); + carray_set(env_list->msg_tab, i, NULL); + } + + i ++; + } + + r = carray_set_size(env_list->msg_tab, j); + if (r < 0) { + if (list != NULL) + newsnntp_xover_resp_list_free(list); + return MAIL_ERROR_MEMORY; + } +#endif + i = 0; + + if (list != NULL) { + for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) { + struct newsnntp_xover_resp_item * item; + struct mailimf_fields * fields; + + item = clist_content(cur); + + while (i < carray_count(env_list->msg_tab)) { + mailmessage * info; + + info = carray_get(env_list->msg_tab, i); + + if (item->ovr_article == info->msg_index) { + + if (info->msg_fields == NULL) { + fields = NULL; + r = xover_resp_to_fields(item, &fields); + if (r == MAIL_NO_ERROR) { + info->msg_fields = fields; + } + + info->msg_size = item->ovr_size; + + i ++; + break; + } + } +#if 0 + else if ((info->fields == NULL) && (info->flags != NULL)) { + info->flags->flags &= ~MAIL_FLAG_NEW; + info->flags->flags |= MAIL_FLAG_CANCELLED; + mailmessage_check(info); + } +#endif + + i ++; + } + } + } + +#if 0 + while (i < env_list->msg_tab->len) { + mailmessage * info; + + info = carray_get(env_list->msg_tab, i); + if ((info->fields == NULL) && (info->flags != NULL)) { + info->flags->flags &= ~MAIL_FLAG_NEW; + info->flags->flags |= MAIL_FLAG_CANCELLED; + mailmessage_check(info); + } + + i ++; + } +#endif + + if (list != NULL) + newsnntp_xover_resp_list_free(list); + + return MAIL_NO_ERROR; +} + + +static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, + struct mailimf_fields ** result) +{ + size_t cur_token; + clist * list; + int r; + struct mailimf_fields * fields; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if (item->ovr_subject != NULL) { + char * subject_str; + struct mailimf_subject * subject; + struct mailimf_field * field; + + subject_str = strdup(item->ovr_subject); + if (subject_str == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + subject = mailimf_subject_new(subject_str); + if (subject == NULL) { + free(subject_str); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_SUBJECT, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, subject, NULL, NULL, NULL); + if (field == NULL) { + mailimf_subject_free(subject); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + if (item->ovr_author != NULL) { + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + struct mailimf_field * field; + + cur_token = 0; + r = mailimf_mailbox_list_parse(item->ovr_author, strlen(item->ovr_author), + &cur_token, &mb_list); + switch (r) { + case MAILIMF_NO_ERROR: + from = mailimf_from_new(mb_list); + if (from == NULL) { + mailimf_mailbox_list_free(mb_list); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, from, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_from_free(from); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + break; + + case MAILIMF_ERROR_PARSE: + break; + + default: + res = maildriver_imf_error_to_mail_error(r); + goto free_list; + } + } + + if (item->ovr_date != NULL) { + struct mailimf_date_time * date_time; + struct mailimf_orig_date * orig_date; + struct mailimf_field * field; + + cur_token = 0; + r = mailimf_date_time_parse(item->ovr_date, strlen(item->ovr_date), + &cur_token, &date_time); + switch (r) { + case MAILIMF_NO_ERROR: + orig_date = mailimf_orig_date_new(date_time); + if (orig_date == NULL) { + mailimf_date_time_free(date_time); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_ORIG_DATE, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, orig_date, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_orig_date_free(orig_date); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + break; + + case MAILIMF_ERROR_PARSE: + break; + + default: + res = maildriver_imf_error_to_mail_error(r); + goto free_list; + } + } + + if (item->ovr_message_id != NULL) { + char * msgid_str; + struct mailimf_message_id * msgid; + struct mailimf_field * field; + + cur_token = 0; + r = mailimf_msg_id_parse(item->ovr_message_id, strlen(item->ovr_message_id), + &cur_token, &msgid_str); + + switch (r) { + case MAILIMF_NO_ERROR: + msgid = mailimf_message_id_new(msgid_str); + if (msgid == NULL) { + mailimf_msg_id_free(msgid_str); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, msgid, NULL, + NULL, NULL, NULL, NULL, NULL); + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + break; + + case MAILIMF_ERROR_PARSE: + break; + + default: + res = maildriver_imf_error_to_mail_error(r); + goto free_list; + } + } + + if (item->ovr_references != NULL) { + clist * msgid_list; + struct mailimf_references * references; + struct mailimf_field * field; + + cur_token = 0; + + r = mailimf_msg_id_list_parse(item->ovr_references, strlen(item->ovr_references), + &cur_token, &msgid_list); + + switch (r) { + case MAILIMF_NO_ERROR: + references = mailimf_references_new(msgid_list); + if (references == NULL) { + clist_foreach(msgid_list, + (clist_func) mailimf_msg_id_free, NULL); + clist_free(msgid_list); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_REFERENCES, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + references, NULL, NULL, NULL, NULL); + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + case MAILIMF_ERROR_PARSE: + break; + + default: + res = maildriver_imf_error_to_mail_error(r); + goto free_list; + } + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = fields; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + err: + return res; +} + + +/* get messages list with group info */ + +static int nntpdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + return nntp_get_messages_list(session, session, nntp_message_driver, result); + +} + +static int nntpdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, nntp_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_noop(mailsession * session) +{ + newsnntp * nntp; + int r; + struct tm tm; + + nntp = get_nntp_session(session); + + r = newsnntp_date(nntp, &tm); + + return nntpdriver_nntp_error_to_mail_error(r); +} + +static int nntpdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t num; + char * p; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + num = (uint32_t) strtoul(uid, &p, 10); + if ((p == uid) || (* p != '\0')) + return MAIL_ERROR_INVAL; + + return nntpdriver_get_message(session, num, result); + } diff --git a/Sources/libetpan/driver/implementation/nntp/nntpdriver.h b/Sources/libetpan/driver/implementation/nntp/nntpdriver.h new file mode 100644 index 00000000..8fe28cbe --- /dev/null +++ b/Sources/libetpan/driver/implementation/nntp/nntpdriver.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver.h,v 1.16 2004/11/21 21:53:33 hoa Exp $ + */ + +#ifndef NNTPDRIVER_H + +#define NNTPDRIVER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * nntp_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/nntp/nntpdriver_cached.c b/Sources/libetpan/driver/implementation/nntp/nntpdriver_cached.c new file mode 100644 index 00000000..60a13631 --- /dev/null +++ b/Sources/libetpan/driver/implementation/nntp/nntpdriver_cached.c @@ -0,0 +1,1070 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver_cached.c,v 1.57 2010/04/05 14:21:35 hoa Exp $ + */ +#define HAVE_CONFIG_H 1 + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "nntpdriver_cached.h" + +#include "libetpan-config.h" + +#include +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#ifdef WIN32 +# include "win_etpan.h" +#endif + +#include "mail_cache_db.h" + +#include "mail.h" +#include "mailmessage.h" +#include "maildriver_tools.h" +#include "nntpdriver.h" +#include "maildriver.h" +#include "newsnntp.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "maillock.h" +#include "nntpdriver_cached_message.h" +#include "nntpdriver_tools.h" + +static int nntpdriver_cached_initialize(mailsession * session); + +static void nntpdriver_cached_uninitialize(mailsession * session); + +static int nntpdriver_cached_parameters(mailsession * session, + int id, void * value); + +static int nntpdriver_cached_connect_stream(mailsession * session, + mailstream * s); + +static int nntpdriver_cached_login(mailsession * session, + const char * userid, const char * password); + +static int nntpdriver_cached_logout(mailsession * session); + +static int nntpdriver_cached_check_folder(mailsession * session); + +static int nntpdriver_cached_select_folder(mailsession * session, const char * mb); + +static int nntpdriver_cached_status_folder(mailsession * session, + const char * mb, + uint32_t * result_messages, + uint32_t * result_recent, + uint32_t * result_unseen); + +static int nntpdriver_cached_messages_number(mailsession * session, const char * mb, + uint32_t * result); + +static int nntpdriver_cached_recent_number(mailsession * session, const char * mb, + uint32_t * result); + +static int nntpdriver_cached_unseen_number(mailsession * session, const char * mb, + uint32_t * result); + +static int nntpdriver_cached_append_message(mailsession * session, + const char * message, size_t size); + +static int nntpdriver_cached_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); + +static int +nntpdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + + +static int +nntpdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int nntpdriver_cached_list_folders(mailsession * session, const char * mb, + struct mail_list ** result); + +static int nntpdriver_cached_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result); + +static int nntpdriver_cached_subscribe_folder(mailsession * session, + const char * mb); + +static int nntpdriver_cached_unsubscribe_folder(mailsession * session, + const char * mb); + +static int nntpdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int nntpdriver_cached_noop(mailsession * session); + +static int nntpdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static mailsession_driver local_nntp_cached_session_driver = { + /* sess_name */ "nntp-cached", + + /* sess_initialize */ nntpdriver_cached_initialize, + /* sess_uninitialize */ nntpdriver_cached_uninitialize, + + /* sess_parameters */ nntpdriver_cached_parameters, + + /* sess_connect_stream */ nntpdriver_cached_connect_stream, + /* sess_connect_path */ NULL, + /* sess_starttls */ NULL, + /* sess_login */ nntpdriver_cached_login, + /* sess_logout */ nntpdriver_cached_logout, + /* sess_noop */ nntpdriver_cached_noop, + + /* sess_build_folder_name */ NULL, + /* sess_create_folder */ NULL, + /* sess_delete_folder */ NULL, + /* sess_rename_folder */ NULL, + /* sess_check_folder */ nntpdriver_cached_check_folder, + /* sess_examine_folder */ NULL, + /* sess_select_folder */ nntpdriver_cached_select_folder, + /* sess_expunge_folder */ NULL, + /* sess_status_folder */ nntpdriver_cached_status_folder, + /* sess_messages_number */ nntpdriver_cached_messages_number, + /* sess_recent_number */ nntpdriver_cached_recent_number, + /* sess_unseen_number */ nntpdriver_cached_unseen_number, + /* sess_list_folders */ nntpdriver_cached_list_folders, + /* sess_lsub_folders */ nntpdriver_cached_lsub_folders, + /* sess_subscribe_folder */ nntpdriver_cached_subscribe_folder, + /* sess_unsubscribe_folder */ nntpdriver_cached_unsubscribe_folder, + + /* sess_append_message */ nntpdriver_cached_append_message, + /* sess_append_message_flags */ nntpdriver_cached_append_message_flags, + /* sess_copy_message */ NULL, + /* sess_move_message */ NULL, + + /* sess_get_message */ nntpdriver_cached_get_message, + /* sess_get_message_by_uid */ nntpdriver_cached_get_message_by_uid, + + /* sess_get_messages_list */ nntpdriver_cached_get_messages_list, + /* sess_get_envelopes_list */ nntpdriver_cached_get_envelopes_list, + /* sess_remove_message */ NULL, +#if 0 + /* sess_search_messages */ maildriver_generic_search_messages, +#endif + /* sess_login_sasl */ NULL +}; + + +mailsession_driver * nntp_cached_session_driver = +&local_nntp_cached_session_driver; + +#define ENV_NAME "env.db" +#define FLAGS_NAME "flags.db" + + + +static void read_article_seq(mailsession * session, + uint32_t * pfirst, uint32_t * plast); + +static void write_article_seq(mailsession * session, + uint32_t first, uint32_t last); + + +static inline struct nntp_cached_session_state_data * +get_cached_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * get_ancestor(mailsession * session) +{ + return get_cached_data(session)->nntp_ancestor; +} + +static inline struct nntp_session_state_data * +get_ancestor_data(mailsession * session) +{ + return get_ancestor(session)->sess_data; +} + +static inline newsnntp * get_nntp_session(mailsession * session) +{ + return get_ancestor_data(session)->nntp_session; +} + +static int nntpdriver_cached_initialize(mailsession * session) +{ + struct nntp_cached_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->nntp_flags_store = mail_flags_store_new(); + if (data->nntp_flags_store == NULL) + goto free; + + data->nntp_ancestor = mailsession_new(nntp_session_driver); + if (data->nntp_ancestor == NULL) + goto free_store; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free_store: + mail_flags_store_free(data->nntp_flags_store); + free: + free(data); + err: + return MAIL_ERROR_MEMORY; +} + +static int nntp_flags_store_process(char * flags_directory, char * group_name, + struct mail_flags_store * flags_store) +{ + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + unsigned int i; + int r; + int res; + + if (carray_count(flags_store->fls_tab) == 0) + return MAIL_NO_ERROR; + + if (group_name == NULL) + return MAIL_NO_ERROR; + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + flags_directory, group_name, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(flags_store->fls_tab, i); + + r = nntpdriver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_index, msg->msg_flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + mail_flags_store_clear(flags_store); + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static void nntpdriver_cached_uninitialize(mailsession * session) +{ + struct nntp_cached_session_state_data * cached_data; + struct nntp_session_state_data * ancestor_data; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + nntp_flags_store_process(cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, + cached_data->nntp_flags_store); + + mail_flags_store_free(cached_data->nntp_flags_store); + + mailsession_free(cached_data->nntp_ancestor); + free(cached_data); + + session->sess_data = NULL; +} + +static int nntpdriver_cached_parameters(mailsession * session, + int id, void * value) +{ + struct nntp_cached_session_state_data * cached_data; + int r; + + cached_data = get_cached_data(session); + + switch (id) { + case NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY: + strncpy(cached_data->nntp_cache_directory, value, PATH_MAX); + cached_data->nntp_cache_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(cached_data->nntp_cache_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + case NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY: + strncpy(cached_data->nntp_flags_directory, value, PATH_MAX); + cached_data->nntp_flags_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(cached_data->nntp_flags_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + default: + return mailsession_parameters(get_ancestor(session), id, value); + } +} + +static int nntpdriver_cached_connect_stream(mailsession * session, + mailstream * s) +{ + return mailsession_connect_stream(get_ancestor(session), s); +} + +static int nntpdriver_cached_login(mailsession * session, + const char * userid, const char * password) +{ + return mailsession_login(get_ancestor(session), userid, password); +} + +static int nntpdriver_cached_logout(mailsession * session) +{ + struct nntp_cached_session_state_data * cached_data; + struct nntp_session_state_data * ancestor_data; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + nntp_flags_store_process(cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, + cached_data->nntp_flags_store); + + return mailsession_logout(get_ancestor(session)); +} + +static int nntpdriver_cached_select_folder(mailsession * session, const char * mb) +{ + int r; + struct nntp_session_state_data * ancestor_data; + struct nntp_cached_session_state_data * cached_data; + int res; + char key[PATH_MAX]; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + nntp_flags_store_process(cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, + cached_data->nntp_flags_store); + + r = mailsession_select_folder(get_ancestor(session), mb); + if (r != MAIL_NO_ERROR) + return r; + + if (ancestor_data->nntp_group_name == NULL) + return MAIL_ERROR_BAD_STATE; + + snprintf(key, PATH_MAX, "%s/%s", cached_data->nntp_cache_directory, + ancestor_data->nntp_group_name); + + r = generic_cache_create_dir(key); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + snprintf(key, PATH_MAX, "%s/%s", cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name); + + r = generic_cache_create_dir(key); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int nntpdriver_cached_check_folder(mailsession * session) +{ + struct nntp_session_state_data * ancestor_data; + struct nntp_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + nntp_flags_store_process(cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, + cached_data->nntp_flags_store); + + return MAIL_NO_ERROR; +} + + +static int nntpdriver_cached_status_folder(mailsession * session, + const char * mb, uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + int res; + struct nntp_cached_session_state_data * cached_data; + struct nntp_session_state_data * ancestor_data; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + uint32_t i; + int r; + uint32_t recent; + uint32_t unseen; + uint32_t first; + uint32_t last; + uint32_t count; + uint32_t additionnal; + + r = nntpdriver_cached_select_folder(session, mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + read_article_seq(session, &first, &last); + + count = 0; + recent = 0; + unseen = 0; + + ancestor_data = get_ancestor_data(session); + cached_data = get_cached_data(session); + if (ancestor_data->nntp_group_name == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + if (ancestor_data->nntp_group_info->grp_first > first) + first = ancestor_data->nntp_group_info->grp_first; + if (last < first) + last = ancestor_data->nntp_group_info->grp_last; + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = first ; i <= last ; i++) { + struct mail_flags * flags; + + r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr, + i, &flags); + if (r == MAIL_NO_ERROR) { + if ((flags->fl_flags & MAIL_FLAG_CANCELLED) != 0) { + mail_flags_free(flags); + continue; + } + + count ++; + if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) { + recent ++; + } + if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) { + unseen ++; + } + mail_flags_free(flags); + } + } + + if ((count == 0) && (first != last)) { + count = last - first + 1; + recent = count; + unseen = count; + } + + additionnal = ancestor_data->nntp_group_info->grp_last - last; + recent += additionnal; + unseen += additionnal; + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + * result_messages = count; + * result_recent = recent; + * result_unseen = unseen; + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int nntpdriver_cached_messages_number(mailsession * session, + const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = nntpdriver_cached_status_folder(session, mb, + &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = messages; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_cached_recent_number(mailsession * session, + const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = nntpdriver_cached_status_folder(session, mb, + &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = recent; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_cached_unseen_number(mailsession * session, + const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = nntpdriver_cached_status_folder(session, mb, + &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = unseen; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_cached_list_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + return mailsession_list_folders(get_ancestor(session), mb, result); +} + +static int nntpdriver_cached_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + return mailsession_lsub_folders(get_ancestor(session), mb, result); +} + +static int nntpdriver_cached_subscribe_folder(mailsession * session, + const char * mb) +{ + return mailsession_subscribe_folder(get_ancestor(session), mb); +} + +static int nntpdriver_cached_unsubscribe_folder(mailsession * session, + const char * mb) +{ + return mailsession_unsubscribe_folder(get_ancestor(session), mb); +} + + + +/* messages operations */ + +static int nntpdriver_cached_append_message(mailsession * session, + const char * message, size_t size) +{ + return mailsession_append_message(get_ancestor(session), message, size); +} + +static int nntpdriver_cached_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags) +{ + return nntpdriver_cached_append_message(session, message, size); +} + + + +static int +get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields ** result) +{ + char keyname[PATH_MAX]; + int r; + struct mailimf_fields * fields; + int res; + + snprintf(keyname, PATH_MAX, "%i-envelope", num); + + r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = fields; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +write_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields * fields) +{ + int r; + int res; + char keyname[PATH_MAX]; + + snprintf(keyname, PATH_MAX, "%i-envelope", num); + + r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +#define SEQ_FILENAME "articles-seq" + +static void read_article_seq(mailsession * session, + uint32_t * pfirst, uint32_t * plast) +{ + FILE * f; + struct nntp_session_state_data * ancestor_data; + uint32_t first; + uint32_t last; + char seq_filename[PATH_MAX]; + struct nntp_cached_session_state_data * cached_data; + int r; + + first = 0; + last = 0; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + if (ancestor_data->nntp_group_name == NULL) + return; + + snprintf(seq_filename, PATH_MAX, "%s/%s/%s", + cached_data->nntp_cache_directory, + ancestor_data->nntp_group_name, SEQ_FILENAME); + f = fopen(seq_filename, "r"); + + if (f != NULL) { + int fd; + + fd = fileno(f); + + r = maillock_read_lock(seq_filename, fd); + if (r == 0) { + MMAPString * mmapstr; + size_t cur_token; + char buf[sizeof(uint32_t) * 2]; + size_t read_size; + + read_size = fread(buf, 1, sizeof(uint32_t) * 2, f); + mmapstr = mmap_string_new_len(buf, read_size); + if (mmapstr != NULL) { + cur_token = 0; + r = mailimf_cache_int_read(mmapstr, &cur_token, &first); + r = mailimf_cache_int_read(mmapstr, &cur_token, &last); + + mmap_string_free(mmapstr); + } + + maillock_read_unlock(seq_filename, fd); + } + fclose(f); + } + + * pfirst = first; + * plast = last; +} + +static void write_article_seq(mailsession * session, + uint32_t first, uint32_t last) +{ + FILE * f; + struct nntp_session_state_data * ancestor_data; + char seq_filename[PATH_MAX]; + struct nntp_cached_session_state_data * cached_data; + int r; + int fd; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + if (ancestor_data->nntp_group_name == NULL) + return; + + snprintf(seq_filename, PATH_MAX, "%s/%s/%s", + cached_data->nntp_cache_directory, + ancestor_data->nntp_group_name, SEQ_FILENAME); + + fd = creat(seq_filename, S_IRUSR | S_IWUSR); + if (fd < 0) + return; + + f = fdopen(fd, "w"); + if (f != NULL) { + r = maillock_write_lock(seq_filename, fd); + if (r == 0) { + MMAPString * mmapstr; + size_t cur_token; + + mmapstr = mmap_string_new(""); + if (mmapstr != NULL) { + r = mail_serialize_clear(mmapstr, &cur_token); + if (r == MAIL_NO_ERROR) { + r = mailimf_cache_int_write(mmapstr, &cur_token, first); + r = mailimf_cache_int_write(mmapstr, &cur_token, last); + + fwrite(mmapstr->str, 1, mmapstr->len, f); + } + + mmap_string_free(mmapstr); + } + + r = maillock_write_unlock(seq_filename, fd); + } + fclose(f); + } + else + close(fd); +} + + +static void get_uid_from_filename(char * filename) +{ + char * p; + + if (strcmp(filename, SEQ_FILENAME) == 0) + * filename = 0; + + p = strstr(filename, "-header"); + if (p != NULL) + * p = 0; +} + +static int +nntpdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + unsigned int i; + struct nntp_cached_session_state_data * cached_data; + uint32_t first; + uint32_t last; + struct nntp_session_state_data * ancestor_data; + char filename_env[PATH_MAX]; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_env; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + int res; + char cache_dir[PATH_MAX]; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + nntp_flags_store_process(cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, + cached_data->nntp_flags_store); + + if (ancestor_data->nntp_group_name == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + /* read articles sequence */ + + read_article_seq(session, &first, &last); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(filename_env, PATH_MAX, "%s/%s/%s", + cached_data->nntp_cache_directory, + ancestor_data->nntp_group_name, ENV_NAME); + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto free_mmapstr; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, FLAGS_NAME); + + /* fill with cached */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailimf_fields * fields; + + msg = carray_get(env_list->msg_tab, i); + + if ((msg->msg_index < first) || (msg->msg_index > last)) + continue; + + if (msg->msg_fields == NULL) { + r = get_cached_envelope(cache_db_env, mmapstr, + session, msg->msg_index, &fields); + if (r == MAIL_NO_ERROR) { + msg->msg_fields = fields; + msg->msg_cached = TRUE; + } + } + } + + mail_cache_db_close_unlock(filename_env, cache_db_env); + + r = mailsession_get_envelopes_list(get_ancestor(session), env_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto free_mmapstr; + } + + /* add flags */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_flags == NULL) { + struct mail_flags * flags; + + r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr, + msg->msg_index, &flags); + if (r == MAIL_NO_ERROR) { + msg->msg_flags = flags; + } + else { + msg->msg_flags = mail_flags_new_empty(); + if (msg->msg_fields == NULL) { + msg->msg_flags->fl_flags |= MAIL_FLAG_CANCELLED; + mailmessage_check(msg); + } + } + } + } + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto close_db_env; + } + + /* must write cache */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields != NULL) { + if (!msg->msg_cached) { + r = write_cached_envelope(cache_db_env, mmapstr, + session, msg->msg_index, msg->msg_fields); + } + } + + if (msg->msg_flags != NULL) { + r = nntpdriver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_index, msg->msg_flags); + } + } + + first = 0; + last = 0; + if (carray_count(env_list->msg_tab) > 0) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, 0); + first = msg->msg_index; + + msg = carray_get(env_list->msg_tab, carray_count(env_list->msg_tab) - 1); + last = msg->msg_index; + } + + /* write articles sequence */ + + write_article_seq(session, first, last); + + /* flush cache */ + + maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list); + + /* remove cache files */ + + snprintf(cache_dir, PATH_MAX, "%s/%s", + cached_data->nntp_cache_directory, ancestor_data->nntp_group_name); + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + mmap_string_free(mmapstr); + + maildriver_message_cache_clean_up(cache_dir, env_list, + get_uid_from_filename); + + return MAIL_NO_ERROR; + + close_db_env: + mail_cache_db_close_unlock(filename_env, cache_db_env); + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + +static int +nntpdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + return nntp_get_messages_list(get_ancestor(session), session, + nntp_cached_message_driver, result); +} + +static int nntpdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, nntp_cached_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_cached_noop(mailsession * session) +{ + return mailsession_noop(get_ancestor(session)); +} + +static int nntpdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t num; + char * p; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + num = (uint32_t) strtoul(uid, &p, 10); + if ((p == uid) || (* p != '\0')) + return MAIL_ERROR_INVAL; + + return nntpdriver_cached_get_message(session, num, result); +} diff --git a/Sources/libetpan/driver/implementation/nntp/nntpdriver_cached.h b/Sources/libetpan/driver/implementation/nntp/nntpdriver_cached.h new file mode 100644 index 00000000..ea9e0d84 --- /dev/null +++ b/Sources/libetpan/driver/implementation/nntp/nntpdriver_cached.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver_cached.h,v 1.14 2004/11/21 21:53:33 hoa Exp $ + */ + +#ifndef NNTPDRIVER_CACHED_H + +#define NNTPDRIVER_CACHED_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * nntp_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/nntp/nntpdriver_cached_message.c b/Sources/libetpan/driver/implementation/nntp/nntpdriver_cached_message.c new file mode 100644 index 00000000..236be33e --- /dev/null +++ b/Sources/libetpan/driver/implementation/nntp/nntpdriver_cached_message.c @@ -0,0 +1,367 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver_cached_message.c,v 1.21 2008/02/17 13:13:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "nntpdriver_cached_message.h" + +#include +#include + +#include "mail_cache_db.h" + +#include "mailmessage.h" +#include "mailmessage_tools.h" +#include "nntpdriver.h" +#include "nntpdriver_tools.h" +#include "nntpdriver_cached.h" +#include "nntpdriver_message.h" +#include "generic_cache.h" + +static int nntp_prefetch(mailmessage * msg_info); + +static void nntp_prefetch_free(struct generic_message_t * msg); + +static int nntp_initialize(mailmessage * msg_info); + +static int nntp_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static int nntp_fetch_size(mailmessage * msg_info, + size_t * result); + +static void nntp_uninitialize(mailmessage * msg_info); + +static void nntp_flush(mailmessage * msg_info); + +static void nntp_check(mailmessage * msg_info); + +static int nntp_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +static mailmessage_driver local_nntp_cached_message_driver = { + /* msg_name */ "nntp-cached", + + /* msg_initialize */ nntp_initialize, + /* msg_uninitialize */ nntp_uninitialize, + + /* msg_flush */ nntp_flush, + /* msg_check */ nntp_check, + + /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free, + + /* msg_fetch */ mailmessage_generic_fetch, + /* msg_fetch_header */ nntp_fetch_header, + /* msg_fetch_body */ mailmessage_generic_fetch_body, + /* msg_fetch_size */ nntp_fetch_size, + /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure, + /* msg_fetch_section */ mailmessage_generic_fetch_section, + /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header, + /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime, + /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body, + /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope, + + /* msg_get_flags */ nntp_get_flags +}; + +mailmessage_driver * nntp_cached_message_driver = +&local_nntp_cached_message_driver; + +static inline struct nntp_cached_session_state_data * +get_cached_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline mailsession * get_ancestor_session(mailmessage * msg) +{ + return get_cached_session_data(msg)->nntp_ancestor; +} + +static inline struct nntp_session_state_data * +get_ancestor_session_data(mailmessage * msg) +{ + return get_ancestor_session(msg)->sess_data; +} + +static inline newsnntp * +get_nntp_session(mailmessage * msg) +{ + return get_ancestor_session_data(msg)->nntp_session; +} + +static int nntp_prefetch(mailmessage * msg_info) +{ + char * msg_content; + size_t msg_length; + struct generic_message_t * msg; + int r; + struct nntp_cached_session_state_data * cached_data; + struct nntp_session_state_data * ancestor_data; + char filename[PATH_MAX]; + + /* we try the cached message */ + + cached_data = get_cached_session_data(msg_info); + + ancestor_data = get_ancestor_session_data(msg_info); + + snprintf(filename, PATH_MAX, "%s/%s/%i", cached_data->nntp_cache_directory, + ancestor_data->nntp_group_name, msg_info->msg_index); + + r = generic_cache_read(filename, &msg_content, &msg_length); + if (r == MAIL_NO_ERROR) { + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; + } + + /* we get the message through the network */ + + r = nntpdriver_article(get_ancestor_session(msg_info), + msg_info->msg_index, &msg_content, + &msg_length); + + if (r != MAIL_NO_ERROR) + return r; + + /* we write the message cache */ + + generic_cache_store(filename, msg_content, msg_length); + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void nntp_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static int nntp_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + char static_uid[20]; + + snprintf(static_uid, 20, "%u", msg_info->msg_index); + uid = strdup(static_uid); + if (uid == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + return r; + } + + msg = msg_info->msg_data; + msg->msg_prefetch = nntp_prefetch; + msg->msg_prefetch_free = nntp_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; +} + + +static void nntp_uninitialize(mailmessage * msg_info) +{ + mailmessage_generic_uninitialize(msg_info); +} + +#define FLAGS_NAME "flags.db" + +static void nntp_flush(mailmessage * msg_info) +{ + mailmessage_generic_flush(msg_info); +} + + +static void nntp_check(mailmessage * msg_info) +{ + if (msg_info->msg_flags != NULL) { + mail_flags_store_set(get_cached_session_data(msg_info)->nntp_flags_store, + msg_info); + /* ignore errors */ + } +} + +static int nntp_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + char * headers; + size_t headers_length; + struct nntp_cached_session_state_data * cached_data; + struct nntp_session_state_data * ancestor_data; + int r; + char filename[PATH_MAX]; + + msg = msg_info->msg_data; + + if (msg->msg_message != NULL) + return mailmessage_generic_fetch_header(msg_info, + result, result_len); + + /* we try the cached message */ + + cached_data = get_cached_session_data(msg_info); + + ancestor_data = get_ancestor_session_data(msg_info); + + snprintf(filename, PATH_MAX, "%s/%s/%i-header", + cached_data->nntp_cache_directory, + ancestor_data->nntp_group_name, msg_info->msg_index); + + r = generic_cache_read(filename, &headers, &headers_length); + if (r == MAIL_NO_ERROR) { + * result = headers; + * result_len = headers_length; + + return MAIL_NO_ERROR; + } + + /* we get the message through the network */ + + r = nntpdriver_head(get_ancestor_session(msg_info), msg_info->msg_index, + &headers, &headers_length); + if (r != MAIL_NO_ERROR) + return r; + + /* we write the message cache */ + + generic_cache_store(filename, headers, headers_length); + + * result = headers; + * result_len = headers_length; + + return MAIL_NO_ERROR; +} + +static int nntp_fetch_size(mailmessage * msg_info, + size_t * result) +{ + return nntpdriver_size(get_ancestor_session(msg_info), + msg_info->msg_index, result); +} + +static int nntp_get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + int r; + struct mail_flags * flags; + struct mail_cache_db * cache_db_flags; + char filename_flags[PATH_MAX]; + int res; + MMAPString * mmapstr; + + if (msg_info->msg_flags != NULL) { + * result = msg_info->msg_flags; + + return MAIL_NO_ERROR; + } + + flags = mail_flags_store_get(get_cached_session_data(msg_info)->nntp_flags_store, msg_info->msg_index); + + if (flags == NULL) { + struct nntp_cached_session_state_data * cached_data; + struct nntp_session_state_data * ancestor_data; + + cached_data = get_cached_session_data(msg_info); + + ancestor_data = get_ancestor_session_data(msg_info); + if (ancestor_data->nntp_group_name == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr, + msg_info->msg_index, &flags); + if (r != MAIL_NO_ERROR) { + flags = mail_flags_new_empty(); + if (flags == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + } + + msg_info->msg_flags = flags; + + * result = flags; + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} diff --git a/Sources/libetpan/driver/implementation/nntp/nntpdriver_cached_message.h b/Sources/libetpan/driver/implementation/nntp/nntpdriver_cached_message.h new file mode 100644 index 00000000..94152bf8 --- /dev/null +++ b/Sources/libetpan/driver/implementation/nntp/nntpdriver_cached_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver_cached_message.h,v 1.6 2004/11/21 21:53:33 hoa Exp $ + */ + +#include + +#ifndef NNTPDRIVER_CACHED_MESSAGE_H + +#define NNTPDRIVER_CACHED_MESSAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * nntp_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/nntp/nntpdriver_message.c b/Sources/libetpan/driver/implementation/nntp/nntpdriver_message.c new file mode 100644 index 00000000..00303fde --- /dev/null +++ b/Sources/libetpan/driver/implementation/nntp/nntpdriver_message.c @@ -0,0 +1,173 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver_message.c,v 1.16 2008/02/17 13:13:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "nntpdriver_message.h" + +#include "mailmessage_tools.h" +#include "nntpdriver_tools.h" +#include "nntpdriver.h" +#include "newsnntp.h" +#include +#include + +static int nntp_prefetch(mailmessage * msg_info); + +static void nntp_prefetch_free(struct generic_message_t * msg); + +static int nntp_initialize(mailmessage * msg_info); + +static int nntp_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static int nntp_fetch_size(mailmessage * msg_info, + size_t * result); + +static mailmessage_driver local_nntp_message_driver = { + /* msg_name */ "nntp", + + /* msg_initialize */ nntp_initialize, + /* msg_uninitialize */ mailmessage_generic_uninitialize, + + /* msg_flush */ mailmessage_generic_flush, + /* msg_check */ NULL, + + /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free, + + /* msg_fetch */ mailmessage_generic_fetch, + /* msg_fetch_header */ nntp_fetch_header, + /* msg_fetch_body */ mailmessage_generic_fetch_body, + /* msg_fetch_size */ nntp_fetch_size, + /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure, + /* msg_fetch_section */ mailmessage_generic_fetch_section, + /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header, + /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime, + /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body, + /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope, + + /* msg_get_flags */ NULL +}; + +mailmessage_driver * nntp_message_driver = &local_nntp_message_driver; + +static int nntp_prefetch(mailmessage * msg_info) +{ + char * msg_content; + size_t msg_length; + struct generic_message_t * msg; + int r; + + r = nntpdriver_article(msg_info->msg_session, msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void nntp_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static int nntp_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + char static_uid[20]; + + snprintf(static_uid, 20, "%u", msg_info->msg_index); + uid = strdup(static_uid); + if (uid == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + return r; + } + + msg = msg_info->msg_data; + msg->msg_prefetch = nntp_prefetch; + msg->msg_prefetch_free = nntp_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; +} + +static int nntp_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + char * headers; + size_t headers_length; + int r; + + msg = msg_info->msg_data; + + if (msg->msg_message != NULL) + return mailmessage_generic_fetch_header(msg_info, + result, result_len); + + r = nntpdriver_head(msg_info->msg_session, msg_info->msg_index, + &headers, &headers_length); + if (r != MAIL_NO_ERROR) + return r; + + * result = headers; + * result_len = headers_length; + + return MAIL_NO_ERROR; +} + +static int nntp_fetch_size(mailmessage * msg_info, + size_t * result) +{ + return nntpdriver_size(msg_info->msg_session, msg_info->msg_index, result); +} diff --git a/Sources/libetpan/driver/implementation/nntp/nntpdriver_message.h b/Sources/libetpan/driver/implementation/nntp/nntpdriver_message.h new file mode 100644 index 00000000..594300c8 --- /dev/null +++ b/Sources/libetpan/driver/implementation/nntp/nntpdriver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver_message.h,v 1.6 2004/11/21 21:53:33 hoa Exp $ + */ + +#ifndef NNTPDRIVER_MESSAGE_H + +#define NNTPDRIVER_MESSAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +extern mailmessage_driver * nntp_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/nntp/nntpdriver_tools.c b/Sources/libetpan/driver/implementation/nntp/nntpdriver_tools.c new file mode 100644 index 00000000..7e4a1b50 --- /dev/null +++ b/Sources/libetpan/driver/implementation/nntp/nntpdriver_tools.c @@ -0,0 +1,569 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver_tools.c,v 1.22 2008/02/20 22:15:50 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "nntpdriver_tools.h" + +#include "mail.h" +#include "nntpdriver.h" +#include "nntpdriver_cached.h" +#include "newsnntp.h" +#include "maildriver_types.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "mailmessage.h" +#include "mail_cache_db.h" + +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include + +int nntpdriver_nntp_error_to_mail_error(int error) +{ + switch (error) { + case NEWSNNTP_NO_ERROR: + return MAIL_NO_ERROR; + + case NEWSNNTP_ERROR_STREAM: + return MAIL_ERROR_STREAM; + + case NEWSNNTP_ERROR_UNEXPECTED: + return MAIL_ERROR_UNKNOWN; + + case NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED: + return MAIL_ERROR_FOLDER_NOT_FOUND; + + case NEWSNNTP_ERROR_NO_ARTICLE_SELECTED: + case NEWSNNTP_ERROR_INVALID_ARTICLE_NUMBER: + case NEWSNNTP_ERROR_ARTICLE_NOT_FOUND: + return MAIL_ERROR_MSG_NOT_FOUND; + + case NEWSNNTP_ERROR_UNEXPECTED_RESPONSE: + case NEWSNNTP_ERROR_INVALID_RESPONSE: + return MAIL_ERROR_PARSE; + + case NEWSNNTP_ERROR_NO_SUCH_NEWS_GROUP: + return MAIL_ERROR_FOLDER_NOT_FOUND; + + case NEWSNNTP_ERROR_POSTING_NOT_ALLOWED: + return MAIL_ERROR_READONLY; + + case NEWSNNTP_ERROR_POSTING_FAILED: + return MAIL_ERROR_APPEND; + + case NEWSNNTP_ERROR_PROGRAM_ERROR: + return MAIL_ERROR_PROGRAM_ERROR; + + case NEWSNNTP_ERROR_NO_PERMISSION: + return MAIL_ERROR_NO_PERMISSION; + + case NEWSNNTP_ERROR_COMMAND_NOT_UNDERSTOOD: + case NEWSNNTP_ERROR_COMMAND_NOT_SUPPORTED: + return MAIL_ERROR_COMMAND_NOT_SUPPORTED; + + case NEWSNNTP_ERROR_CONNECTION_REFUSED: + return MAIL_ERROR_CONNECT; + + case NEWSNNTP_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case NEWSNNTP_ERROR_AUTHENTICATION_REJECTED: + return MAIL_ERROR_LOGIN; + + case NEWSNNTP_ERROR_BAD_STATE: + case NEWSNNTP_ERROR_AUTHENTICATION_OUT_OF_SEQUENCE: + return MAIL_ERROR_BAD_STATE; + + case NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME: + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + default: + return MAIL_ERROR_INVAL; + } +} + +static inline struct nntp_session_state_data * +session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline newsnntp * session_get_nntp_session(mailsession * session) +{ + return session_get_data(session)->nntp_session; +} + +static inline struct nntp_cached_session_state_data * +cached_session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * cached_session_get_ancestor(mailsession * session) +{ + return cached_session_get_data(session)->nntp_ancestor; +} + +static inline struct nntp_session_state_data * +cached_session_get_ancestor_data(mailsession * session) +{ + return session_get_data(cached_session_get_ancestor(session)); +} + +static inline newsnntp * cached_session_get_nntp_session(mailsession * session) +{ + return session_get_nntp_session(cached_session_get_ancestor(session)); +} + + +int nntpdriver_authenticate_password(mailsession * session) +{ + struct nntp_session_state_data * data; + int r; + + data = session_get_data(session); + + if (data->nntp_password == NULL) + return MAIL_ERROR_LOGIN; + + r = newsnntp_authinfo_password(session_get_nntp_session(session), + data->nntp_password); + + return nntpdriver_nntp_error_to_mail_error(r); +} + +int nntpdriver_mode_reader(mailsession * session) +{ + int done; + int r; + + done = FALSE; + + do { + r = newsnntp_mode_reader(session_get_nntp_session(session)); + + switch (r) { + case NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME: + r = nntpdriver_authenticate_user(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + r = nntpdriver_authenticate_password(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_NO_ERROR: + done = TRUE; + break; + + default: + done = TRUE; + break; + } + } + while (!done); + + return MAIL_NO_ERROR; +} + +int nntpdriver_authenticate_user(mailsession * session) +{ + struct nntp_session_state_data * data; + int r; + + data = session_get_data(session); + + if (data->nntp_userid == NULL) + return MAIL_ERROR_LOGIN; + + r = newsnntp_authinfo_username(session_get_nntp_session(session), + data->nntp_userid); + + switch (r) { + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + return nntpdriver_authenticate_password(session); + + default: + return nntpdriver_nntp_error_to_mail_error(r); + } +} + +int nntpdriver_article(mailsession * session, uint32_t indx, + char ** result, + size_t * result_len) +{ + char * msg_content; + size_t msg_length; + int r; + int done; + + done = FALSE; + do { + r = newsnntp_article(session_get_nntp_session(session), + indx, &msg_content, &msg_length); + + switch (r) { + case NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME: + r = nntpdriver_authenticate_user(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + r = nntpdriver_authenticate_password(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_NO_ERROR: + done = TRUE; + break; + + default: + return nntpdriver_nntp_error_to_mail_error(r); + } + } + while (!done); + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; +} + +int nntpdriver_head(mailsession * session, uint32_t indx, + char ** result, + size_t * result_len) +{ + char * headers; + size_t headers_length; + int r; + int done; + + done = FALSE; + do { + r = newsnntp_head(session_get_nntp_session(session), + indx, &headers, &headers_length); + + switch (r) { + case NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME: + r = nntpdriver_authenticate_user(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + r = nntpdriver_authenticate_password(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_NO_ERROR: + done = TRUE; + break; + + default: + return nntpdriver_nntp_error_to_mail_error(r); + } + } + while (!done); + + * result = headers; + * result_len = headers_length; + + return MAIL_NO_ERROR; +} + +int nntpdriver_size(mailsession * session, uint32_t indx, + size_t * result) +{ + newsnntp * nntp; + struct newsnntp_xover_resp_item * item; + int r; + int done; + + nntp = session_get_nntp_session(session); + + done = FALSE; + do { + r = newsnntp_xover_single(nntp, indx, &item); + switch (r) { + case NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME: + r = nntpdriver_authenticate_user(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + r = nntpdriver_authenticate_password(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_NO_ERROR: + done = TRUE; + break; + + default: + return nntpdriver_nntp_error_to_mail_error(r); + } + } + while (!done); + + * result = item->ovr_size; + + xover_resp_item_free(item); + + return MAIL_NO_ERROR; +} + +int +nntpdriver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + uint32_t num, + struct mail_flags ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mail_flags * flags; + int res; + + snprintf(keyname, PATH_MAX, "%u-flags", num); + + r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = flags; + + return MAIL_NO_ERROR; + + err: + return res; +} + +int +nntpdriver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + uint32_t num, + struct mail_flags * flags) +{ + int r; + char keyname[PATH_MAX]; + int res; + + snprintf(keyname, PATH_MAX, "%u-flags", num); + + r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + +int nntpdriver_select_folder(mailsession * session, const char * mb) +{ + int r; + struct newsnntp_group_info * info; + newsnntp * nntp_session; + struct nntp_session_state_data * data; + char * new_name; + int done; + + data = session_get_data(session); + + if (!data->nntp_mode_reader) { + r = nntpdriver_mode_reader(session); + if (r != MAIL_NO_ERROR) + return r; + + data->nntp_mode_reader = TRUE; + } + + if (data->nntp_group_name != NULL) + if (strcmp(data->nntp_group_name, mb) == 0) + return MAIL_NO_ERROR; + + nntp_session = session_get_nntp_session(session); + + done = FALSE; + do { + r = newsnntp_group(nntp_session, mb, &info); + + switch (r) { + case NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME: + r = nntpdriver_authenticate_user(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + r = nntpdriver_authenticate_password(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_NO_ERROR: + done = TRUE; + break; + + default: + return nntpdriver_nntp_error_to_mail_error(r); + } + + } + while (!done); + + new_name = strdup(mb); + if (new_name == NULL) + return MAIL_ERROR_MEMORY; + + if (data->nntp_group_name != NULL) + free(data->nntp_group_name); + data->nntp_group_name = new_name; + if (data->nntp_group_info != NULL) + newsnntp_group_free(data->nntp_group_info); + data->nntp_group_info = info; + + return MAIL_NO_ERROR; +} + + +int nntp_get_messages_list(mailsession * nntp_session, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result) +{ + carray * tab; + struct mailmessage_list * env_list; + uint32_t i; + int res; + int r; + struct nntp_session_state_data * data; + struct newsnntp_group_info * group_info; + uint32_t max; + unsigned int cur; + + data = session_get_data(nntp_session); + + if (data->nntp_group_name == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + r = nntpdriver_select_folder(nntp_session, data->nntp_group_name); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + group_info = data->nntp_group_info; + + if (group_info == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + max = group_info->grp_first; + if (data->nntp_max_articles != 0) { + if (group_info->grp_last - data->nntp_max_articles + 1 > max) + max = group_info->grp_last - data->nntp_max_articles + 1; + } + + tab = carray_new(128); + if (tab == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = max ; i <= group_info->grp_last ; i++) { + mailmessage * msg; + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = mailmessage_init(msg, session, driver, i, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg); + res = r; + goto free_list; + } + + r = carray_add(tab, msg, NULL); + if (r < 0) { + mailmessage_free(msg); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + env_list = mailmessage_list_new(tab); + if (env_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = env_list; + + return MAIL_NO_ERROR; + + free_list: + for(cur = 0 ; cur < carray_count(tab) ; cur ++) + mailmessage_free(carray_get(tab, cur)); + carray_free(tab); + err: + return res; +} diff --git a/Sources/libetpan/driver/implementation/nntp/nntpdriver_tools.h b/Sources/libetpan/driver/implementation/nntp/nntpdriver_tools.h new file mode 100644 index 00000000..c1fc9be9 --- /dev/null +++ b/Sources/libetpan/driver/implementation/nntp/nntpdriver_tools.h @@ -0,0 +1,88 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver_tools.h,v 1.13 2008/02/20 22:15:50 hoa Exp $ + */ + +#ifndef NNTPDRIVER_TOOLS_H + +#define NNTPDRIVER_TOOLS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mail_cache_db_types.h" +#include "nntpdriver_types.h" + +int nntpdriver_nntp_error_to_mail_error(int error); + +int nntpdriver_authenticate_password(mailsession * session); + +int nntpdriver_authenticate_user(mailsession * session); + +int nntpdriver_article(mailsession * session, uint32_t indx, + char ** result, size_t * result_len); + +int nntpdriver_head(mailsession * session, uint32_t indx, + char ** result, + size_t * result_len); + +int nntpdriver_size(mailsession * session, uint32_t indx, + size_t * result); + +int +nntpdriver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + uint32_t num, + struct mail_flags ** result); + +int +nntpdriver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + uint32_t num, + struct mail_flags * flags); + +int nntpdriver_select_folder(mailsession * session, const char * mb); + +int nntp_get_messages_list(mailsession * nntp_session, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result); + +int nntpdriver_mode_reader(mailsession * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/nntp/nntpdriver_types.h b/Sources/libetpan/driver/implementation/nntp/nntpdriver_types.h new file mode 100644 index 00000000..6a9d57ab --- /dev/null +++ b/Sources/libetpan/driver/implementation/nntp/nntpdriver_types.h @@ -0,0 +1,149 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver_types.h,v 1.10 2007/06/30 12:58:21 hoa Exp $ + */ + +#ifndef NNTPDRIVER_TYPES_H + +#define NNTPDRIVER_TYPES_H + +#include + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* NNTP driver for session */ + +enum { + NNTPDRIVER_SET_MAX_ARTICLES = 1 +}; + +struct nntp_session_state_data { + newsnntp * nntp_session; + char * nntp_userid; + char * nntp_password; + + struct newsnntp_group_info * nntp_group_info; + char * nntp_group_name; + + clist * nntp_subscribed_list; + + uint32_t nntp_max_articles; + + int nntp_mode_reader; +}; + +/* cached NNTP driver for session */ + +enum { + /* the mapping of the parameters should be the same as for nntp */ + NNTPDRIVER_CACHED_SET_MAX_ARTICLES = 1, + /* cache specific */ + NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY, + NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY +}; + +struct nntp_cached_session_state_data { + mailsession * nntp_ancestor; + char nntp_cache_directory[PATH_MAX]; + char nntp_flags_directory[PATH_MAX]; + struct mail_flags_store * nntp_flags_store; +}; + + +/* nntp storage */ + +/* + nntp_mailstorage is the state data specific to the IMAP4rev1 storage. + + - storage this is the storage to initialize. + + - servername this is the name of the NNTP server + + - port is the port to connect to, on the server. + you give 0 to use the default port. + + - connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN or CONNECTION_TYPE_TLS. + + - auth_type is the authenticate mechanism to use. + The value can be NNTP_AUTH_TYPE_PLAIN. + + - login is the login of the POP3 account. + + - password is the password of the POP3 account. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache + + - flags_directory is the location of the flags +*/ + +struct nntp_mailstorage { + char * nntp_servername; + uint16_t nntp_port; + char * nntp_command; + int nntp_connection_type; + + int nntp_auth_type; + char * nntp_login; + char * nntp_password; + + int nntp_cached; + char * nntp_cache_directory; + char * nntp_flags_directory; + + char * nntp_local_address; + uint16_t nntp_local_port; +}; + +/* this is the type of NNTP authentication */ + +enum { + NNTP_AUTH_TYPE_PLAIN /* plain text authentication */ +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/nntp/nntpstorage.c b/Sources/libetpan/driver/implementation/nntp/nntpstorage.c new file mode 100644 index 00000000..e73a80ab --- /dev/null +++ b/Sources/libetpan/driver/implementation/nntp/nntpstorage.c @@ -0,0 +1,308 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpstorage.c,v 1.19 2008/02/17 13:13:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "nntpstorage.h" + +#include +#include + +#include "maildriver.h" +#include "nntpdriver.h" +#include "nntpdriver_cached.h" +#include "mailstorage_tools.h" +#include "mail.h" + +/* nntp storage */ + +#define NNTP_DEFAULT_PORT 119 +#define NNTPS_DEFAULT_PORT 563 + +static int nntp_mailstorage_connect(struct mailstorage * storage); +static int nntp_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result); +static void nntp_mailstorage_uninitialize(struct mailstorage * storage); + +static mailstorage_driver nntp_mailstorage_driver = { + /* sto_name */ "nntp", + /* sto_connect */ nntp_mailstorage_connect, + /* sto_get_folder_session */ nntp_mailstorage_get_folder_session, + /* sto_uninitialize */ nntp_mailstorage_uninitialize +}; + +LIBETPAN_EXPORT +int nntp_mailstorage_init(struct mailstorage * storage, + const char * nntp_servername, uint16_t nntp_port, + const char * nntp_command, + int nntp_connection_type, int nntp_auth_type, + const char * nntp_login, const char * nntp_password, + int nntp_cached, + const char * nntp_cache_directory, const char * nntp_flags_directory) +{ + return nntp_mailstorage_init_with_local_address(storage, + nntp_servername, nntp_port, + NULL, 0, + nntp_command, + nntp_connection_type, nntp_auth_type, + nntp_login, nntp_password, + nntp_cached, nntp_cache_directory, + nntp_flags_directory); +} + +LIBETPAN_EXPORT +int nntp_mailstorage_init_with_local_address(struct mailstorage * storage, + const char * nntp_servername, uint16_t nntp_port, + const char * nntp_local_address, uint16_t nntp_local_port, + const char * nntp_command, + int nntp_connection_type, int nntp_auth_type, + const char * nntp_login, const char * nntp_password, + int nntp_cached, const char * nntp_cache_directory, + const char * nntp_flags_directory) +{ + struct nntp_mailstorage * nntp_storage; + int res; + + nntp_storage = malloc(sizeof(* nntp_storage)); + if (nntp_storage == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if (nntp_servername != NULL) { + nntp_storage->nntp_servername = strdup(nntp_servername); + if (nntp_storage->nntp_servername == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + } + else { + nntp_storage->nntp_servername = NULL; + } + + if (nntp_local_address != NULL) { + nntp_storage->nntp_local_address = strdup(nntp_local_address); + if (nntp_storage->nntp_local_address == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_servername; + } + } + else { + nntp_storage->nntp_local_address = NULL; + } + + nntp_storage->nntp_local_port = nntp_local_port; + + nntp_storage->nntp_connection_type = nntp_connection_type; + + if (nntp_port == 0) { + switch (nntp_connection_type) { + case CONNECTION_TYPE_PLAIN: + case CONNECTION_TYPE_COMMAND: + nntp_port = NNTP_DEFAULT_PORT; + break; + + case CONNECTION_TYPE_TLS: + case CONNECTION_TYPE_COMMAND_TLS: + nntp_port = NNTPS_DEFAULT_PORT; + break; + + default: + nntp_port = NNTP_DEFAULT_PORT; + break; + } + } + + nntp_storage->nntp_port = nntp_port; + + if (nntp_command != NULL) { + nntp_storage->nntp_command = strdup(nntp_command); + if (nntp_storage->nntp_command == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_local_address; + } + } + else + nntp_storage->nntp_command = NULL; + + nntp_storage->nntp_auth_type = nntp_auth_type; + + if (nntp_login != NULL) { + nntp_storage->nntp_login = strdup(nntp_login); + if (nntp_storage->nntp_login == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_command; + } + } + else + nntp_storage->nntp_login = NULL; + + if (nntp_password != NULL) { + nntp_storage->nntp_password = strdup(nntp_password); + if (nntp_storage->nntp_password == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_login; + } + } + else + nntp_storage->nntp_password = NULL; + + nntp_storage->nntp_cached = nntp_cached; + + if (nntp_cached && (nntp_cache_directory != NULL) && + (nntp_flags_directory != NULL)) { + nntp_storage->nntp_cache_directory = strdup(nntp_cache_directory); + if (nntp_storage->nntp_cache_directory == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_password; + } + nntp_storage->nntp_flags_directory = strdup(nntp_flags_directory); + if (nntp_storage->nntp_flags_directory == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_cache_directory; + } + } + else { + nntp_storage->nntp_cached = FALSE; + nntp_storage->nntp_cache_directory = NULL; + nntp_storage->nntp_flags_directory = NULL; + } + + storage->sto_data = nntp_storage; + storage->sto_driver = &nntp_mailstorage_driver; + + return MAIL_NO_ERROR; + + free_cache_directory: + free(nntp_storage->nntp_cache_directory); + free_password: + free(nntp_storage->nntp_password); + free_login: + free(nntp_storage->nntp_login); + free_command: + free(nntp_storage->nntp_command); + free_local_address: + free(nntp_storage->nntp_local_address); + free_servername: + free(nntp_storage->nntp_servername); + free: + free(nntp_storage); + err: + return res; +} + +static void nntp_mailstorage_uninitialize(struct mailstorage * storage) +{ + struct nntp_mailstorage * nntp_storage; + + nntp_storage = storage->sto_data; + + free(nntp_storage->nntp_flags_directory); + free(nntp_storage->nntp_cache_directory); + free(nntp_storage->nntp_password); + free(nntp_storage->nntp_login); + free(nntp_storage->nntp_command); + free(nntp_storage->nntp_local_address); + free(nntp_storage->nntp_servername); + free(nntp_storage); + + storage->sto_data = NULL; +} + +static int nntp_mailstorage_connect(struct mailstorage * storage) +{ + struct nntp_mailstorage * nntp_storage; + mailsession_driver * driver; + int r; + int res; + mailsession * session; + + nntp_storage = storage->sto_data; + + if (nntp_storage->nntp_cached) + driver = nntp_cached_session_driver; + else + driver = nntp_session_driver; + + r = mailstorage_generic_connect_with_local_address(driver, + nntp_storage->nntp_servername, nntp_storage->nntp_port, + nntp_storage->nntp_local_address, nntp_storage->nntp_local_port, + nntp_storage->nntp_command, + nntp_storage->nntp_connection_type, + NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY, + nntp_storage->nntp_cache_directory, + NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY, + nntp_storage->nntp_flags_directory, + &session); + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto err; + } + + r = mailstorage_generic_auth(session, r, + nntp_storage->nntp_connection_type, + nntp_storage->nntp_login, + nntp_storage->nntp_password); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + storage->sto_session = session; + + return MAIL_NO_ERROR; + + free: + mailsession_free(session); + err: + return res; +} + +static int nntp_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result) +{ + mailsession_select_folder(storage->sto_session, pathname); + + * result = storage->sto_session; + + return MAIL_NO_ERROR; +} diff --git a/Sources/libetpan/driver/implementation/nntp/nntpstorage.h b/Sources/libetpan/driver/implementation/nntp/nntpstorage.h new file mode 100644 index 00000000..15451a17 --- /dev/null +++ b/Sources/libetpan/driver/implementation/nntp/nntpstorage.h @@ -0,0 +1,104 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpstorage.h,v 1.11 2007/06/30 12:58:21 hoa Exp $ + */ + +#ifndef NNTPSTORAGE_H + +#define NNTPSTORAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + nntp_mailstorage_init is the constructor for a NNTP storage + + @param storage this is the storage to initialize. + + @param servername this is the name of the NNTP server + + @param port is the port to connect to, on the server. + you give 0 to use the default port. + + @param command the command used to connect to the server instead of + allowing normal TCP connections to be used. + + @param connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS, + CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS, + CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS, + CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,. + + @param auth_type is the authenticate mechanism to use. + The value can be NNTP_AUTH_TYPE_PLAIN. + + @param login is the login of the POP3 account. + + @param password is the password of the POP3 account. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache + + @param flags_directory is the location of the flags +*/ + +LIBETPAN_EXPORT +int nntp_mailstorage_init(struct mailstorage * storage, + const char * nntp_servername, uint16_t nntp_port, + const char * nntp_command, + int nntp_connection_type, int nntp_auth_type, + const char * nntp_login, const char * nntp_password, + int nntp_cached, const char * nntp_cache_directory, + const char * nntp_flags_directory); + +LIBETPAN_EXPORT +int nntp_mailstorage_init_with_local_address(struct mailstorage * storage, + const char * nntp_servername, uint16_t nntp_port, + const char * nntp_local_servername, uint16_t nntp_local_port, + const char * nntp_command, + int nntp_connection_type, int nntp_auth_type, + const char * nntp_login, const char * nntp_password, + int nntp_cached, const char * nntp_cache_directory, + const char * nntp_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/pop3/Makefile.am b/Sources/libetpan/driver/implementation/pop3/Makefile.am new file mode 100644 index 00000000..0f9db314 --- /dev/null +++ b/Sources/libetpan/driver/implementation/pop3/Makefile.am @@ -0,0 +1,56 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +etpaninclude_HEADERS = \ + pop3driver.h \ + pop3driver_cached.h \ + pop3driver_cached_message.h \ + pop3driver_message.h \ + pop3driver_types.h \ + pop3storage.h + +AM_CPPFLAGS = -I$(top_builddir)/include \ + -I$(top_srcdir)/src/driver/interface \ + -I$(top_srcdir)/src/driver/tools \ + -I$(top_srcdir)/src/low-level/pop3 \ + -I$(top_srcdir)/src/low-level/mime \ + -I$(top_srcdir)/src/low-level/imf \ + -I$(top_srcdir)/src/data-types + +noinst_LTLIBRARIES = libpop3.la + +libpop3_la_SOURCES = \ + pop3driver.c \ + pop3driver_cached.c \ + pop3driver_cached_message.c \ + pop3driver_message.c \ + pop3driver_tools.h pop3driver_tools.c \ + pop3storage.c diff --git a/Sources/libetpan/driver/implementation/pop3/pop3driver.c b/Sources/libetpan/driver/implementation/pop3/pop3driver.c new file mode 100644 index 00000000..fff68a97 --- /dev/null +++ b/Sources/libetpan/driver/implementation/pop3/pop3driver.c @@ -0,0 +1,450 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver.c,v 1.46 2010/04/05 14:43:49 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "pop3driver.h" + +#include +#include + +#include "pop3driver_message.h" +#include "maildriver_tools.h" +#include "pop3driver_tools.h" +#include "mailmessage.h" + +static int pop3driver_initialize(mailsession * session); + +static void pop3driver_uninitialize(mailsession * session); + +static int pop3driver_parameters(mailsession * session, + int id, void * value); + +static int pop3driver_connect_stream(mailsession * session, mailstream * s); + +static int pop3driver_starttls(mailsession * session); + +static int pop3driver_login(mailsession * session, + const char * userid, const char * password); + +static int pop3driver_logout(mailsession * session); + +static int pop3driver_noop(mailsession * session); + +static int pop3driver_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int pop3driver_messages_number(mailsession * session, const char * mb, + uint32_t * result); + +static int pop3driver_remove_message(mailsession * session, uint32_t num); + +static int pop3driver_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int pop3driver_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int pop3driver_get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result); + +static int pop3driver_login_sasl(mailsession * session, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); + +static mailsession_driver local_pop3_session_driver = { + /* sess_name */ "pop3", + + /* sess_initialize */ pop3driver_initialize, + /* sess_uninitialize */ pop3driver_uninitialize, + + /* sess_parameters */ pop3driver_parameters, + + /* sess_connect_stream */ pop3driver_connect_stream, + /* sess_connect_path */ NULL, + /* sess_starttls */ pop3driver_starttls, + /* sess_login */ pop3driver_login, + /* sess_logout */ pop3driver_logout, + /* sess_noop */ pop3driver_noop, + + /* sess_build_folder_name */ NULL, + /* sess_create_folder */ NULL, + /* sess_delete_folder */ NULL, + /* sess_rename_folder */ NULL, + /* sess_check_folder */ NULL, + /* sess_examine_folder */ NULL, + /* sess_select_folder */ NULL, + /* sess_expunge_folder */ NULL, + /* sess_status_folder */ pop3driver_status_folder, + /* sess_messages_number */ pop3driver_messages_number, + /* sess_recent_number */ pop3driver_messages_number, + /* sess_unseen_number */ pop3driver_messages_number, + /* sess_list_folders */ NULL, + /* sess_lsub_folders */ NULL, + /* sess_subscribe_folder */ NULL, + /* sess_unsubscribe_folder */ NULL, + + /* sess_append_message */ NULL, + /* sess_append_message_flags */ NULL, + /* sess_copy_message */ NULL, + /* sess_move_message */ NULL, + + /* sess_get_message */ pop3driver_get_message, + /* sess_get_message_by_uid */ pop3driver_get_message_by_uid, + + /* sess_get_messages_list */ pop3driver_get_messages_list, + /* sess_get_envelopes_list */ maildriver_generic_get_envelopes_list, + /* sess_remove_message */ pop3driver_remove_message, + + /* sess_login_sasl */ pop3driver_login_sasl +}; + +mailsession_driver * pop3_session_driver = &local_pop3_session_driver; + +static inline struct pop3_session_state_data * +get_data(mailsession * session) +{ + return session->sess_data; +} + +static mailpop3 * get_pop3_session(mailsession * session) +{ + return get_data(session)->pop3_session; +} + +static int pop3driver_initialize(mailsession * session) +{ + struct pop3_session_state_data * data; + mailpop3 * pop3; + + pop3 = mailpop3_new(0, NULL); + if (session == NULL) + goto err; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto free; + + data->pop3_session = pop3; + data->pop3_auth_type = POP3DRIVER_AUTH_TYPE_PLAIN; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free: + mailpop3_free(pop3); + err: + return MAIL_ERROR_MEMORY; +} + +static void pop3driver_uninitialize(mailsession * session) +{ + struct pop3_session_state_data * data; + + data = get_data(session); + + mailpop3_free(data->pop3_session); + free(data); + + session->sess_data = NULL; +} + +static int pop3driver_connect_stream(mailsession * session, mailstream * s) +{ + int r; + + r = mailpop3_connect(get_pop3_session(session), s); + + switch (r) { + case MAILPOP3_NO_ERROR: + return MAIL_NO_ERROR_NON_AUTHENTICATED; + + default: + return pop3driver_pop3_error_to_mail_error(r); + } +} + +static int pop3driver_starttls(mailsession * session) +{ + int r; + mailpop3 * pop3; + + pop3 = get_pop3_session(session); + + r = mailpop3_socket_starttls(pop3); + return pop3driver_pop3_error_to_mail_error(r); +} + +static int pop3driver_parameters(mailsession * session, + int id, void * value) +{ + struct pop3_session_state_data * data; + + data = get_data(session); + + switch (id) { + case POP3DRIVER_SET_AUTH_TYPE: + { + int * param; + + param = value; + + data->pop3_auth_type = * param; + return MAIL_NO_ERROR; + } + break; + case POP3DRIVER_CACHED_SET_SSL_CALLBACK: + data->pop3_ssl_callback = value; + break; + case POP3DRIVER_CACHED_SET_SSL_CALLBACK_DATA: + data->pop3_ssl_cb_data = value; + break; + } + + return MAIL_ERROR_INVAL; +} + +static int pop3driver_login(mailsession * session, + const char * userid, const char * password) +{ + int r; + carray * msg_tab; + struct pop3_session_state_data * data; + + data = get_data(session); + + switch (data->pop3_auth_type) { + case POP3DRIVER_AUTH_TYPE_TRY_APOP: + r = mailpop3_login_apop(get_pop3_session(session), userid, password); + if (r != MAILPOP3_NO_ERROR) + r = mailpop3_login(get_pop3_session(session), userid, password); + break; + + case POP3DRIVER_AUTH_TYPE_APOP: + r = mailpop3_login_apop(get_pop3_session(session), userid, password); + break; + + default: + case POP3DRIVER_AUTH_TYPE_PLAIN: + r = mailpop3_login(get_pop3_session(session), userid, password); + break; + } + + if (r != MAILPOP3_NO_ERROR) + return pop3driver_pop3_error_to_mail_error(r); + + r = mailpop3_list(get_pop3_session(session), &msg_tab); + + return pop3driver_pop3_error_to_mail_error(r); +} + +static int pop3driver_logout(mailsession * session) +{ + int r; + + r = mailpop3_quit(get_pop3_session(session)); + + return pop3driver_pop3_error_to_mail_error(r); +} + +static int pop3driver_noop(mailsession * session) +{ + int r; + + r = mailpop3_noop(get_pop3_session(session)); + + return pop3driver_pop3_error_to_mail_error(r); +} + +static int pop3driver_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, + uint32_t * result_recent, + uint32_t * result_unseen) +{ + uint32_t count; + int r; + + count = 0; + r = pop3driver_messages_number(session, mb, &count); + if (r != MAIL_NO_ERROR) + return r; + + * result_messages = count; + * result_recent = count; + * result_unseen = count; + + return MAIL_NO_ERROR; +} + +static int pop3driver_messages_number(mailsession * session, const char * mb, + uint32_t * result) +{ + carray * msg_tab; + int r; + + r = mailpop3_list(get_pop3_session(session), &msg_tab); + if (r != MAILPOP3_NO_ERROR) { + return pop3driver_pop3_error_to_mail_error(r); + } + + * result = carray_count(msg_tab) - + get_pop3_session(session)->pop3_deleted_count; + + return MAIL_NO_ERROR; +} + + +/* messages operations */ + +static int pop3driver_remove_message(mailsession * session, uint32_t num) +{ + mailpop3 * pop3; + int r; + + pop3 = get_pop3_session(session); + + r = mailpop3_dele(pop3, num); + switch (r) { + case MAILPOP3_ERROR_BAD_STATE: + return MAIL_ERROR_BAD_STATE; + + case MAILPOP3_ERROR_NO_SUCH_MESSAGE: + return MAIL_ERROR_MSG_NOT_FOUND; + + case MAILPOP3_ERROR_STREAM: + return MAIL_ERROR_STREAM; + + case MAILPOP3_NO_ERROR: + return MAIL_NO_ERROR; + + default: + return MAIL_ERROR_REMOVE; + } +} + +static int pop3driver_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + mailpop3 * pop3; + + pop3 = get_pop3_session(session); + + return pop3_get_messages_list(pop3, session, + pop3_message_driver, result); +} + +static int pop3driver_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, pop3_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int pop3driver_get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result) +{ + mailpop3 * pop3; + struct mailpop3_msg_info * msg_info; + int found; + unsigned int i; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + pop3 = get_pop3_session(session); + + found = 0; + + /* iterate all messages and look for uid */ + for(i = 0 ; i < carray_count(pop3->pop3_msg_tab) ; i++) { + msg_info = carray_get(pop3->pop3_msg_tab, i); + + if (msg_info == NULL) + continue; + + if (msg_info->msg_deleted) + continue; + + /* uid found, stop looking */ + if (strcmp(msg_info->msg_uidl, uid) == 0) { + found = 1; + break; + } + } + + if (!found) + return MAIL_ERROR_MSG_NOT_FOUND; + + return pop3driver_get_message(session, msg_info->msg_index, result); +} + +static int pop3driver_login_sasl(mailsession * session, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm) +{ + int r; + + r = mailpop3_auth(get_pop3_session(session), + auth_type, server_fqdn, local_ip_port, remote_ip_port, + login, auth_name, password, realm); + + return pop3driver_pop3_error_to_mail_error(r); +} diff --git a/Sources/libetpan/driver/implementation/pop3/pop3driver.h b/Sources/libetpan/driver/implementation/pop3/pop3driver.h new file mode 100644 index 00000000..5224e49b --- /dev/null +++ b/Sources/libetpan/driver/implementation/pop3/pop3driver.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver.h,v 1.15 2004/11/21 21:53:34 hoa Exp $ + */ + +#ifndef POP3DRIVER_H + +#define POP3DRIVER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * pop3_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/pop3/pop3driver_cached.c b/Sources/libetpan/driver/implementation/pop3/pop3driver_cached.c new file mode 100644 index 00000000..6fa167b7 --- /dev/null +++ b/Sources/libetpan/driver/implementation/pop3/pop3driver_cached.c @@ -0,0 +1,945 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver_cached.c,v 1.52 2010/04/05 14:43:49 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "pop3driver_cached.h" + +#include "libetpan-config.h" + +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include + +#include "mail.h" +#include "mail_cache_db.h" + +#include "maildriver.h" +#include "mailmessage.h" +#include "pop3driver.h" +#include "mailpop3.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "pop3driver_cached_message.h" +#include "pop3driver_tools.h" +#include "maildriver_tools.h" + +static int pop3driver_cached_initialize(mailsession * session); + +static void pop3driver_cached_uninitialize(mailsession * session); + +static int pop3driver_cached_parameters(mailsession * session, + int id, void * value); + +static int pop3driver_cached_connect_stream(mailsession * session, + mailstream * s); + +static int pop3driver_cached_starttls(mailsession * session); + +static int pop3driver_cached_login(mailsession * session, + const char * userid, const char * password); + +static int pop3driver_cached_logout(mailsession * session); + +static int pop3driver_cached_check_folder(mailsession * session); + +static int pop3driver_cached_noop(mailsession * session); + +static int pop3driver_cached_expunge_folder(mailsession * session); + +static int pop3driver_cached_status_folder(mailsession * session, + const char * mb, uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int pop3driver_cached_messages_number(mailsession * session, + const char * mb, + uint32_t * result); + +static int pop3driver_cached_recent_number(mailsession * session, + const char * mb, + uint32_t * result); + +static int pop3driver_cached_unseen_number(mailsession * session, + const char * mb, + uint32_t * result); + +static int pop3driver_cached_remove_message(mailsession * session, + uint32_t num); + +static int +pop3driver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int +pop3driver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +static int pop3driver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int pop3driver_cached_get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result); + +static int pop3driver_cached_login_sasl(mailsession * session, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); + +static mailsession_driver local_pop3_cached_session_driver = { + /* sess_name */ "pop3-cached", + + /* sess_initialize */ pop3driver_cached_initialize, + /* sess_uninitialize */ pop3driver_cached_uninitialize, + + /* sess_parameters */ pop3driver_cached_parameters, + + /* sess_connect_stream */ pop3driver_cached_connect_stream, + /* sess_connect_path */ NULL, + /* sess_starttls */ pop3driver_cached_starttls, + /* sess_login */ pop3driver_cached_login, + /* sess_logout */ pop3driver_cached_logout, + /* sess_noop */ pop3driver_cached_noop, + + /* sess_build_folder_name */ NULL, + /* sess_create_folder */ NULL, + /* sess_delete_folder */ NULL, + /* sess_rename_folder */ NULL, + /* sess_check_folder */ pop3driver_cached_check_folder, + /* sess_examine_folder */ NULL, + /* sess_select_folder */ NULL, + /* sess_expunge_folder */ pop3driver_cached_expunge_folder, + /* sess_status_folder */ pop3driver_cached_status_folder, + /* sess_messages_number */ pop3driver_cached_messages_number, + /* sess_recent_number */ pop3driver_cached_recent_number, + /* sess_unseen_number */ pop3driver_cached_unseen_number, + /* sess_list_folders */ NULL, + /* sess_lsub_folders */ NULL, + /* sess_subscribe_folder */ NULL, + /* sess_unsubscribe_folder */ NULL, + + /* sess_append_message */ NULL, + /* sess_append_message_flags */ NULL, + /* sess_copy_message */ NULL, + /* sess_move_message */ NULL, + + /* sess_get_message */ pop3driver_cached_get_message, + /* sess_get_message_by_uid */ pop3driver_cached_get_message_by_uid, + + /* sess_get_messages_list */ pop3driver_cached_get_messages_list, + /* sess_get_envelopes_list */ pop3driver_cached_get_envelopes_list, + /* sess_remove_message */ pop3driver_cached_remove_message, +#if 0 + /* sess_search_messages */ maildriver_generic_search_messages, +#endif + /* sess_login_sasl */ pop3driver_cached_login_sasl +}; + +mailsession_driver * pop3_cached_session_driver = +&local_pop3_cached_session_driver; + +#define ENV_NAME "env.db" +#define FLAGS_NAME "flags.db" + + +static inline struct pop3_cached_session_state_data * +get_cached_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * get_ancestor(mailsession * session) +{ + return get_cached_data(session)->pop3_ancestor; +} + +static inline struct pop3_session_state_data * +get_ancestor_data(mailsession * session) +{ + return get_ancestor(session)->sess_data; +} + +static inline mailpop3 * get_pop3_session(mailsession * session) +{ + return get_ancestor_data(session)->pop3_session; +} + +static int pop3driver_cached_initialize(mailsession * session) +{ + struct pop3_cached_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->pop3_flags_store = mail_flags_store_new(); + if (data->pop3_flags_store == NULL) + goto free_data; + + data->pop3_ancestor = mailsession_new(pop3_session_driver); + if (data->pop3_ancestor == NULL) + goto free_store; + + data->pop3_flags_hash = chash_new(128, CHASH_COPYNONE); + if (data->pop3_flags_hash == NULL) + goto free_session; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free_session: + mailsession_free(data->pop3_ancestor); + free_store: + mail_flags_store_free(data->pop3_flags_store); + free_data: + free(data); + err: + return MAIL_ERROR_MEMORY; +} + +static int pop3_flags_store_process(char * flags_directory, + struct mail_flags_store * flags_store) +{ + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + unsigned int i; + int r; + int res; + + if (carray_count(flags_store->fls_tab) == 0) + return MAIL_NO_ERROR; + + snprintf(filename_flags, PATH_MAX, "%s/%s", + flags_directory, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(flags_store->fls_tab, i); + + r = pop3driver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + mail_flags_store_clear(flags_store); + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static void pop3driver_cached_uninitialize(mailsession * session) +{ + struct pop3_cached_session_state_data * data; + + data = get_cached_data(session); + + pop3_flags_store_process(data->pop3_flags_directory, + data->pop3_flags_store); + + mail_flags_store_free(data->pop3_flags_store); + + chash_free(data->pop3_flags_hash); + mailsession_free(data->pop3_ancestor); + free(data); + + session->sess_data = NULL; +} + +static int pop3driver_cached_check_folder(mailsession * session) +{ + struct pop3_cached_session_state_data * pop3_data; + + pop3_data = get_cached_data(session); + + pop3_flags_store_process(pop3_data->pop3_flags_directory, + pop3_data->pop3_flags_store); + + return MAIL_NO_ERROR; +} + +static int pop3driver_cached_parameters(mailsession * session, + int id, void * value) +{ + struct pop3_cached_session_state_data * data; + int r; + + data = get_cached_data(session); + + switch (id) { + case POP3DRIVER_CACHED_SET_CACHE_DIRECTORY: + strncpy(data->pop3_cache_directory, value, PATH_MAX); + data->pop3_cache_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(data->pop3_cache_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + case POP3DRIVER_CACHED_SET_FLAGS_DIRECTORY: + strncpy(data->pop3_flags_directory, value, PATH_MAX); + data->pop3_flags_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(data->pop3_flags_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + default: + return mailsession_parameters(data->pop3_ancestor, id, value); + } +} + +static int pop3driver_cached_connect_stream(mailsession * session, + mailstream * s) +{ + int r; + + r = mailsession_connect_stream(get_ancestor(session), s); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; +} + +static int pop3driver_cached_starttls(mailsession * session) +{ + return mailsession_starttls(get_ancestor(session)); +} + + +static int pop3driver_cached_login(mailsession * session, + const char * userid, const char * password) +{ + return mailsession_login(get_ancestor(session), userid, password); +} + +static int pop3driver_cached_logout(mailsession * session) +{ + struct pop3_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + + pop3_flags_store_process(cached_data->pop3_flags_directory, + cached_data->pop3_flags_store); + + return mailsession_logout(get_ancestor(session)); +} + +static int pop3driver_cached_noop(mailsession * session) +{ + return mailsession_noop(get_ancestor(session)); +} + +static int pop3driver_cached_expunge_folder(mailsession * session) +{ + int res; + struct pop3_cached_session_state_data * cached_data; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + unsigned int i; + int r; + carray * msg_tab; + mailpop3 * pop3; + + pop3 = get_pop3_session(session); + + cached_data = get_cached_data(session); + + pop3_flags_store_process(cached_data->pop3_flags_directory, + cached_data->pop3_flags_store); + + snprintf(filename_flags, PATH_MAX, "%s/%s", + cached_data->pop3_flags_directory, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + r = mailpop3_list(pop3, &msg_tab); + if (r != MAILPOP3_NO_ERROR) { + res = pop3driver_pop3_error_to_mail_error(r); + goto free_mmapstr; + } + + for(i = 0 ; i < carray_count(msg_tab) ; i++) { + struct mailpop3_msg_info * pop3_info; + struct mail_flags * flags; + + pop3_info = carray_get(msg_tab, i); + if (pop3_info == NULL) + continue; + + if (pop3_info->msg_deleted) + continue; + + r = pop3driver_get_cached_flags(cache_db_flags, mmapstr, + session, pop3_info->msg_index, &flags); + if (r != MAIL_NO_ERROR) + continue; + + if (flags->fl_flags & MAIL_FLAG_DELETED) { + r = mailpop3_dele(pop3, pop3_info->msg_index); + } + + mail_flags_free(flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int pop3driver_cached_status_folder(mailsession * session, + const char * mb, uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + int res; + struct pop3_cached_session_state_data * cached_data; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + unsigned int i; + int r; + carray * msg_tab; + mailpop3 * pop3; + uint32_t recent; + uint32_t unseen; + + recent = 0; + unseen = 0; + + pop3 = get_pop3_session(session); + + cached_data = get_cached_data(session); + + pop3_flags_store_process(cached_data->pop3_flags_directory, + cached_data->pop3_flags_store); + + snprintf(filename_flags, PATH_MAX, "%s/%s", + cached_data->pop3_flags_directory, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + r = mailpop3_list(pop3, &msg_tab); + if (r != MAILPOP3_NO_ERROR) { + res = pop3driver_pop3_error_to_mail_error(r); + goto free_mmapstr; + } + + for(i = 0 ; i < carray_count(msg_tab) ; i++) { + struct mailpop3_msg_info * pop3_info; + struct mail_flags * flags; + + pop3_info = carray_get(msg_tab, i); + if (pop3_info == NULL) + continue; + + if (pop3_info->msg_deleted) + continue; + + r = pop3driver_get_cached_flags(cache_db_flags, mmapstr, + session, pop3_info->msg_index, &flags); + if (r != MAIL_NO_ERROR) { + recent ++; + unseen ++; + continue; + } + + if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) { + recent ++; + } + if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) { + unseen ++; + } + mail_flags_free(flags); + + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + * result_messages = carray_count(msg_tab) - pop3->pop3_deleted_count; + * result_recent = recent; + * result_unseen = unseen; + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int pop3driver_cached_messages_number(mailsession * session, + const char * mb, + uint32_t * result) +{ + return mailsession_messages_number(get_ancestor(session), mb, result); +} + +static int pop3driver_cached_recent_number(mailsession * session, + const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = pop3driver_cached_status_folder(session, mb, + &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = recent; + + return MAIL_NO_ERROR; +} + +static int pop3driver_cached_unseen_number(mailsession * session, + const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + messages = 0; + recent = 0; + unseen = 0; + r = pop3driver_cached_status_folder(session, mb, + &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = unseen; + + return MAIL_NO_ERROR; +} + +/* messages operations */ + +static int pop3driver_cached_remove_message(mailsession * session, + uint32_t num) +{ + return mailsession_remove_message(get_ancestor(session), num); +} + +static int +pop3driver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + mailpop3 * pop3; + + pop3 = get_pop3_session(session); + + return pop3_get_messages_list(pop3, session, + pop3_cached_message_driver, result); +} + + +static int +get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mailpop3_msg_info * info; + struct mailimf_fields * fields; + int res; + mailpop3 * pop3; + + pop3 = get_pop3_session(session); + + r = mailpop3_get_msg_info(pop3, num, &info); + switch (r) { + case MAILPOP3_ERROR_BAD_STATE: + return MAIL_ERROR_BAD_STATE; + case MAILPOP3_ERROR_NO_SUCH_MESSAGE: + return MAIL_ERROR_MSG_NOT_FOUND; + case MAILPOP3_NO_ERROR: + break; + default: + return MAIL_ERROR_FETCH; + } + + snprintf(keyname, PATH_MAX, "%s-envelope", info->msg_uidl); + + r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = fields; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +write_cached_envelope(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields * fields) +{ + int r; + char keyname[PATH_MAX]; + int res; + struct mailpop3_msg_info * info; + mailpop3 * pop3; + + pop3 = get_pop3_session(session); + + r = mailpop3_get_msg_info(pop3, num, &info); + switch (r) { + case MAILPOP3_ERROR_BAD_STATE: + return MAIL_ERROR_BAD_STATE; + case MAILPOP3_ERROR_NO_SUCH_MESSAGE: + return MAIL_ERROR_MSG_NOT_FOUND; + case MAILPOP3_NO_ERROR: + break; + default: + return MAIL_ERROR_FETCH; + } + + snprintf(keyname, PATH_MAX, "%s-envelope", info->msg_uidl); + + r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +static void get_uid_from_filename(char * filename) +{ + char * p; + + p = strstr(filename, "-header"); + if (p != NULL) + * p = 0; +} + +static int +pop3driver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + unsigned int i; + struct pop3_cached_session_state_data * cached_data; + char filename_env[PATH_MAX]; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_env; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + int res; + + cached_data = get_cached_data(session); + + pop3_flags_store_process(cached_data->pop3_flags_directory, + cached_data->pop3_flags_store); + + snprintf(filename_env, PATH_MAX, "%s/%s", + cached_data->pop3_cache_directory, ENV_NAME); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto free_mmapstr; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s", + cached_data->pop3_flags_directory, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto close_db_env; + } + + /* fill with cached */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailimf_fields * fields; + struct mail_flags * flags; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + r = get_cached_envelope(cache_db_env, mmapstr, + session, msg->msg_index, &fields); + if (r == MAIL_NO_ERROR) { + msg->msg_cached = TRUE; + msg->msg_fields = fields; + } + } + + if (msg->msg_flags == NULL) { + r = pop3driver_get_cached_flags(cache_db_flags, mmapstr, + session, msg->msg_index, &flags); + if (r == MAIL_NO_ERROR) { + msg->msg_flags = flags; + } + } + } + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + + r = maildriver_generic_get_envelopes_list(session, env_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + /* add flags */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_flags == NULL) + msg->msg_flags = mail_flags_new_empty(); + } + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto close_db_env; + } + + /* must write cache */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields != NULL) { + if (!msg->msg_cached) { + r = write_cached_envelope(cache_db_env, mmapstr, + session, msg->msg_index, msg->msg_fields); + } + } + + if (msg->msg_flags != NULL) { + r = pop3driver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + } + } + + /* flush cache */ + + maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list); + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + mmap_string_free(mmapstr); + + /* remove cache files */ + + maildriver_message_cache_clean_up(cached_data->pop3_cache_directory, + env_list, get_uid_from_filename); + + return MAIL_NO_ERROR; + + close_db_env: + mail_cache_db_close_unlock(filename_env, cache_db_env); + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + +static int pop3driver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, pop3_cached_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int pop3driver_cached_get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result) +{ + mailpop3 * pop3; + struct mailpop3_msg_info * msg_info; + int found; + unsigned int i; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + pop3 = get_pop3_session(session); + + found = 0; + + /* iterate all messages and look for uid */ + for(i = 0 ; i < carray_count(pop3->pop3_msg_tab) ; i++) { + msg_info = carray_get(pop3->pop3_msg_tab, i); + + if (msg_info == NULL) + continue; + + if (msg_info->msg_deleted) + continue; + + /* uid found, stop looking */ + if (strcmp(msg_info->msg_uidl, uid) == 0) { + found = 1; + break; + } + } + + if (!found) + return MAIL_ERROR_MSG_NOT_FOUND; + + return pop3driver_cached_get_message(session, msg_info->msg_index, result); +} + +static int pop3driver_cached_login_sasl(mailsession * session, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm) +{ + return mailsession_login_sasl(get_ancestor(session), auth_type, + server_fqdn, + local_ip_port, + remote_ip_port, + login, auth_name, + password, realm); +} diff --git a/Sources/libetpan/driver/implementation/pop3/pop3driver_cached.h b/Sources/libetpan/driver/implementation/pop3/pop3driver_cached.h new file mode 100644 index 00000000..7eb0574c --- /dev/null +++ b/Sources/libetpan/driver/implementation/pop3/pop3driver_cached.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver_cached.h,v 1.15 2004/11/21 21:53:34 hoa Exp $ + */ + +#ifndef POP3DRIVER_CACHED_H + +#define POP3DRIVER_CACHED_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +extern mailsession_driver * pop3_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/pop3/pop3driver_cached_message.c b/Sources/libetpan/driver/implementation/pop3/pop3driver_cached_message.c new file mode 100644 index 00000000..13c208d2 --- /dev/null +++ b/Sources/libetpan/driver/implementation/pop3/pop3driver_cached_message.c @@ -0,0 +1,357 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver_cached_message.c,v 1.22 2008/02/17 13:13:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "pop3driver_cached_message.h" + +#include +#include + +#include "mail_cache_db.h" + +#include "mailmessage.h" +#include "mailmessage_tools.h" +#include "pop3driver.h" +#include "pop3driver_tools.h" +#include "pop3driver_cached.h" +#include "pop3driver_message.h" +#include "generic_cache.h" + +static int pop3_prefetch(mailmessage * msg_info); + +static void pop3_prefetch_free(struct generic_message_t * msg); + +static int pop3_initialize(mailmessage * msg_info); + +static void pop3_flush(mailmessage * msg_info); + +static void pop3_check(mailmessage * msg_info); + +static int pop3_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static int pop3_fetch_size(mailmessage * msg_info, + size_t * result); + +static int pop3_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +static void pop3_uninitialize(mailmessage * msg_info); + +static mailmessage_driver local_pop3_cached_message_driver = { + /* msg_name */ "pop3-cached", + + /* msg_initialize */ pop3_initialize, + /* msg_uninitialize */ pop3_uninitialize, + + /* msg_flush */ pop3_flush, + /* msg_check */ pop3_check, + + /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free, + + /* msg_fetch */ mailmessage_generic_fetch, + /* msg_fetch_header */ pop3_fetch_header, + /* msg_fetch_body */ mailmessage_generic_fetch_body, + /* msg_fetch_size */ pop3_fetch_size, + /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure, + /* msg_fetch_section */ mailmessage_generic_fetch_section, + /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header, + /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime, + /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body, + /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope, + + /* msg_get_flags */ pop3_get_flags +}; + +mailmessage_driver * pop3_cached_message_driver = +&local_pop3_cached_message_driver; + + +static inline struct pop3_cached_session_state_data * +get_cached_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline mailsession * get_ancestor_session(mailmessage * msg) +{ + return get_cached_session_data(msg)->pop3_ancestor; +} + +static inline struct pop3_session_state_data * +get_ancestor_session_data(mailmessage * msg) +{ + return get_ancestor_session(msg)->sess_data; +} + +static inline mailpop3 * get_pop3_session(mailmessage * msg) +{ + return get_ancestor_session_data(msg)->pop3_session; +} + + +static int pop3_prefetch(mailmessage * msg_info) +{ + char * msg_content; + size_t msg_length; + struct generic_message_t * msg; + int r; + struct pop3_cached_session_state_data * cached_data; + char filename[PATH_MAX]; + + /* we try the cached message */ + + cached_data = get_cached_session_data(msg_info); + + snprintf(filename, PATH_MAX, "%s/%s", + cached_data->pop3_cache_directory, msg_info->msg_uid); + + r = generic_cache_read(filename, &msg_content, &msg_length); + if (r == MAIL_NO_ERROR) { + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; + } + + /* we get the message through the network */ + + r = pop3driver_retr(get_ancestor_session(msg_info), msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + /* we write the message cache */ + + generic_cache_store(filename, msg_content, msg_length); + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void pop3_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static int pop3_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + struct mailpop3_msg_info * info; + mailpop3 * pop3; + + pop3 = get_pop3_session(msg_info); + + r = mailpop3_get_msg_info(pop3, msg_info->msg_index, &info); + switch (r) { + case MAILPOP3_NO_ERROR: + break; + default: + return pop3driver_pop3_error_to_mail_error(r); + } + + uid = strdup(info->msg_uidl); + if (uid == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + return r; + } + + msg = msg_info->msg_data; + msg->msg_prefetch = pop3_prefetch; + msg->msg_prefetch_free = pop3_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; +} + +static void pop3_uninitialize(mailmessage * msg_info) +{ + mailmessage_generic_uninitialize(msg_info); +} + +#define FLAGS_NAME "flags.db" + +static void pop3_flush(mailmessage * msg_info) +{ + mailmessage_generic_flush(msg_info); +} + +static void pop3_check(mailmessage * msg_info) +{ + if (msg_info->msg_flags != NULL) { + mail_flags_store_set(get_cached_session_data(msg_info)->pop3_flags_store, + msg_info); + } +} + + +static int pop3_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + char * headers; + size_t headers_length; + int r; + struct pop3_cached_session_state_data * cached_data; + char filename[PATH_MAX]; + + msg = msg_info->msg_data; + + if (msg->msg_message != NULL) + return mailmessage_generic_fetch_header(msg_info, + result, result_len); + + /* we try the cached message */ + + cached_data = get_cached_session_data(msg_info); + + snprintf(filename, PATH_MAX, "%s/%s-header", + cached_data->pop3_cache_directory, msg_info->msg_uid); + + r = generic_cache_read(filename, &headers, &headers_length); + if (r == MAIL_NO_ERROR) { + * result = headers; + * result_len = headers_length; + + return MAIL_NO_ERROR; + } + + /* we get the message trough the network */ + + r = pop3driver_header(get_ancestor_session(msg_info), msg_info->msg_index, + &headers, &headers_length); + if (r != MAIL_NO_ERROR) + return r; + + generic_cache_store(filename, headers, headers_length); + + * result = headers; + * result_len = headers_length; + + return MAIL_NO_ERROR; +} + +static int pop3_fetch_size(mailmessage * msg_info, + size_t * result) +{ + return pop3driver_size(get_ancestor_session(msg_info), + msg_info->msg_index, result); +} + +static int pop3_get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + int r; + struct mail_flags * flags; + struct mail_cache_db * cache_db_flags; + char filename_flags[PATH_MAX]; + int res; + struct pop3_cached_session_state_data * cached_data; + MMAPString * mmapstr; + + if (msg_info->msg_flags != NULL) { + * result = msg_info->msg_flags; + + return MAIL_NO_ERROR; + } + + cached_data = get_cached_session_data(msg_info); + + flags = mail_flags_store_get(cached_data->pop3_flags_store, + msg_info->msg_index); + + if (flags == NULL) { + snprintf(filename_flags, PATH_MAX, "%s/%s", + cached_data->pop3_flags_directory, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + r = pop3driver_get_cached_flags(cache_db_flags, mmapstr, + msg_info->msg_session, msg_info->msg_index, &flags); + if (r != MAIL_NO_ERROR) { + flags = mail_flags_new_empty(); + if (flags == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + } + + msg_info->msg_flags = flags; + + * result = flags; + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} diff --git a/Sources/libetpan/driver/implementation/pop3/pop3driver_cached_message.h b/Sources/libetpan/driver/implementation/pop3/pop3driver_cached_message.h new file mode 100644 index 00000000..a348c95e --- /dev/null +++ b/Sources/libetpan/driver/implementation/pop3/pop3driver_cached_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver_cached_message.h,v 1.6 2004/11/21 21:53:34 hoa Exp $ + */ + +#ifndef POP3DRIVER_CACHED_MESSAGE_H + +#define POP3DRIVER_CACHED_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * pop3_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/pop3/pop3driver_message.c b/Sources/libetpan/driver/implementation/pop3/pop3driver_message.c new file mode 100644 index 00000000..e186491d --- /dev/null +++ b/Sources/libetpan/driver/implementation/pop3/pop3driver_message.c @@ -0,0 +1,197 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver_message.c,v 1.15 2008/02/17 13:13:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "pop3driver_message.h" + +#include "mailmessage_tools.h" +#include "pop3driver_tools.h" +#include "pop3driver.h" +#include "mailpop3.h" +#include +#include + +static int pop3_prefetch(mailmessage * msg_info); + +static void pop3_prefetch_free(struct generic_message_t * msg); + +static int pop3_initialize(mailmessage * msg_info); + +static int pop3_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static int pop3_fetch_size(mailmessage * msg_info, + size_t * result); + +static mailmessage_driver local_pop3_message_driver = { + /* msg_name */ "pop3", + + /* msg_initialize */ pop3_initialize, + /* msg_uninitialize */ mailmessage_generic_uninitialize, + + /* msg_flush */ mailmessage_generic_flush, + /* msg_check */ NULL, + + /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free, + + /* msg_fetch */ mailmessage_generic_fetch, + /* msg_fetch_header */ pop3_fetch_header, + /* msg_fetch_body */ mailmessage_generic_fetch_body, + /* msg_fetch_size */ pop3_fetch_size, + /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure, + /* msg_fetch_section */ mailmessage_generic_fetch_section, + /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header, + /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime, + /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body, + /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope, + + /* msg_get_flags */ NULL +}; + +mailmessage_driver * pop3_message_driver = &local_pop3_message_driver; + +static inline struct pop3_session_state_data * +get_data(mailsession * session) +{ + return session->sess_data; +} + + +static mailpop3 * get_pop3_session(mailsession * session) +{ + return get_data(session)->pop3_session; +} + + +static int pop3_prefetch(mailmessage * msg_info) +{ + char * msg_content; + size_t msg_length; + struct generic_message_t * msg; + int r; + + r = pop3driver_retr(msg_info->msg_session, msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void pop3_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static int pop3_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + struct mailpop3_msg_info * info; + mailpop3 * pop3; + + pop3 = get_pop3_session(msg_info->msg_session); + + r = mailpop3_get_msg_info(pop3, msg_info->msg_index, &info); + switch (r) { + case MAILPOP3_NO_ERROR: + break; + default: + return pop3driver_pop3_error_to_mail_error(r); + } + + uid = strdup(info->msg_uidl); + if (uid == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + return r; + } + + msg = msg_info->msg_data; + msg->msg_prefetch = pop3_prefetch; + msg->msg_prefetch_free = pop3_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; +} + + +static int pop3_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + char * headers; + size_t headers_length; + int r; + + msg = msg_info->msg_data; + + if (msg->msg_message != NULL) + return mailmessage_generic_fetch_header(msg_info, + result, result_len); + + r = pop3driver_header(msg_info->msg_session, msg_info->msg_index, + &headers, &headers_length); + if (r != MAIL_NO_ERROR) + return r; + + * result = headers; + * result_len = headers_length; + + return MAIL_NO_ERROR; +} + +static int pop3_fetch_size(mailmessage * msg_info, + size_t * result) +{ + return pop3driver_size(msg_info->msg_session, msg_info->msg_index, result); +} diff --git a/Sources/libetpan/driver/implementation/pop3/pop3driver_message.h b/Sources/libetpan/driver/implementation/pop3/pop3driver_message.h new file mode 100644 index 00000000..0cf6bc59 --- /dev/null +++ b/Sources/libetpan/driver/implementation/pop3/pop3driver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver_message.h,v 1.6 2004/11/21 21:53:34 hoa Exp $ + */ + +#ifndef POP3DRIVER_MESSAGE_H + +#define POP3DRIVER_MESSAGE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * pop3_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/pop3/pop3driver_tools.c b/Sources/libetpan/driver/implementation/pop3/pop3driver_tools.c new file mode 100644 index 00000000..72ee4d32 --- /dev/null +++ b/Sources/libetpan/driver/implementation/pop3/pop3driver_tools.c @@ -0,0 +1,360 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver_tools.c,v 1.19 2010/04/05 14:43:49 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "pop3driver_tools.h" + +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif + +#include "maildriver_types.h" +#include "mailpop3.h" +#include "pop3driver.h" +#include "pop3driver_cached.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "mailmessage.h" +#include "mail_cache_db.h" + +int pop3driver_pop3_error_to_mail_error(int error) +{ + switch (error) { + case MAILPOP3_NO_ERROR: + return MAIL_NO_ERROR; + + case MAILPOP3_ERROR_BAD_STATE: + return MAIL_ERROR_BAD_STATE; + + case MAILPOP3_ERROR_UNAUTHORIZED: + return MAIL_ERROR_CONNECT; + + case MAILPOP3_ERROR_STREAM: + return MAIL_ERROR_STREAM; + + case MAILPOP3_ERROR_DENIED: + return MAIL_ERROR_CONNECT; + + case MAILPOP3_ERROR_BAD_USER: + case MAILPOP3_ERROR_BAD_PASSWORD: + return MAIL_ERROR_LOGIN; + + case MAILPOP3_ERROR_CANT_LIST: + return MAIL_ERROR_LIST; + + case MAILPOP3_ERROR_NO_SUCH_MESSAGE: + return MAIL_ERROR_MSG_NOT_FOUND; + + case MAILPOP3_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case MAILPOP3_ERROR_CONNECTION_REFUSED: + return MAIL_ERROR_CONNECT; + + case MAILPOP3_ERROR_APOP_NOT_SUPPORTED: + return MAIL_ERROR_NO_APOP; + + case MAILPOP3_ERROR_CAPA_NOT_SUPPORTED: + return MAIL_ERROR_CAPABILITY; + + case MAILPOP3_ERROR_STLS_NOT_SUPPORTED: + return MAIL_ERROR_NO_TLS; + + case MAILPOP3_ERROR_SSL: + return MAIL_ERROR_SSL; + + default: + return MAIL_ERROR_INVAL; + } +} + +static inline struct pop3_session_state_data * +session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailpop3 * session_get_pop3_session(mailsession * session) +{ + return session_get_data(session)->pop3_session; +} + +static inline struct pop3_cached_session_state_data * +cached_session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * +cached_session_get_ancestor(mailsession * session) +{ + return cached_session_get_data(session)->pop3_ancestor; +} + +static inline struct pop3_session_state_data * +cached_session_get_ancestor_data(mailsession * session) +{ + return session_get_data(cached_session_get_ancestor(session)); +} + +static inline mailpop3 * +cached_session_get_pop3_session(mailsession * session) +{ + return session_get_pop3_session(cached_session_get_ancestor(session)); +} + + +int pop3driver_retr(mailsession * session, uint32_t indx, + char ** result, size_t * result_len) +{ + char * msg_content; + size_t msg_length; + int r; + + r = mailpop3_retr(session_get_pop3_session(session), indx, + &msg_content, &msg_length); + + switch (r) { + case MAILPOP3_NO_ERROR: + break; + default: + return pop3driver_pop3_error_to_mail_error(r); + } + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; +} + +int pop3driver_header(mailsession * session, uint32_t indx, + char ** result, + size_t * result_len) +{ + char * headers; + size_t headers_length; + int r; + + r = mailpop3_header(session_get_pop3_session(session), + indx, &headers, &headers_length); + + switch (r) { + case MAILPOP3_NO_ERROR: + break; + default: + return pop3driver_pop3_error_to_mail_error(r); + } + + * result = headers; + * result_len = headers_length; + + return MAIL_NO_ERROR; +} + +int pop3driver_size(mailsession * session, uint32_t indx, + size_t * result) +{ + mailpop3 * pop3; + carray * msg_tab; + struct mailpop3_msg_info * info; + int r; + + pop3 = session_get_pop3_session(session); + + r = mailpop3_list(pop3, &msg_tab); + if (r != MAILPOP3_NO_ERROR) { + return pop3driver_pop3_error_to_mail_error(r); + } + + r = mailpop3_get_msg_info(pop3, indx, &info); + switch (r) { + case MAILPOP3_NO_ERROR: + break; + default: + return pop3driver_pop3_error_to_mail_error(r); + } + + * result = info->msg_size; + + return MAIL_NO_ERROR; +} + +int +pop3driver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, + uint32_t num, + struct mail_flags ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mail_flags * flags; + int res; + struct mailpop3_msg_info * info; + + r = mailpop3_get_msg_info(cached_session_get_pop3_session(session), + num, &info); + switch (r) { + case MAILPOP3_ERROR_BAD_STATE: + return MAIL_ERROR_BAD_STATE; + case MAILPOP3_ERROR_NO_SUCH_MESSAGE: + return MAIL_ERROR_MSG_NOT_FOUND; + case MAILPOP3_NO_ERROR: + break; + default: + return MAIL_ERROR_FETCH; + } + + snprintf(keyname, PATH_MAX, "%s-flags", info->msg_uidl); + + r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = flags; + + return MAIL_NO_ERROR; + + err: + return res; +} + +int +pop3driver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, + struct mail_flags * flags) +{ + int r; + char keyname[PATH_MAX]; + int res; + + snprintf(keyname, PATH_MAX, "%s-flags", uid); + + r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +int pop3_get_messages_list(mailpop3 * pop3, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result) +{ + carray * msg_tab; + carray * tab; + struct mailmessage_list * env_list; + unsigned int i; + int res; + int r; + + r = mailpop3_list(pop3, &msg_tab); + if (r != MAILPOP3_NO_ERROR) { + res = pop3driver_pop3_error_to_mail_error(r); + goto err; + } + + tab = carray_new(128); + if (tab == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < carray_count(msg_tab) ; i++) { + struct mailpop3_msg_info * pop3_info; + mailmessage * msg; + + pop3_info = carray_get(msg_tab, i); + + if (pop3_info == NULL) + continue; + + if (pop3_info->msg_deleted) + continue; + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = mailmessage_init(msg, session, driver, + (uint32_t) pop3_info->msg_index, pop3_info->msg_size); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg); + res = r; + goto free_list; + } + + r = carray_add(tab, msg, NULL); + if (r < 0) { + mailmessage_free(msg); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + env_list = mailmessage_list_new(/*list*/ tab); + if (env_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = env_list; + + return MAIL_NO_ERROR; + + free_list: + for(i = 0 ; i < carray_count(tab) ; i ++) + mailmessage_free(carray_get(tab, i)); + carray_free(tab); + err: + return res; +} diff --git a/Sources/libetpan/driver/implementation/pop3/pop3driver_tools.h b/Sources/libetpan/driver/implementation/pop3/pop3driver_tools.h new file mode 100644 index 00000000..cc31ff0e --- /dev/null +++ b/Sources/libetpan/driver/implementation/pop3/pop3driver_tools.h @@ -0,0 +1,82 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver_tools.h,v 1.11 2008/02/20 22:15:51 hoa Exp $ + */ + +#ifndef POP3DRIVER_TOOLS_H + +#define POP3DRIVER_TOOLS_H + +#include "mail_cache_db_types.h" +#include "pop3driver_types.h" +#include "mailpop3.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int pop3driver_pop3_error_to_mail_error(int error); + +int pop3driver_retr(mailsession * session, uint32_t indx, + char ** result, size_t * result_len); + +int pop3driver_header(mailsession * session, uint32_t indx, + char ** result, + size_t * result_len); + +int pop3driver_size(mailsession * session, uint32_t indx, + size_t * result); + +int +pop3driver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, + uint32_t num, + struct mail_flags ** result); + +int +pop3driver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, + struct mail_flags * flags); + +int pop3_get_messages_list(mailpop3 * pop3, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/pop3/pop3driver_types.h b/Sources/libetpan/driver/implementation/pop3/pop3driver_types.h new file mode 100644 index 00000000..e36e98b7 --- /dev/null +++ b/Sources/libetpan/driver/implementation/pop3/pop3driver_types.h @@ -0,0 +1,175 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver_types.h,v 1.11 2007/06/30 12:58:21 hoa Exp $ + */ + +#ifndef POP3DRIVER_TYPES_H + +#define POP3DRIVER_TYPES_H + +#include + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* POP3 driver for session */ + +enum { + POP3DRIVER_SET_AUTH_TYPE = 1 +}; + +enum { + POP3DRIVER_AUTH_TYPE_PLAIN = 0, + POP3DRIVER_AUTH_TYPE_APOP, + POP3DRIVER_AUTH_TYPE_TRY_APOP +}; + +struct pop3_session_state_data { + int pop3_auth_type; + mailpop3 * pop3_session; + void (* pop3_ssl_callback)(struct mailstream_ssl_context * ssl_context, void * data); + void * pop3_ssl_cb_data; +}; + +/* cached POP3 driver for session */ + +enum { + /* the mapping of the parameters should be the same as for pop3 */ + POP3DRIVER_CACHED_SET_AUTH_TYPE = 1, + POP3DRIVER_CACHED_SET_SSL_CALLBACK = 2, + POP3DRIVER_CACHED_SET_SSL_CALLBACK_DATA = 3, + /* cache specific */ + POP3DRIVER_CACHED_SET_CACHE_DIRECTORY = 1001, + POP3DRIVER_CACHED_SET_FLAGS_DIRECTORY = 1002 +}; + +struct pop3_cached_session_state_data { + mailsession * pop3_ancestor; + char pop3_cache_directory[PATH_MAX]; + char pop3_flags_directory[PATH_MAX]; + chash * pop3_flags_hash; + carray * pop3_flags_array; + struct mail_flags_store * pop3_flags_store; +}; + +/* pop3 storage */ + +/* + pop3_mailstorage is the state data specific to the POP3 storage. + + - servername this is the name of the POP3 server + + - port is the port to connect to, on the server. + you give 0 to use the default port. + + - connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS, + CONNECTION_TYPE_TRY_STARTTLS or CONNECTION_TYPE_TLS. + + - auth_type is the authenticate mechanism to use. + The value can be POP3_AUTH_TYPE_PLAIN, POP3_AUTH_TYPE_APOP + or POP3_AUTH_TYPE_TRY_APOP. Other values are not yet implemented. + + - login is the login of the POP3 account. + + - password is the password of the POP3 account. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache. + + - flags_directory is the location of the flags. +*/ + +struct pop3_mailstorage { + char * pop3_servername; + uint16_t pop3_port; + char * pop3_command; + int pop3_connection_type; + + int pop3_auth_type; + char * pop3_login; /* deprecated */ + char * pop3_password; /* deprecated */ + + int pop3_cached; + char * pop3_cache_directory; + char * pop3_flags_directory; + + struct { + int sasl_enabled; + char * sasl_auth_type; + char * sasl_server_fqdn; + char * sasl_local_ip_port; + char * sasl_remote_ip_port; + char * sasl_login; + char * sasl_auth_name; + char * sasl_password; + char * sasl_realm; + } pop3_sasl; + + char * pop3_local_address; + uint16_t pop3_local_port; +}; + +/* this is the type of POP3 authentication */ + +enum { + POP3_AUTH_TYPE_PLAIN, /* plain text authentication */ + POP3_AUTH_TYPE_APOP, /* APOP authentication */ + POP3_AUTH_TYPE_TRY_APOP, /* first, try APOP, if it fails, + try plain text */ + POP3_AUTH_TYPE_SASL_ANONYMOUS, /* SASL anonymous */ + POP3_AUTH_TYPE_SASL_CRAM_MD5, /* SASL CRAM MD5 */ + POP3_AUTH_TYPE_SASL_KERBEROS_V4, /* SASL KERBEROS V4 */ + POP3_AUTH_TYPE_SASL_PLAIN, /* SASL plain */ + POP3_AUTH_TYPE_SASL_SCRAM_MD5, /* SASL SCRAM MD5 */ + POP3_AUTH_TYPE_SASL_GSSAPI, /* SASL GSSAPI */ + POP3_AUTH_TYPE_SASL_DIGEST_MD5 /* SASL digest MD5 */ +}; + +#define POP3_SASL_AUTH_TYPE_APOP "X-LIBETPAN-APOP" +#define POP3_SASL_AUTH_TYPE_TRY_APOP "X-LIBETPAN-TRY-APOP" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/implementation/pop3/pop3storage.c b/Sources/libetpan/driver/implementation/pop3/pop3storage.c new file mode 100644 index 00000000..4e6de067 --- /dev/null +++ b/Sources/libetpan/driver/implementation/pop3/pop3storage.c @@ -0,0 +1,482 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3storage.c,v 1.22 2009/07/23 19:46:46 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "pop3storage.h" + +#include +#include + +#include "mail.h" +#include "mailstorage_tools.h" +#include "maildriver.h" + +/* pop3 storage */ + +#define POP3_DEFAULT_PORT 110 +#define POP3S_DEFAULT_PORT 995 + +static int pop3_mailstorage_connect(struct mailstorage * storage); +static int pop3_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result); +static void pop3_mailstorage_uninitialize(struct mailstorage * storage); + +static mailstorage_driver pop3_mailstorage_driver = { + /* sto_name */ "pop3", + /* sto_connect */ pop3_mailstorage_connect, + /* sto_get_folder_session */ pop3_mailstorage_get_folder_session, + /* sto_uninitialize */ pop3_mailstorage_uninitialize +}; + +LIBETPAN_EXPORT +int pop3_mailstorage_init(struct mailstorage * storage, + const char * pop3_servername, uint16_t pop3_port, + const char * pop3_command, + int pop3_connection_type, int pop3_auth_type, + const char * pop3_login, const char * pop3_password, + int pop3_cached, + const char * pop3_cache_directory, const char * pop3_flags_directory) +{ + char * sasl_auth_type; + + sasl_auth_type = NULL; + switch (pop3_auth_type) { + case POP3_AUTH_TYPE_APOP: + sasl_auth_type = POP3_SASL_AUTH_TYPE_APOP; + break; + case POP3_AUTH_TYPE_TRY_APOP: + sasl_auth_type = POP3_SASL_AUTH_TYPE_TRY_APOP; + break; + } + + return pop3_mailstorage_init_sasl(storage, + pop3_servername, pop3_port, + pop3_command, + pop3_connection_type, + sasl_auth_type, + NULL, + NULL, NULL, + pop3_login, pop3_login, + pop3_password, NULL, + pop3_cached, pop3_cache_directory, + pop3_flags_directory); +} + +LIBETPAN_EXPORT +int pop3_mailstorage_init_sasl(struct mailstorage * storage, + const char * pop3_servername, uint16_t pop3_port, + const char * pop3_command, + int pop3_connection_type, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm, + int pop3_cached, const char * pop3_cache_directory, + const char * pop3_flags_directory) +{ + return pop3_mailstorage_init_sasl_with_local_address(storage, + pop3_servername, pop3_port, + NULL, 0, + pop3_command, + pop3_connection_type, + auth_type, + server_fqdn, + local_ip_port, + remote_ip_port, + login, auth_name, + password, realm, + pop3_cached, pop3_cache_directory, + pop3_flags_directory); +} + +LIBETPAN_EXPORT +int pop3_mailstorage_init_sasl_with_local_address(struct mailstorage * storage, + const char * pop3_servername, uint16_t pop3_port, + const char * pop3_local_address, uint16_t pop3_local_port, + const char * pop3_command, + int pop3_connection_type, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm, + int pop3_cached, const char * pop3_cache_directory, + const char * pop3_flags_directory) +{ + struct pop3_mailstorage * pop3_storage; + + pop3_storage = malloc(sizeof(* pop3_storage)); + if (pop3_storage == NULL) + goto err; + + if (pop3_servername != NULL) { + pop3_storage->pop3_servername = strdup(pop3_servername); + if (pop3_storage->pop3_servername == NULL) + goto free; + } + else { + pop3_storage->pop3_servername = NULL; + } + + if (pop3_local_address != NULL) { + pop3_storage->pop3_local_address = strdup(pop3_local_address); + if (pop3_storage->pop3_local_address == NULL) + goto free_servername; + } + else { + pop3_storage->pop3_local_address = NULL; + } + + pop3_storage->pop3_local_port = pop3_local_port; + + pop3_storage->pop3_connection_type = pop3_connection_type; + + if (pop3_port == 0) { + switch (pop3_connection_type) { + case CONNECTION_TYPE_PLAIN: + case CONNECTION_TYPE_TRY_STARTTLS: + case CONNECTION_TYPE_STARTTLS: + case CONNECTION_TYPE_COMMAND: + case CONNECTION_TYPE_COMMAND_TRY_STARTTLS: + case CONNECTION_TYPE_COMMAND_STARTTLS: + pop3_port = POP3_DEFAULT_PORT; + break; + + case CONNECTION_TYPE_TLS: + case CONNECTION_TYPE_COMMAND_TLS: + pop3_port = POP3S_DEFAULT_PORT; + break; + + default: + pop3_port = POP3_DEFAULT_PORT; + break; + } + } + + pop3_storage->pop3_port = pop3_port; + + if (pop3_command != NULL) { + pop3_storage->pop3_command = strdup(pop3_command); + if (pop3_storage->pop3_command == NULL) + goto free_local_address; + } + else + pop3_storage->pop3_command = NULL; + + pop3_storage->pop3_auth_type = POP3_AUTH_TYPE_PLAIN; + + pop3_storage->pop3_sasl.sasl_enabled = (auth_type != NULL); + + if (auth_type != NULL) { + if (strcmp(auth_type, POP3_SASL_AUTH_TYPE_APOP) == 0) { + pop3_storage->pop3_auth_type = POP3_AUTH_TYPE_APOP; + auth_type = NULL; + } + else if (strcmp(auth_type, POP3_SASL_AUTH_TYPE_TRY_APOP) == 0) { + pop3_storage->pop3_auth_type = POP3_AUTH_TYPE_TRY_APOP; + auth_type = NULL; + } + } + + if (auth_type != NULL) { + pop3_storage->pop3_sasl.sasl_auth_type = strdup(auth_type); + if (pop3_storage->pop3_sasl.sasl_auth_type == NULL) + goto free_command; + } + else + pop3_storage->pop3_sasl.sasl_auth_type = NULL; + + if (server_fqdn != NULL) { + pop3_storage->pop3_sasl.sasl_server_fqdn = strdup(server_fqdn); + if (pop3_storage->pop3_sasl.sasl_server_fqdn == NULL) + goto free_auth_type; + } + else + pop3_storage->pop3_sasl.sasl_server_fqdn = NULL; + + if (local_ip_port != NULL) { + pop3_storage->pop3_sasl.sasl_local_ip_port = strdup(local_ip_port); + if (pop3_storage->pop3_sasl.sasl_local_ip_port == NULL) + goto free_server_fqdn; + } + else + pop3_storage->pop3_sasl.sasl_local_ip_port = NULL; + + if (remote_ip_port != NULL) { + pop3_storage->pop3_sasl.sasl_remote_ip_port = strdup(remote_ip_port); + if (pop3_storage->pop3_sasl.sasl_remote_ip_port == NULL) + goto free_local_ip_port; + } + else + pop3_storage->pop3_sasl.sasl_remote_ip_port = NULL; + + if (login != NULL) { + pop3_storage->pop3_sasl.sasl_login = strdup(login); + if (pop3_storage->pop3_sasl.sasl_login == NULL) + goto free_remote_ip_port; + } + else + pop3_storage->pop3_sasl.sasl_login = NULL; + + if (auth_name != NULL) { + pop3_storage->pop3_sasl.sasl_auth_name = strdup(auth_name); + if (pop3_storage->pop3_sasl.sasl_auth_name == NULL) + goto free_login; + } + else + pop3_storage->pop3_sasl.sasl_auth_name = NULL; + + if (password != NULL) { + pop3_storage->pop3_sasl.sasl_password = strdup(password); + if (pop3_storage->pop3_sasl.sasl_password == NULL) + goto free_auth_name; + } + else + pop3_storage->pop3_sasl.sasl_password = NULL; + + if (realm != NULL) { + pop3_storage->pop3_sasl.sasl_realm = strdup(realm); + if (pop3_storage->pop3_sasl.sasl_realm == NULL) + goto free_password; + } + else + pop3_storage->pop3_sasl.sasl_realm = NULL; + + pop3_storage->pop3_cached = pop3_cached; + + if (pop3_cached && (pop3_cache_directory != NULL) && + (pop3_flags_directory != NULL)) { + pop3_storage->pop3_cache_directory = strdup(pop3_cache_directory); + if (pop3_storage->pop3_cache_directory == NULL) + goto free_realm; + pop3_storage->pop3_flags_directory = strdup(pop3_flags_directory); + if (pop3_storage->pop3_flags_directory == NULL) + goto free_cache_directory; + } + else { + pop3_storage->pop3_cached = FALSE; + pop3_storage->pop3_cache_directory = NULL; + pop3_storage->pop3_flags_directory = NULL; + } + + pop3_storage->pop3_auth_type = pop3_storage->pop3_auth_type; + if (pop3_storage->pop3_sasl.sasl_login != NULL) { + pop3_storage->pop3_login = strdup(pop3_storage->pop3_sasl.sasl_login); + if (pop3_storage->pop3_login == NULL) + goto free_cache_directory; + } + else { + pop3_storage->pop3_login = NULL; + } + if (pop3_storage->pop3_sasl.sasl_password != NULL) { + pop3_storage->pop3_password = strdup(pop3_storage->pop3_sasl.sasl_password); + if (pop3_storage->pop3_password == NULL) + goto free_copy_login; + } + + storage->sto_data = pop3_storage; + storage->sto_driver = &pop3_mailstorage_driver; + + return MAIL_NO_ERROR; + + free_copy_login: + free(pop3_storage->pop3_login); + free_cache_directory: + free(pop3_storage->pop3_cache_directory); + free_realm: + free(pop3_storage->pop3_sasl.sasl_realm); + free_password: + free(pop3_storage->pop3_sasl.sasl_password); + free_auth_name: + free(pop3_storage->pop3_sasl.sasl_auth_name); + free_login: + free(pop3_storage->pop3_sasl.sasl_login); + free_remote_ip_port: + free(pop3_storage->pop3_sasl.sasl_remote_ip_port); + free_local_ip_port: + free(pop3_storage->pop3_sasl.sasl_local_ip_port); + free_server_fqdn: + free(pop3_storage->pop3_sasl.sasl_server_fqdn); + free_auth_type: + free(pop3_storage->pop3_sasl.sasl_auth_type); + free_command: + free(pop3_storage->pop3_command); + free_local_address: + free(pop3_storage->pop3_local_address); + free_servername: + free(pop3_storage->pop3_servername); + free: + free(pop3_storage); + err: + return MAIL_ERROR_MEMORY; +} + +static void pop3_mailstorage_uninitialize(struct mailstorage * storage) +{ + struct pop3_mailstorage * pop3_storage; + + pop3_storage = storage->sto_data; + + free(pop3_storage->pop3_password); + free(pop3_storage->pop3_login); + + free(pop3_storage->pop3_flags_directory); + free(pop3_storage->pop3_cache_directory); + + free(pop3_storage->pop3_sasl.sasl_realm); + free(pop3_storage->pop3_sasl.sasl_password); + free(pop3_storage->pop3_sasl.sasl_auth_name); + free(pop3_storage->pop3_sasl.sasl_login); + free(pop3_storage->pop3_sasl.sasl_remote_ip_port); + free(pop3_storage->pop3_sasl.sasl_local_ip_port); + free(pop3_storage->pop3_sasl.sasl_server_fqdn); + free(pop3_storage->pop3_sasl.sasl_auth_type); + + free(pop3_storage->pop3_command); + free(pop3_storage->pop3_local_address); + free(pop3_storage->pop3_servername); + free(pop3_storage); + + storage->sto_data = NULL; +} + +static int pop3_mailstorage_connect(struct mailstorage * storage) +{ + struct pop3_mailstorage * pop3_storage; + mailsession_driver * driver; + int r; + int res; + mailsession * session; + int auth_type; + + pop3_storage = storage->sto_data; + + if (pop3_storage->pop3_cached) + driver = pop3_cached_session_driver; + else + driver = pop3_session_driver; + + r = mailstorage_generic_connect_with_local_address(driver, + pop3_storage->pop3_servername, + pop3_storage->pop3_port, + pop3_storage->pop3_local_address, + pop3_storage->pop3_local_port, + pop3_storage->pop3_command, + pop3_storage->pop3_connection_type, + POP3DRIVER_CACHED_SET_CACHE_DIRECTORY, + pop3_storage->pop3_cache_directory, + POP3DRIVER_CACHED_SET_FLAGS_DIRECTORY, + pop3_storage->pop3_flags_directory, + &session); + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto err; + } + + auth_type = -1; + switch (pop3_storage->pop3_auth_type) { + case POP3_AUTH_TYPE_PLAIN: + auth_type = POP3DRIVER_AUTH_TYPE_PLAIN; + break; + case POP3_AUTH_TYPE_APOP: + auth_type = POP3DRIVER_AUTH_TYPE_APOP; + break; + case POP3_AUTH_TYPE_TRY_APOP: + auth_type = POP3DRIVER_AUTH_TYPE_TRY_APOP; + break; + } + + if (auth_type != -1) { + mailsession_parameters(session, POP3DRIVER_SET_AUTH_TYPE, &auth_type); + } + + r = mailstorage_generic_auth_sasl(session, r, + pop3_storage->pop3_sasl.sasl_auth_type, + pop3_storage->pop3_sasl.sasl_server_fqdn, + pop3_storage->pop3_sasl.sasl_local_ip_port, + pop3_storage->pop3_sasl.sasl_remote_ip_port, + pop3_storage->pop3_sasl.sasl_login, + pop3_storage->pop3_sasl.sasl_auth_name, + pop3_storage->pop3_sasl.sasl_password, + pop3_storage->pop3_sasl.sasl_realm); + if (r != MAIL_NO_ERROR) { + if (pop3_storage->pop3_auth_type == POP3_AUTH_TYPE_TRY_APOP) { + /* try in clear authentication */ + mailsession_free(session); + + pop3_storage->pop3_auth_type = POP3_AUTH_TYPE_PLAIN; + r = mailstorage_connect(storage); + pop3_storage->pop3_auth_type = POP3_AUTH_TYPE_TRY_APOP; + if (r != MAIL_NO_ERROR) { + res = r; + return res; + } + + return MAIL_NO_ERROR; + } + + res = r; + goto free; + } + + storage->sto_session = session; + + return MAIL_NO_ERROR; + + free: + mailsession_free(session); + err: + return res; +} + +static int pop3_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result) +{ + * result = storage->sto_session; + + return MAIL_NO_ERROR; +} + diff --git a/Sources/libetpan/driver/implementation/pop3/pop3storage.h b/Sources/libetpan/driver/implementation/pop3/pop3storage.h new file mode 100644 index 00000000..8145c237 --- /dev/null +++ b/Sources/libetpan/driver/implementation/pop3/pop3storage.h @@ -0,0 +1,125 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3storage.h,v 1.12 2007/06/30 12:58:21 hoa Exp $ + */ + +#ifndef POP3STORAGE_H + +#define POP3STORAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +/* + pop3_mailstorage_init is the constructor for a POP3 storage + + @param storage this is the storage to initialize. + + @param servername this is the name of the POP3 server + + @param port is the port to connect to, on the server. + you give 0 to use the default port. + + @param command the command used to connect to the server instead of + allowing normal TCP connections to be used. + + @param connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS, + CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS, + CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS, + CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,. + + @param auth_type is the authenticate mechanism to use. + The value can be POP3_AUTH_TYPE_PLAIN, POP3_AUTH_TYPE_APOP + or POP3_AUTH_TYPE_TRY_APOP. Other values are not yet implemented. + + @param login is the login of the POP3 account. + + @param password is the password of the POP3 account. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache + + @param flags_directory is the location of the flags +*/ + +LIBETPAN_EXPORT +int pop3_mailstorage_init(struct mailstorage * storage, + const char * pop3_servername, uint16_t pop3_port, + const char * pop3_command, + int pop3_connection_type, int pop3_auth_type, + const char * pop3_login, const char * pop3_password, + int pop3_cached, const char * pop3_cache_directory, + const char * pop3_flags_directory); + +LIBETPAN_EXPORT +int pop3_mailstorage_init_sasl(struct mailstorage * storage, + const char * pop3_servername, uint16_t pop3_port, + const char * pop3_command, + int pop3_connection_type, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm, + int pop3_cached, const char * pop3_cache_directory, + const char * pop3_flags_directory); + +LIBETPAN_EXPORT +int pop3_mailstorage_init_sasl_with_local_address(struct mailstorage * storage, + const char * pop3_servername, uint16_t pop3_port, + const char * imap_local_address, uint16_t imap_local_port, + const char * pop3_command, + int pop3_connection_type, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm, + int pop3_cached, const char * pop3_cache_directory, + const char * pop3_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/interface/Makefile.am b/Sources/libetpan/driver/interface/Makefile.am new file mode 100644 index 00000000..cfcdf743 --- /dev/null +++ b/Sources/libetpan/driver/interface/Makefile.am @@ -0,0 +1,57 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +etpaninclude_HEADERS = \ + maildriver.h maildriver_types.h maildriver_types_helper.h \ + maildriver_errors.h \ + mailmessage.h mailmessage_types.h \ + mailstorage.h \ + mailstorage_types.h \ + mailfolder.h + +AM_CPPFLAGS = -I$(top_builddir)/include \ + -I$(top_srcdir)/src/low-level/imf \ + -I$(top_srcdir)/src/low-level/mime \ + -I$(top_srcdir)/src/data-types \ + -I$(top_srcdir)/src/interface/tools + +noinst_LTLIBRARIES = libinterface.la + +libinterface_la_SOURCES = \ + maildriver.c maildriver_types.c \ + maildriver_tools.h maildriver_tools.c \ + mailmessage.c \ + mailmessage_tools.h mailmessage_tools.c \ + mailmessage_types.c \ + maildriver_types_helper.c \ + mailstorage.c \ + mailstorage_tools.h mailstorage_tools.c \ + mailfolder.c diff --git a/Sources/libetpan/driver/interface/maildriver.c b/Sources/libetpan/driver/interface/maildriver.c new file mode 100644 index 00000000..9bec5278 --- /dev/null +++ b/Sources/libetpan/driver/interface/maildriver.c @@ -0,0 +1,444 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildriver.c,v 1.28 2006/06/07 15:10:01 smarinier Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "maildriver.h" +#include +#include +#include + +/* *********************************************************************** */ +/* mail session */ + +LIBETPAN_EXPORT +mailsession * mailsession_new(mailsession_driver * sess_driver) +{ + mailsession * session; + int r; + + session = malloc(sizeof(* session)); + if (session == NULL) + goto err; + + session->sess_data = NULL; + + if (sess_driver->sess_initialize != NULL) { + r = sess_driver->sess_initialize(session); + if (r != MAIL_NO_ERROR) + goto free; + } + + session->sess_driver = sess_driver; + + return session; + + free: + free(session); + err: + return NULL; +} + +LIBETPAN_EXPORT +void mailsession_free(mailsession * session) +{ + if (session->sess_driver->sess_uninitialize != NULL) + session->sess_driver->sess_uninitialize(session); + free(session); +} + +LIBETPAN_EXPORT +int mailsession_parameters(mailsession * session, + int id, void * value) +{ + if (session->sess_driver->sess_parameters == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_parameters(session, id, value); +} + +LIBETPAN_EXPORT +int mailsession_connect_stream(mailsession * session, mailstream * s) +{ + if (session->sess_driver->sess_connect_stream == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_connect_stream(session, s); +} + +LIBETPAN_EXPORT +int mailsession_connect_path(mailsession * session, const char * path) +{ + if (session->sess_driver->sess_connect_path == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_connect_path(session, path); +} + +LIBETPAN_EXPORT +int mailsession_starttls(mailsession * session) +{ + if (session->sess_driver->sess_starttls == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_starttls(session); +} + +LIBETPAN_EXPORT +int mailsession_login(mailsession * session, + const char * userid, const char * password) +{ + if (session->sess_driver->sess_login == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_login(session, userid, password); +} + +LIBETPAN_EXPORT +int mailsession_logout(mailsession * session) +{ + if (session->sess_driver->sess_logout == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_logout(session); +} + +LIBETPAN_EXPORT +int mailsession_noop(mailsession * session) +{ + if (session->sess_driver->sess_noop == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_noop(session); +} + +/* folders operations */ + +LIBETPAN_EXPORT +int mailsession_build_folder_name(mailsession * session, const char * mb, + const char * name, char ** result) +{ + if (session->sess_driver->sess_build_folder_name == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_build_folder_name(session, + mb, name, result); +} + +LIBETPAN_EXPORT +int mailsession_create_folder(mailsession * session, const char * mb) +{ + if (session->sess_driver->sess_create_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_create_folder(session, mb); +} + +LIBETPAN_EXPORT +int mailsession_delete_folder(mailsession * session, const char * mb) +{ + if (session->sess_driver->sess_delete_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_delete_folder(session, mb); +} + +LIBETPAN_EXPORT +int mailsession_rename_folder(mailsession * session, + const char * mb, const char * new_name) +{ + if (session->sess_driver->sess_rename_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_rename_folder(session, mb, new_name); +} + +LIBETPAN_EXPORT +int mailsession_check_folder(mailsession * session) +{ + if (session->sess_driver->sess_check_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_check_folder(session); +} + +LIBETPAN_EXPORT +int mailsession_examine_folder(mailsession * session, const char * mb) +{ + if (session->sess_driver->sess_examine_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_examine_folder(session, mb); +} + +LIBETPAN_EXPORT +int mailsession_select_folder(mailsession * session, const char * mb) +{ + if (session->sess_driver->sess_select_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_select_folder(session, mb); +} + +LIBETPAN_EXPORT +int mailsession_expunge_folder(mailsession * session) +{ + if (session->sess_driver->sess_expunge_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_expunge_folder(session); +} + +LIBETPAN_EXPORT +int mailsession_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + if (session->sess_driver->sess_status_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_status_folder(session, mb, + result_messages, result_recent, result_unseen); +} + +LIBETPAN_EXPORT +int mailsession_messages_number(mailsession * session, const char * mb, + uint32_t * result) +{ + if (session->sess_driver->sess_messages_number == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_messages_number(session, mb, result); +} + +LIBETPAN_EXPORT +int mailsession_recent_number(mailsession * session, const char * mb, + uint32_t * result) +{ + if (session->sess_driver->sess_recent_number == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_recent_number(session, mb, result); +} + +LIBETPAN_EXPORT +int mailsession_unseen_number(mailsession * session, const char * mb, + uint32_t * result) +{ + if (session->sess_driver->sess_unseen_number == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_unseen_number(session, mb, result); +} + +LIBETPAN_EXPORT +int mailsession_list_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + if (session->sess_driver->sess_list_folders == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_list_folders(session, mb, result); +} + +LIBETPAN_EXPORT +int mailsession_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + if (session->sess_driver->sess_lsub_folders == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_lsub_folders(session, mb, result); +} + +LIBETPAN_EXPORT +int mailsession_subscribe_folder(mailsession * session, const char * mb) +{ + if (session->sess_driver->sess_subscribe_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_subscribe_folder(session, mb); +} + +LIBETPAN_EXPORT +int mailsession_unsubscribe_folder(mailsession * session, const char * mb) +{ + if (session->sess_driver->sess_unsubscribe_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_unsubscribe_folder(session, mb); +} + +/* message */ + +LIBETPAN_EXPORT +int mailsession_append_message(mailsession * session, + const char * message, size_t size) +{ + if (session->sess_driver->sess_append_message == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_append_message(session, message, size); +} + +LIBETPAN_EXPORT +int mailsession_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags) +{ + if (session->sess_driver->sess_append_message_flags == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_append_message_flags(session, + message, size, flags); +} + +LIBETPAN_EXPORT +int mailsession_copy_message(mailsession * session, + uint32_t num, const char * mb) +{ + if (session->sess_driver->sess_copy_message == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_copy_message(session, num, mb); +} + +LIBETPAN_EXPORT +int mailsession_move_message(mailsession * session, + uint32_t num, const char * mb) +{ + if (session->sess_driver->sess_move_message == NULL) { + int r; + + if ((session->sess_driver->sess_copy_message == NULL) && + (session->sess_driver->sess_remove_message == NULL)) + return MAIL_ERROR_NOT_IMPLEMENTED; + + r = mailsession_copy_message(session, num, mb); + if (r != MAIL_NO_ERROR) + return r; + + r = mailsession_remove_message(session, num); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + } + + return session->sess_driver->sess_move_message(session, num, mb); +} + +LIBETPAN_EXPORT +int mailsession_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + if (session->sess_driver->sess_get_envelopes_list == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_get_envelopes_list(session, env_list); +} + +LIBETPAN_EXPORT +int mailsession_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + if (session->sess_driver->sess_get_messages_list == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_get_messages_list(session, result); +} + +LIBETPAN_EXPORT +int mailsession_remove_message(mailsession * session, uint32_t num) +{ + if (session->sess_driver->sess_remove_message == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_remove_message(session, num); +} + +#if 0 +LIBETPAN_EXPORT +int mailsession_search_messages(mailsession * session, const char * charset, + struct mail_search_key * key, + struct mail_search_result ** result) +{ + if (session->sess_driver->sess_search_messages == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_search_messages(session, + charset, key, result); +} +#endif + +LIBETPAN_EXPORT +int mailsession_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + if (session->sess_driver->sess_get_message == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_get_message(session, num, result); +} + +LIBETPAN_EXPORT +int mailsession_get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result) +{ + if (session->sess_driver->sess_get_message_by_uid == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_get_message_by_uid(session, uid, result); +} + +LIBETPAN_EXPORT +int mailsession_login_sasl(mailsession * session, const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm) +{ + if (session->sess_driver->sess_login_sasl == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_login_sasl(session, auth_type, + server_fqdn, + local_ip_port, + remote_ip_port, + login, auth_name, + password, realm); +} diff --git a/Sources/libetpan/driver/interface/maildriver.h b/Sources/libetpan/driver/interface/maildriver.h new file mode 100644 index 00000000..12dd2c52 --- /dev/null +++ b/Sources/libetpan/driver/interface/maildriver.h @@ -0,0 +1,607 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildriver.h,v 1.34 2006/06/07 15:10:01 smarinier Exp $ + */ + +#ifndef MAILDRIVER_H + +#define MAILDRIVER_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* mailsession */ + +/* + mailsession_new creates a new session, using the given driver + + @return the created session is returned +*/ + +LIBETPAN_EXPORT +mailsession * mailsession_new(mailsession_driver * sess_driver); + +/* + mailsession_free release the memory used by the session +*/ + +LIBETPAN_EXPORT +void mailsession_free(mailsession * session); + +/* + mailsession_parameters is used to make calls specific to the driver + + @param id is the command to send to the driver, + usually, commands can be found in the header of the driver + + @param value is the parameter of the specific call + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_parameters(mailsession * session, + int id, void * value); + +/* + There are drivers of two kinds : stream drivers (driver that connects + to servers through TCP or other means of connection) and file drivers + (driver that are based on filesystem) + + The following function can only be used by stream drivers. + mailsession_connect_stream connects a stream to the session + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_connect_stream(mailsession * session, mailstream * s); + +/* + The following function can only be used by file drivers. + mailsession_connect_path selects the main path of the session + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_connect_path(mailsession * session, const char * path); + +/* + NOTE: works only on stream drivers + + mailsession_starttls switches the current connection to TLS (secure layer) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_starttls(mailsession * session); + +/* + mailsession_login notifies the login and the password to authenticate + to the session + + @param userid the given string is only needed at this function call + (it will be duplicated if necessary) + @param password the given string is only needed at this function call + (it will be duplicated if necessary) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_login(mailsession * session, + const char * userid, const char * password); + +/* + NOTE: this function doesn't often work on filsystem drivers + + mailsession_logout deconnects the session and closes the stream. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_logout(mailsession * session); + +/* + mailsession_noop does no operation on the session, but it can be + used to poll for the status of the connection. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_noop(mailsession * session); + +/* + NOTE: driver's specific should be used + + mailsession_build_folder_name will return an allocated string with + that contains the complete path of the folder to create + + @param session the sesion + @param mb is the parent mailbox + @param name is the name of the folder to create + @param result the complete path of the folder to create will be + stored in (* result), this name have to be freed with free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_build_folder_name(mailsession * session, const char * mb, + const char * name, char ** result); + +/* + NOTE: driver's specific should be used + + mailsession_create_folder creates the folder that corresponds to the + given name + + @param session the session + @param mb is the name of the mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_create_folder(mailsession * session, const char * mb); + + +/* + NOTE: driver's specific should be used + + mailsession_delete_folder deletes the folder that corresponds to the + given name + + @param session the session + @param mb is the name of the mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_delete_folder(mailsession * session, const char * mb); + + +/* + mailsession_rename_folder changes the name of the folder + + @param session the session + @param mb is the name of the mailbox whose name has to be changed + @param new_name is the destination name (the parent + of the new folder folder can be other) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_rename_folder(mailsession * session, + const char * mb, const char * new_name); + +/* + mailsession_check_folder makes a checkpoint of the session + + @param session the session + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_check_folder(mailsession * session); + + +/* + NOTE: this function is not implemented in most drivers + + mailsession_examine_folder selects a mailbox as readonly + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_examine_folder(mailsession * session, const char * mb); + + +/* + mailsession_select_folder selects a mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_select_folder(mailsession * session, const char * mb); + + +/* + mailsession_expunge_folder deletes all messages marked \Deleted + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_expunge_folder(mailsession * session); + + +/* + mailsession_status_folder queries the status of the folder + (number of messages, number of recent messages, number of unseen messages) + + @param session the session + @param mb mailbox to query + @param result_messages the number of messages is stored + in (* result_messages) + @param result_recent the number of messages is stored + in (* result_recent) + @param result_unseen the number of messages is stored + in (* result_unseen) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + + +/* + mailsession_messages_number queries the number of messages in the folder + + @param session the session + @param mb mailbox to query + @param result the number of messages is stored in (* result) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_messages_number(mailsession * session, const char * mb, + uint32_t * result); + +/* + mailsession_recent_number queries the number of recent messages in the folder + + @param session the session + @param mb mailbox to query + @param result the number of recent messages is stored in (* result) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_recent_number(mailsession * session, + const char * mb, uint32_t * result); + +/* + mailsession_unseen_number queries the number of unseen messages in the folder + + @param session the session + @param mb mailbox to query + @param result the number of unseen messages is stored in (* result) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_unseen_number(mailsession * session, const char * mb, + uint32_t * result); + +/* + NOTE: driver's specific should be used + + mailsession_list_folders returns the list of all sub-mailboxes + of the given mailbox + + @param session the session + @param mb the mailbox + @param result list of mailboxes if stored in (* result), + this structure have to be freed with mail_list_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_list_folders(mailsession * session, const char * mb, + struct mail_list ** result); + +/* + NOTE: driver's specific should be used + + mailsession_lsub_folders returns the list of subscribed + sub-mailboxes of the given mailbox + + @param session the session + @param mb the mailbox + @param result list of mailboxes if stored in (* result), + this structure have to be freed with mail_list_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result); + +/* + NOTE: driver's specific should be used + + mailsession_subscribe_folder subscribes to the given mailbox + + @param session the session + @param mb the mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_subscribe_folder(mailsession * session, const char * mb); + +/* + NOTE: driver's specific should be used + + mailsession_unsubscribe_folder unsubscribes to the given mailbox + + @param session the session + @param mb the mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_unsubscribe_folder(mailsession * session, const char * mb); + +/* + mailsession_append_message adds a RFC 2822 message to the current + given mailbox + + @param session the session + @param message is a string that contains the RFC 2822 message + @param size this is the size of the message + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_append_message(mailsession * session, + const char * message, size_t size); + +LIBETPAN_EXPORT +int mailsession_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); + +/* + NOTE: some drivers does not implement this + + mailsession_copy_message copies a message whose number is given to + a given mailbox. The mailbox must be accessible from the same session. + + @param session the session + @param num the message number + @param mb the destination mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_copy_message(mailsession * session, + uint32_t num, const char * mb); + +/* + NOTE: some drivers does not implement this + + mailsession_move_message copies a message whose number is given to + a given mailbox. The mailbox must be accessible from the same session. + + @param session the session + @param num the message number + @param mb the destination mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_move_message(mailsession * session, + uint32_t num, const char * mb); + +/* + mailsession_get_messages_list returns the list of message numbers + of the current mailbox. + + @param session the session + @param result the list of message numbers will be stored in (* result), + this structure have to be freed with mailmessage_list_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +/* + mailsession_get_envelopes_list fills the parsed fields in the + mailmessage structures of the mailmessage_list. + + @param session the session + @param result this is the list of mailmessage structures + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_get_envelopes_list(mailsession * session, + struct mailmessage_list * result); + +/* + NOTE: some drivers does not implement this + + mailsession_remove_message removes the given message from the mailbox. + The message is permanently deleted. + + @param session the session + @param num is the message number + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_remove_message(mailsession * session, uint32_t num); + + +/* + NOTE: this function is not implemented in most drivers + + mailsession_search_message returns a list of message numbers that + corresponds to the given criteria. + + @param session the session + @param charset is the charset to use (it can be NULL) + @param key is the list of criteria + @param result the search result is stored in (* result), + this structure have to be freed with mail_search_result_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +#if 0 +LIBETPAN_EXPORT +int mailsession_search_messages(mailsession * session, const char * charset, + struct mail_search_key * key, + struct mail_search_result ** result); +#endif + +/* + mailsession_get_message returns a mailmessage structure that corresponds + to the given message number. + * WARNING * mailsession_get_message_by_uid() should be used instead. + + @param session the session + @param num the message number + @param result the allocated mailmessage structure will be stored + in (* result), this structure have to be freed with mailmessage_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +/* + mailsession_get_message_by_uid returns a mailmessage structure + that corresponds to the given message unique identifier. + This is currently implemented only for cached drivers. + * WARNING * That will deprecates the use of mailsession_get_message() + + @param session the session + @param uid the message unique identifier + @param result the allocated mailmessage structure will be stored + in (* result), this structure have to be freed with mailmessage_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result); + + +/* + mailsession_login notifies the SASL authentication information + to the session + + @param auth_type type of SASL authentication + @param server_fqdn server full qualified domain name + @param local_ip_port local IP:port (client) + @param remote_ip_port remote IP:port (server) + @param login login + @param auth_name authentication name + @param password password (or token for OAuth2 login) + @param realm realm + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_login_sasl(mailsession * session, const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/interface/maildriver_errors.h b/Sources/libetpan/driver/interface/maildriver_errors.h new file mode 100644 index 00000000..b131a72e --- /dev/null +++ b/Sources/libetpan/driver/interface/maildriver_errors.h @@ -0,0 +1,103 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildriver_errors.h,v 1.9 2006/12/13 18:31:32 hoa Exp $ + */ + +#ifndef MAILDRIVER_ERRORS_H + +#define MAILDRIVER_ERRORS_H + +enum { + MAIL_NO_ERROR = 0, + MAIL_NO_ERROR_AUTHENTICATED, + MAIL_NO_ERROR_NON_AUTHENTICATED, + MAIL_ERROR_NOT_IMPLEMENTED, + MAIL_ERROR_UNKNOWN, + MAIL_ERROR_CONNECT, + MAIL_ERROR_BAD_STATE, + MAIL_ERROR_FILE, + MAIL_ERROR_STREAM, + MAIL_ERROR_LOGIN, + MAIL_ERROR_CREATE, /* 10 */ + MAIL_ERROR_DELETE, + MAIL_ERROR_LOGOUT, + MAIL_ERROR_NOOP, + MAIL_ERROR_RENAME, + MAIL_ERROR_CHECK, + MAIL_ERROR_EXAMINE, + MAIL_ERROR_SELECT, + MAIL_ERROR_MEMORY, + MAIL_ERROR_STATUS, + MAIL_ERROR_SUBSCRIBE, /* 20 */ + MAIL_ERROR_UNSUBSCRIBE, + MAIL_ERROR_LIST, + MAIL_ERROR_LSUB, + MAIL_ERROR_APPEND, + MAIL_ERROR_COPY, + MAIL_ERROR_FETCH, + MAIL_ERROR_STORE, + MAIL_ERROR_SEARCH, + MAIL_ERROR_DISKSPACE, + MAIL_ERROR_MSG_NOT_FOUND, /* 30 */ + MAIL_ERROR_PARSE, + MAIL_ERROR_INVAL, + MAIL_ERROR_PART_NOT_FOUND, + MAIL_ERROR_REMOVE, + MAIL_ERROR_FOLDER_NOT_FOUND, + MAIL_ERROR_MOVE, + MAIL_ERROR_STARTTLS, + MAIL_ERROR_CACHE_MISS, + MAIL_ERROR_NO_TLS, + MAIL_ERROR_EXPUNGE, /* 40 */ + /* misc errors */ + MAIL_ERROR_MISC, + MAIL_ERROR_PROTOCOL, + MAIL_ERROR_CAPABILITY, + MAIL_ERROR_CLOSE, + MAIL_ERROR_FATAL, + MAIL_ERROR_READONLY, + MAIL_ERROR_NO_APOP, + MAIL_ERROR_COMMAND_NOT_SUPPORTED, + MAIL_ERROR_NO_PERMISSION, + MAIL_ERROR_PROGRAM_ERROR, /* 50 */ + MAIL_ERROR_SUBJECT_NOT_FOUND, + MAIL_ERROR_CHAR_ENCODING_FAILED, + MAIL_ERROR_SEND, + MAIL_ERROR_COMMAND, + MAIL_ERROR_SYSTEM, + MAIL_ERROR_UNABLE, + MAIL_ERROR_FOLDER, + MAIL_ERROR_SSL +}; + +#endif diff --git a/Sources/libetpan/driver/interface/maildriver_tools.c b/Sources/libetpan/driver/interface/maildriver_tools.c new file mode 100644 index 00000000..75424f5a --- /dev/null +++ b/Sources/libetpan/driver/interface/maildriver_tools.c @@ -0,0 +1,797 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildriver_tools.c,v 1.36 2008/02/20 22:15:51 hoa Exp $ + */ +#define HAVE_CONFIG_H 1 + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "maildriver_tools.h" + +#include "libetpan-config.h" + +#include +#include +#include +#ifdef WIN32 +# include "win_etpan.h" +#else +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif +#include "maildriver.h" +#include "mailmessage.h" +#include "mailstream.h" +#include "mailmime.h" +#include "mail_cache_db.h" + +/* ********************************************************************* */ +/* tools */ + + +int +maildriver_generic_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + unsigned i; + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + struct mailimf_fields * fields; + + r = mailmessage_fetch_envelope(msg, &fields); + if (r != MAIL_NO_ERROR) { + /* do nothing */ + } + else { + msg->msg_fields = fields; + } + mailmessage_flush(msg); + } + } + + return MAIL_NO_ERROR; +} + + +#if 0 +static int is_search_header_only(struct mail_search_key * key) +{ + clistiter * cur; + int result; + + switch (key->type) { + case MAIL_SEARCH_KEY_ANSWERED: + case MAIL_SEARCH_KEY_BCC: + case MAIL_SEARCH_KEY_BEFORE: + case MAIL_SEARCH_KEY_CC: + case MAIL_SEARCH_KEY_DELETED: + case MAIL_SEARCH_KEY_FLAGGED: + case MAIL_SEARCH_KEY_FROM: + case MAIL_SEARCH_KEY_NEW: + case MAIL_SEARCH_KEY_OLD: + case MAIL_SEARCH_KEY_ON: + case MAIL_SEARCH_KEY_RECENT: + case MAIL_SEARCH_KEY_SEEN: + case MAIL_SEARCH_KEY_SINCE: + case MAIL_SEARCH_KEY_SUBJECT: + case MAIL_SEARCH_KEY_TO: + case MAIL_SEARCH_KEY_UNANSWERED: + case MAIL_SEARCH_KEY_UNDELETED: + case MAIL_SEARCH_KEY_UNFLAGGED: + case MAIL_SEARCH_KEY_UNSEEN: + case MAIL_SEARCH_KEY_HEADER: + case MAIL_SEARCH_KEY_LARGER: + case MAIL_SEARCH_KEY_NOT: + case MAIL_SEARCH_KEY_SMALLER: + case MAIL_SEARCH_KEY_ALL: + return TRUE; + + case MAIL_SEARCH_KEY_BODY: + case MAIL_SEARCH_KEY_TEXT: + return FALSE; + + case MAIL_SEARCH_KEY_OR: + return (is_search_header_only(key->or1) && + is_search_header_only(key->or2)); + + case MAIL_SEARCH_KEY_MULTIPLE: + result = TRUE; + for (cur = clist_begin(key->multiple) ; cur != NULL ; + cur = clist_next(cur)) + result = result && is_search_header_only(clist_content(cur)); + return result; + + default: + return TRUE; + } +} + +static int match_header(struct mailimf_fields * fields, + char * name, char * value) +{ + clistiter * cur; + + for(cur = clist_begin(fields->list) ; cur != NULL ; + cur = clist_content(cur)) { + struct mailimf_field * field; + struct mailimf_optional_field * opt_field; + + field = clist_content(cur); + opt_field = field->optional_field; + if ((char) toupper((unsigned char) opt_field->name[0]) == + (char) toupper((unsigned char) name[0])) { + if (strcasecmp(opt_field->name, name) == 0) + if (strstr(opt_field->value, value) != NULL) + return TRUE; + } + } + return FALSE; +} + +static int comp_date(struct mailimf_fields * fields, + struct mailimf_date_time * ref_date) +{ + clistiter * cur; + struct mailimf_date_time * date; + int r; + + date = NULL; + for(cur = clist_begin(fields->list) ; cur != NULL ; + cur = clist_content(cur)) { + struct mailimf_field * field; + struct mailimf_optional_field * opt_field; + + field = clist_content(cur); + opt_field = field->optional_field; + if ((char) toupper((unsigned char) opt_field->name[0]) == 'D') { + if (strcasecmp(opt_field->name, "Date") == 0) { + size_t cur_token; + + cur_token = 0; + r = mailimf_date_time_parse(opt_field->value, strlen(opt_field->value), + &cur_token, &date); + if (r == MAILIMF_NO_ERROR) + break; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + break; + } + } + } + + if (date == NULL) + return 0; + + return mailimf_date_time_comp(date, ref_date); +} + +static int match_messages(char * message, + size_t size, + struct mailimf_fields * fields, + int32_t flags, + char * charset, + struct mail_search_key * key) +{ + clistiter * cur; + size_t length; + size_t cur_token; + int r; + + switch (key->type) { + + /* flags */ + case MAIL_SEARCH_KEY_ANSWERED: + return ((flags & MAIL_FLAG_ANSWERED) != 0); + + case MAIL_SEARCH_KEY_FLAGGED: + return ((flags & MAIL_FLAG_FLAGGED) != 0); + + case MAIL_SEARCH_KEY_DELETED: + return ((flags & MAIL_FLAG_DELETED) != 0); + + case MAIL_SEARCH_KEY_RECENT: + return ((flags & MAIL_FLAG_NEW) != 0) && + ((flags & MAIL_FLAG_SEEN) == 0); + + case MAIL_SEARCH_KEY_SEEN: + return ((flags & MAIL_FLAG_SEEN) != 0); + + case MAIL_SEARCH_KEY_NEW: + return ((flags & MAIL_FLAG_NEW) != 0); + + case MAIL_SEARCH_KEY_OLD: + return ((flags & MAIL_FLAG_NEW) == 0); + + case MAIL_SEARCH_KEY_UNANSWERED: + return ((flags & MAIL_FLAG_ANSWERED) == 0); + + case MAIL_SEARCH_KEY_UNDELETED: + return ((flags & MAIL_FLAG_DELETED) == 0); + + case MAIL_SEARCH_KEY_UNFLAGGED: + return ((flags & MAIL_FLAG_FLAGGED) == 0); + + case MAIL_SEARCH_KEY_UNSEEN: + return ((flags & MAIL_FLAG_SEEN) == 0); + + /* headers */ + case MAIL_SEARCH_KEY_BCC: + return match_header(fields, "Bcc", key->bcc); + + case MAIL_SEARCH_KEY_CC: + return match_header(fields, "Cc", key->cc); + + case MAIL_SEARCH_KEY_FROM: + return match_header(fields, "From", key->from); + + case MAIL_SEARCH_KEY_SUBJECT: + return match_header(fields, "Subject", key->subject); + + case MAIL_SEARCH_KEY_TO: + return match_header(fields, "To", key->to); + + case MAIL_SEARCH_KEY_HEADER: + return match_header(fields, key->header_name, key->header_value); + + /* date */ + case MAIL_SEARCH_KEY_BEFORE: + return (comp_date(fields, key->before) <= 0); + + case MAIL_SEARCH_KEY_ON: + return (comp_date(fields, key->before) == 0); + + case MAIL_SEARCH_KEY_SINCE: + return (comp_date(fields, key->before) >= 0); + + /* boolean */ + case MAIL_SEARCH_KEY_NOT: + return (!match_messages(message, size, fields, flags, charset, key->not)); + case MAIL_SEARCH_KEY_OR: + return (match_messages(message, size, fields, flags, charset, key->or1) || + match_messages(message, size, fields, flags, charset, key->or2)); + + case MAIL_SEARCH_KEY_MULTIPLE: + for(cur = clist_begin(key->multiple) ; cur != NULL ; + cur = clist_next(cur)) { + if (!match_messages(message, size, fields, flags, charset, + clist_content(cur))) + return FALSE; + } + + return TRUE; + + /* size */ + case MAIL_SEARCH_KEY_SMALLER: + return (size <= key->smaller); + + case MAIL_SEARCH_KEY_LARGER: + return (size >= key->larger); + + case MAIL_SEARCH_KEY_BODY: + length = strlen(message); + + cur_token = 0; + while (1) { + r = mailimf_ignore_field_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + + return (strstr(message + cur_token, key->body) != NULL); + + case MAIL_SEARCH_KEY_TEXT: + return (strstr(message, key->body) != NULL); + + case MAIL_SEARCH_KEY_ALL: + default: + return TRUE; + } +} + +int maildriver_generic_search_messages(mailsession * session, char * charset, + struct mail_search_key * key, + struct mail_search_result ** result) +{ + int header; + clist * list; + struct mail_search_result * search_result; + int r; + struct mailmessage_list * env_list; + int res; + unsigned int i; + + header = is_search_header_only(key); + + r = mailsession_get_messages_list(session, &env_list); + if (r != MAIL_NO_ERROR) + return r; + + list = NULL; + for(i = 0 ; i < carray_count(env_list->tab) ; i ++) { + char * message; + size_t length; + struct mail_info * info; + uint32_t flags; + struct mailimf_fields * fields; + size_t cur_token; + + info = carray_get(env_list->tab, i); + + if (!header) { + r = mailsession_fetch_message(session, info->indx, &message, &length); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + cur_token = 0; + r = mailimf_optional_fields_parse(message, length, + &cur_token, &fields); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_PARSE; + goto free_list; + } + } + else { + char * msg_header; + int r; + size_t cur_token; + size_t header_len; + + r = mailsession_fetch_message_header(session, info->indx, &msg_header, + &header_len); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + message = NULL; + cur_token = 0; + r = mailimf_optional_fields_parse(msg_header, header_len, + &cur_token, &fields); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_PARSE; + goto free_list; + } + + mailsession_fetch_result_free(session, msg_header); + } + + r = mailsession_get_message_flags(session, info->indx, &flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + if (match_messages(message, info->size, fields, flags, + charset, key)) { + uint32_t * pnum; + + pnum = malloc(sizeof(* pnum)); + if (pnum == NULL) { + if (message != NULL) + mailsession_fetch_result_free(session, message); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * pnum = info->indx; + + r = clist_append(list, pnum); + if (r < 0) { + free(pnum); + if (message != NULL) + mailsession_fetch_result_free(session, message); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + if (message != NULL) + mailsession_fetch_result_free(session, message); + } + + search_result = mail_search_result_new(list); + if (search_result == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = search_result; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + mailmessage_list_free(env_list); + return res; +} +#endif + +#if 0 +int maildriver_generic_search_messages(mailsession * session, char * charset, + struct mail_search_key * key, + struct mail_search_result ** result) +{ + return MAIL_ERROR_NOT_IMPLEMENTED; +} +#endif + +int +maildriver_env_list_to_msg_list(struct mailmessage_list * env_list, + clist ** result) +{ + clist * msg_list; + int r; + int res; + unsigned int i; + + msg_list = clist_new(); + if (msg_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + uint32_t * pindex; + + pindex = malloc(sizeof(* pindex)); + if (pindex == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_msg_list; + } + + * pindex = msg->msg_index; + + r = clist_append(msg_list, pindex); + if (r < 0) { + free(pindex); + res = MAIL_ERROR_MEMORY; + goto free_msg_list; + } + + } + } + + * result = msg_list; + + return MAIL_NO_ERROR; + + free_msg_list: + clist_foreach(msg_list, (clist_func) free, NULL); + clist_free(msg_list); + err: + return res; +} + + +int +maildriver_env_list_to_msg_list_no_flags(struct mailmessage_list * env_list, + clist ** result) +{ + clist * msg_list; + int r; + int res; + unsigned int i; + + msg_list = clist_new(); + if (msg_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_flags == NULL) { + uint32_t * pindex; + + pindex = malloc(sizeof(* pindex)); + if (pindex == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_msg_list; + } + + * pindex = msg->msg_index; + + r = clist_append(msg_list, pindex); + if (r < 0) { + free(pindex); + res = MAIL_ERROR_MEMORY; + goto free_msg_list; + } + + } + } + + * result = msg_list; + + return MAIL_NO_ERROR; + + free_msg_list: + clist_foreach(msg_list, (clist_func) free, NULL); + clist_free(msg_list); + err: + return res; +} + + + +int maildriver_imf_error_to_mail_error(int error) +{ + switch (error) { + case MAILIMF_NO_ERROR: + return MAIL_NO_ERROR; + + case MAILIMF_ERROR_PARSE: + return MAIL_ERROR_PARSE; + + case MAILIMF_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case MAILIMF_ERROR_INVAL: + return MAIL_ERROR_INVAL; + + case MAILIMF_ERROR_FILE: + return MAIL_ERROR_FILE; + + default: + return MAIL_ERROR_INVAL; + } +} + +char * maildriver_quote_mailbox(const char * mb) +{ + MMAPString * gstr; + char * str; + + gstr = mmap_string_new(""); + if (gstr == NULL) + return NULL; + + while (* mb != 0) { + char hex[3]; + + if (((* mb >= 'a') && (* mb <= 'z')) || + ((* mb >= 'A') && (* mb <= 'Z')) || + ((* mb >= '0') && (* mb <= '9'))) + mmap_string_append_c(gstr, * mb); + else { + if (mmap_string_append_c(gstr, '%') == NULL) + goto free; + snprintf(hex, 3, "%02x", (unsigned char) (* mb)); + if (mmap_string_append(gstr, hex) == NULL) + goto free; + } + mb ++; + } + + str = strdup(gstr->str); + if (str == NULL) + goto free; + + mmap_string_free(gstr); + + return str; + + free: + mmap_string_free(gstr); + return NULL; +} + + +int maildriver_cache_clean_up(struct mail_cache_db * cache_db_env, + struct mail_cache_db * cache_db_flags, + struct mailmessage_list * env_list) +{ + chash * hash_exist; + int res; + int r; + char keyname[PATH_MAX]; + unsigned int i; + + /* flush cache */ + + hash_exist = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL); + if (hash_exist == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + chashdatum key; + chashdatum value; + + msg = carray_get(env_list->msg_tab, i); + + value.data = NULL; + value.len = 0; + + if (cache_db_env != NULL) { + snprintf(keyname, PATH_MAX, "%s-envelope", msg->msg_uid); + + key.data = keyname; + key.len = (unsigned int) strlen(keyname); + r = chash_set(hash_exist, &key, &value, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + } + + if (cache_db_flags != NULL) { + snprintf(keyname, PATH_MAX, "%s-flags", msg->msg_uid); + + key.data = keyname; + key.len = (unsigned int) strlen(keyname); + r = chash_set(hash_exist, &key, &value, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + } + } + + /* clean up */ + if (cache_db_env != NULL) + mail_cache_db_clean_up(cache_db_env, hash_exist); + if (cache_db_flags != NULL) + mail_cache_db_clean_up(cache_db_flags, hash_exist); + + chash_free(hash_exist); + + return MAIL_NO_ERROR; + + free: + chash_free(hash_exist); + err: + return res; +} + +/* + maildriver_message_cache_clean_up() + + remove files in cache_dir that does not correspond to a message. + + get_uid_from_filename() modifies the given filename so that it + is a uid when returning from the function. If get_uid_from_filename() + clears the content of file (set to empty string), this means that + this file should not be deleted. +*/ + +int maildriver_message_cache_clean_up(char * cache_dir, + struct mailmessage_list * env_list, + void (* get_uid_from_filename)(char *)) +{ + chash * hash_exist; + DIR * d; + char cached_filename[PATH_MAX]; + struct dirent * ent; + char keyname[PATH_MAX]; + unsigned int i; + int res; + int r; + + /* remove files */ + + hash_exist = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL); + if (hash_exist == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + chashdatum key; + chashdatum value; + + msg = carray_get(env_list->msg_tab, i); + + key.data = msg->msg_uid; + key.len = (unsigned int) strlen(msg->msg_uid); + value.data = NULL; + value.len = 0; + r = chash_set(hash_exist, &key, &value, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + } + + d = opendir(cache_dir); + while ((ent = readdir(d)) != NULL) { + chashdatum key; + chashdatum value; + + if (strcmp(ent->d_name, ".") == 0) + continue; + + if (strcmp(ent->d_name, "..") == 0) + continue; + + if (strstr(ent->d_name, ".db") != NULL) + continue; + + strncpy(keyname, ent->d_name, sizeof(keyname)); + keyname[sizeof(keyname) - 1] = '\0'; + + get_uid_from_filename(keyname); + + if (* keyname == '\0') + continue; + + key.data = keyname; + key.len = (unsigned int) strlen(keyname); + + r = chash_get(hash_exist, &key, &value); + if (r < 0) { + snprintf(cached_filename, sizeof(cached_filename), + "%s/%s", cache_dir, ent->d_name); + unlink(cached_filename); + } + } + closedir(d); + + chash_free(hash_exist); + + return MAIL_NO_ERROR; + + free: + chash_free(hash_exist); + err: + return res; +} diff --git a/Sources/libetpan/driver/interface/maildriver_tools.h b/Sources/libetpan/driver/interface/maildriver_tools.h new file mode 100644 index 00000000..229e72b7 --- /dev/null +++ b/Sources/libetpan/driver/interface/maildriver_tools.h @@ -0,0 +1,81 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildriver_tools.h,v 1.15 2006/06/07 15:10:01 smarinier Exp $ + */ + +#ifndef MAILDRIVER_TOOLS_H + +#define MAILDRIVER_TOOLS_H + +#include "maildriver_types.h" +#include "mail_cache_db_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int +maildriver_generic_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +#if 0 +int maildriver_generic_search_messages(mailsession * session, char * charset, + struct mail_search_key * key, + struct mail_search_result ** result); +#endif + +int +maildriver_env_list_to_msg_list(struct mailmessage_list * env_list, + clist ** result); + +int maildriver_imf_error_to_mail_error(int error); + +char * maildriver_quote_mailbox(const char * mb); + +int +maildriver_env_list_to_msg_list_no_flags(struct mailmessage_list * env_list, + clist ** result); + +int maildriver_cache_clean_up(struct mail_cache_db * cache_db_env, + struct mail_cache_db * cache_db_flags, + struct mailmessage_list * env_list); + +int maildriver_message_cache_clean_up(char * cache_dir, + struct mailmessage_list * env_list, + void (* get_uid_from_filename)(char *)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/interface/maildriver_types.c b/Sources/libetpan/driver/interface/maildriver_types.c new file mode 100644 index 00000000..52cd5943 --- /dev/null +++ b/Sources/libetpan/driver/interface/maildriver_types.c @@ -0,0 +1,361 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildriver_types.c,v 1.28 2006/06/16 09:23:38 smarinier Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "maildriver_types.h" +#include +#include +#include "mailmessage.h" + +LIBETPAN_EXPORT +struct mailmessage_list * mailmessage_list_new(carray * msg_tab) +{ + struct mailmessage_list * env_list; + + env_list = malloc(sizeof(* env_list)); + if (env_list == NULL) + return NULL; + + env_list->msg_tab = msg_tab; + + return env_list; +} + +LIBETPAN_EXPORT +void mailmessage_list_free(struct mailmessage_list * env_list) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + if (msg != NULL) + mailmessage_free(msg); + } + carray_free(env_list->msg_tab); + free(env_list); +} + +LIBETPAN_EXPORT +struct mail_list * mail_list_new(clist * list) +{ + struct mail_list * resp; + + resp = malloc(sizeof(* resp)); + if (resp == NULL) + return NULL; + resp->mb_list = list; + + return resp; +} + +LIBETPAN_EXPORT +void mail_list_free(struct mail_list * resp) +{ + clist_foreach(resp->mb_list, (clist_func) free, NULL); + clist_free(resp->mb_list); + free(resp); +} + +static int32_t mailimf_date_time_to_int(struct mailimf_date_time * date) +{ + return date->dt_year * 12 * 30 * 24 * 60 * 60 + + date->dt_month * 30 * 24 * 60 * 60 + date->dt_day * 24 * 60 * 60 + + (date->dt_hour - date->dt_zone) * 60 * 60 + + date->dt_min * 60 + date->dt_sec; +} + +LIBETPAN_EXPORT +int32_t mailimf_date_time_comp(struct mailimf_date_time * date1, + struct mailimf_date_time * date2) +{ + return mailimf_date_time_to_int(date1) - mailimf_date_time_to_int(date2); +} + + + + + + + +#if 0 +struct mail_search_key * +mail_search_key_new(int sk_type, + char * sk_bcc, + struct mailimf_date_time * sk_before, + char * sk_body, + char * sk_cc, + char * sk_from, + struct mailimf_date_time * sk_on, + struct mailimf_date_time * sk_since, + char * sk_subject, + char * sk_text, + char * sk_to, + char * sk_header_name, + char * sk_header_value, + size_t sk_larger, + struct mail_search_key * sk_not, + struct mail_search_key * sk_or1, + struct mail_search_key * sk_or2, + size_t sk_smaller, + clist * sk_multiple) +{ + struct mail_search_key * key; + + key = malloc(sizeof(* key)); + if (key == NULL) + return NULL; + + key->sk_type = sk_type; + key->sk_bcc = sk_bcc; + key->sk_before = sk_before; + key->sk_body = sk_body; + key->sk_cc = sk_cc; + key->sk_from = sk_from; + key->sk_on = sk_on; + key->sk_since = sk_since; + key->sk_subject = sk_subject; + key->sk_text = sk_text; + key->sk_to = sk_to; + key->sk_header_name = sk_header_name; + key->sk_header_value = sk_header_value; + key->sk_larger = sk_larger; + key->sk_not = sk_not; + key->sk_or1 = sk_or1; + key->sk_or2 = sk_or2; + key->sk_smaller = sk_smaller; + key->sk_multiple = sk_multiple; + + return key; +} + + +void mail_search_key_free(struct mail_search_key * key) +{ + if (key->sk_bcc) + free(key->sk_bcc); + if (key->sk_before) + mailimf_date_time_free(key->sk_before); + if (key->sk_body) + free(key->sk_body); + if (key->sk_cc) + free(key->sk_cc); + if (key->sk_from) + free(key->sk_from); + if (key->sk_on) + mailimf_date_time_free(key->sk_on); + if (key->sk_since) + mailimf_date_time_free(key->sk_since); + if (key->sk_subject) + free(key->sk_subject); + if (key->sk_text) + free(key->sk_text); + if (key->sk_to) + free(key->sk_to); + if (key->sk_header_name) + free(key->sk_header_name); + if (key->sk_header_value) + free(key->sk_header_value); + if (key->sk_not) + mail_search_key_free(key->sk_not); + if (key->sk_or1) + mail_search_key_free(key->sk_or1); + if (key->sk_or2) + mail_search_key_free(key->sk_or2); + if (key->sk_multiple) { + clist_foreach(key->sk_multiple, (clist_func) mail_search_key_free, NULL); + clist_free(key->sk_multiple); + } + + free(key); +} + + +struct mail_search_result * mail_search_result_new(clist * list) +{ + struct mail_search_result * search_result; + + search_result = malloc(sizeof(* search_result)); + if (search_result == NULL) + return NULL; + search_result->list = list; + + return search_result; +} + +void mail_search_result_free(struct mail_search_result * search_result) +{ + clist_foreach(search_result->list, (clist_func) free, NULL); + clist_free(search_result->list); + free(search_result); +} +#endif + +struct error_message { + int code; + char * message; +}; + +static struct error_message message_tab[] = { +{ MAIL_NO_ERROR, "no error" }, +{ MAIL_NO_ERROR_AUTHENTICATED, "no error - authenticated" }, +{ MAIL_NO_ERROR_NON_AUTHENTICATED, "no error - not authenticated" }, +{ MAIL_ERROR_NOT_IMPLEMENTED, "not implemented" }, +{ MAIL_ERROR_UNKNOWN, "unknown"}, +{ MAIL_ERROR_CONNECT, "connect"}, +{ MAIL_ERROR_BAD_STATE, "bad state"}, +{ MAIL_ERROR_FILE, "file error - file could not be accessed" }, +{ MAIL_ERROR_STREAM, "stream error - socket could not be read or written" }, +{ MAIL_ERROR_LOGIN, "login error" }, +{ MAIL_ERROR_CREATE, "create error" }, +{ MAIL_ERROR_DELETE, /* 10 */ "delete error" }, +{ MAIL_ERROR_LOGOUT, "logout error" }, +{ MAIL_ERROR_NOOP, "noop error" }, +{ MAIL_ERROR_RENAME, "rename error" }, +{ MAIL_ERROR_CHECK, "check error" }, +{ MAIL_ERROR_EXAMINE, "examine error" }, +{ MAIL_ERROR_SELECT, "select error - folder does not exist" }, +{ MAIL_ERROR_MEMORY, "not enough memory" }, +{ MAIL_ERROR_STATUS, "status error" }, +{ MAIL_ERROR_SUBSCRIBE, "subscribe error" }, +{ MAIL_ERROR_UNSUBSCRIBE, /* 20 */ "unsubscribe error" }, +{ MAIL_ERROR_LIST, "list error" }, +{ MAIL_ERROR_LSUB, "lsub error" }, +{ MAIL_ERROR_APPEND, "append error - mail could not be appended" }, +{ MAIL_ERROR_COPY, "copy error" }, +{ MAIL_ERROR_FETCH, "fetch error" }, +{ MAIL_ERROR_STORE, "store error" }, +{ MAIL_ERROR_SEARCH, "search error" }, +{ MAIL_ERROR_DISKSPACE, " error: not enough diskspace" }, +{ MAIL_ERROR_MSG_NOT_FOUND, "message not found" }, +{ MAIL_ERROR_PARSE, /* 30 */ "parse error" }, +{ MAIL_ERROR_INVAL, "invalid parameter for the function" }, +{ MAIL_ERROR_PART_NOT_FOUND, "mime part of the message is not found" }, +{ MAIL_ERROR_REMOVE, "remove error - the message did not exist" }, +{ MAIL_ERROR_FOLDER_NOT_FOUND, "folder not found" }, +{ MAIL_ERROR_MOVE, "move error" }, +{ MAIL_ERROR_STARTTLS, "starttls error" }, +{ MAIL_ERROR_CACHE_MISS, "mail cache missed" }, +{ MAIL_ERROR_NO_TLS, "no starttls" }, +{ MAIL_ERROR_EXPUNGE, "expunge error" }, +{ MAIL_ERROR_PROTOCOL, "protocol error - server did not respect the protocol" }, +{ MAIL_ERROR_CAPABILITY, "capability error" }, +{ MAIL_ERROR_CLOSE, "close error" }, +{ MAIL_ERROR_FATAL, "fatal error" }, +{ MAIL_ERROR_READONLY, "mailbox is readonly" }, +{ MAIL_ERROR_NO_APOP, "pop3 error - no apop" }, +{ MAIL_ERROR_COMMAND_NOT_SUPPORTED, "nntp error - command not supported" }, +{ MAIL_ERROR_NO_PERMISSION, "nntp error - no permission" }, +{ MAIL_ERROR_PROGRAM_ERROR, "nntp error - program error" }, +{ MAIL_ERROR_SUBJECT_NOT_FOUND, "internal threading error - subject not found" }}; + +LIBETPAN_EXPORT +const char * maildriver_strerror(int err) +{ + int count; + int i; + + count = sizeof(message_tab) / sizeof(struct error_message); + + for(i = 0 ; i < count ; i++) { + if (message_tab[i].code == err) { + return message_tab[i].message; + } + } + + return "unknown error"; +} + +LIBETPAN_EXPORT +struct mail_flags * mail_flags_new_empty(void) +{ + struct mail_flags * flags; + + flags = malloc(sizeof(* flags)); + if (flags == NULL) + goto err; + + flags->fl_flags = MAIL_FLAG_NEW; + flags->fl_extension = clist_new(); + if (flags->fl_extension == NULL) + goto free; + + return flags; + + free: + free(flags); + err: + return NULL; +} + +LIBETPAN_EXPORT +struct mail_flags * mail_flags_new(uint32_t fl_flags, clist * fl_extension) +{ + struct mail_flags * flags; + + flags = malloc(sizeof(* flags)); + if (flags == NULL) + goto err; + + flags->fl_flags = fl_flags; + flags->fl_extension = fl_extension; + + return flags; + +err: + return NULL; +} + +LIBETPAN_EXPORT +void mail_flags_free(struct mail_flags * flags) +{ + clist_foreach(flags->fl_extension, (clist_func) free, NULL); + clist_free(flags->fl_extension); + free(flags); +} + +LIBETPAN_EXPORT +void *libetpan_malloc(size_t length) { + return malloc( length); +} + +LIBETPAN_EXPORT +void libetpan_free(void* data) { + free( data); +} diff --git a/Sources/libetpan/driver/interface/maildriver_types.h b/Sources/libetpan/driver/interface/maildriver_types.h new file mode 100644 index 00000000..e0a8b680 --- /dev/null +++ b/Sources/libetpan/driver/interface/maildriver_types.h @@ -0,0 +1,822 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildriver_types.h,v 1.49 2008/04/19 09:25:40 hoa Exp $ + */ + +#ifndef MAILDRIVER_TYPES_H + +#define MAILDRIVER_TYPES_H + +#ifndef _MSC_VER +# ifdef HAVE_INTTYPES_H +# include +# endif +# include +#endif + +#include +#include +#include +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct mailsession_driver mailsession_driver; + +typedef struct mailsession mailsession; + +typedef struct mailmessage_driver mailmessage_driver; + +typedef struct mailmessage mailmessage; + + +/* + mailmessage_list is a list of mailmessage + + - tab is an array of mailmessage structures +*/ + +struct mailmessage_list { + carray * msg_tab; /* elements are (mailmessage *) */ +}; + +LIBETPAN_EXPORT +struct mailmessage_list * mailmessage_list_new(carray * msg_tab); + +LIBETPAN_EXPORT +void mailmessage_list_free(struct mailmessage_list * env_list); + +/* + mail_list is a list of mailbox names + + - list is a list of mailbox names +*/ + +struct mail_list { + clist * mb_list; /* elements are (char *) */ +}; + +LIBETPAN_EXPORT +struct mail_list * mail_list_new(clist * mb_list); + +LIBETPAN_EXPORT +void mail_list_free(struct mail_list * resp); + +/* + This is a flag value. + Flags can be combined with OR operation +*/ + +enum { + MAIL_FLAG_NEW = 1 << 0, + MAIL_FLAG_SEEN = 1 << 1, + MAIL_FLAG_FLAGGED = 1 << 2, + MAIL_FLAG_DELETED = 1 << 3, + MAIL_FLAG_ANSWERED = 1 << 4, + MAIL_FLAG_FORWARDED = 1 << 5, + MAIL_FLAG_CANCELLED = 1 << 6 +}; + +/* + mail_flags is the value of a flag related to a message. + + - flags is the standard flags value + + - extension is a list of unknown flags for libEtPan! +*/ + +struct mail_flags { + uint32_t fl_flags; + clist * fl_extension; /* elements are (char *) */ +}; + +LIBETPAN_EXPORT +struct mail_flags * mail_flags_new(uint32_t fl_flags, clist * fl_ext); + +LIBETPAN_EXPORT +void mail_flags_free(struct mail_flags * flags); + +/* + This function creates a flag for a new message +*/ + +LIBETPAN_EXPORT +struct mail_flags * mail_flags_new_empty(void); + + +/* + mailimf_date_time_comp compares two dates + + +*/ + +LIBETPAN_EXPORT +int32_t mailimf_date_time_comp(struct mailimf_date_time * date1, + struct mailimf_date_time * date2); + +/* + this is type type of the search criteria +*/ + +enum { + MAIL_SEARCH_KEY_ALL, /* all messages correspond */ + MAIL_SEARCH_KEY_ANSWERED, /* messages with flag \Answered */ + MAIL_SEARCH_KEY_BCC, /* messages which Bcc field contains + a given string */ + MAIL_SEARCH_KEY_BEFORE, /* messages which internal date is earlier + than the specified date */ + MAIL_SEARCH_KEY_BODY, /* message that contains the given string + (in header and text parts) */ + MAIL_SEARCH_KEY_CC, /* messages whose Cc field contains the + given string */ + MAIL_SEARCH_KEY_DELETED, /* messages with the flag \Deleted */ + MAIL_SEARCH_KEY_FLAGGED, /* messages with the flag \Flagged */ + MAIL_SEARCH_KEY_FROM, /* messages whose From field contains the + given string */ + MAIL_SEARCH_KEY_NEW, /* messages with the flag \Recent and not + the \Seen flag */ + MAIL_SEARCH_KEY_OLD, /* messages that do not have the + \Recent flag set */ + MAIL_SEARCH_KEY_ON, /* messages whose internal date is the + specified date */ + MAIL_SEARCH_KEY_RECENT, /* messages with the flag \Recent */ + MAIL_SEARCH_KEY_SEEN, /* messages with the flag \Seen */ + MAIL_SEARCH_KEY_SINCE, /* messages whose internal date is later + than specified date */ + MAIL_SEARCH_KEY_SUBJECT, /* messages whose Subject field contains the + given string */ + MAIL_SEARCH_KEY_TEXT, /* messages whose text part contains the + given string */ + MAIL_SEARCH_KEY_TO, /* messages whose To field contains the + given string */ + MAIL_SEARCH_KEY_UNANSWERED, /* messages with no flag \Answered */ + MAIL_SEARCH_KEY_UNDELETED, /* messages with no flag \Deleted */ + MAIL_SEARCH_KEY_UNFLAGGED, /* messages with no flag \Flagged */ + MAIL_SEARCH_KEY_UNSEEN, /* messages with no flag \Seen */ + MAIL_SEARCH_KEY_HEADER, /* messages whose given field + contains the given string */ + MAIL_SEARCH_KEY_LARGER, /* messages whose size is larger then + the given size */ + MAIL_SEARCH_KEY_NOT, /* not operation of the condition */ + MAIL_SEARCH_KEY_OR, /* or operation between two conditions */ + MAIL_SEARCH_KEY_SMALLER, /* messages whose size is smaller than + the given size */ + MAIL_SEARCH_KEY_MULTIPLE /* the boolean operator between the + conditions is AND */ +}; + +/* + mail_search_key is the condition on the messages to return + + - type is the type of the condition + + - bcc is the text to search in the Bcc field when type is + MAIL_SEARCH_KEY_BCC, should be allocated with malloc() + + - before is a date when type is MAIL_SEARCH_KEY_BEFORE + + - body is the text to search in the message when type is + MAIL_SEARCH_KEY_BODY, should be allocated with malloc() + + - cc is the text to search in the Cc field when type is + MAIL_SEARCH_KEY_CC, should be allocated with malloc() + + - from is the text to search in the From field when type is + MAIL_SEARCH_KEY_FROM, should be allocated with malloc() + + - on is a date when type is MAIL_SEARCH_KEY_ON + + - since is a date when type is MAIL_SEARCH_KEY_SINCE + + - subject is the text to search in the Subject field when type is + MAILIMAP_SEARCH_KEY_SUBJECT, should be allocated with malloc() + + - text is the text to search in the text part of the message when + type is MAILIMAP_SEARCH_KEY_TEXT, should be allocated with malloc() + + - to is the text to search in the To field when type is + MAILIMAP_SEARCH_KEY_TO, should be allocated with malloc() + + - header_name is the header name when type is MAILIMAP_SEARCH_KEY_HEADER, + should be allocated with malloc() + + - header_value is the text to search in the given header when type is + MAILIMAP_SEARCH_KEY_HEADER, should be allocated with malloc() + + - larger is a size when type is MAILIMAP_SEARCH_KEY_LARGER + + - not is a condition when type is MAILIMAP_SEARCH_KEY_NOT + + - or1 is a condition when type is MAILIMAP_SEARCH_KEY_OR + + - or2 is a condition when type is MAILIMAP_SEARCH_KEY_OR + + - sentbefore is a date when type is MAILIMAP_SEARCH_KEY_SENTBEFORE + + - senton is a date when type is MAILIMAP_SEARCH_KEY_SENTON + + - sentsince is a date when type is MAILIMAP_SEARCH_KEY_SENTSINCE + + - smaller is a size when type is MAILIMAP_SEARCH_KEY_SMALLER + + - multiple is a set of message when type is MAILIMAP_SEARCH_KEY_MULTIPLE +*/ + +#if 0 +struct mail_search_key { + int sk_type; + union { + char * sk_bcc; + struct mailimf_date_time * sk_before; + char * sk_body; + char * sk_cc; + char * sk_from; + struct mailimf_date_time * sk_on; + struct mailimf_date_time * sk_since; + char * sk_subject; + char * sk_text; + char * sk_to; + char * sk_header_name; + char * sk_header_value; + size_t sk_larger; + struct mail_search_key * sk_not; + struct mail_search_key * sk_or1; + struct mail_search_key * sk_or2; + size_t sk_smaller; + clist * sk_multiple; /* list of (struct mailimap_search_key *) */ + } sk_data; +}; + + +struct mail_search_key * +mail_search_key_new(int sk_type, + char * sk_bcc, struct mailimf_date_time * sk_before, + char * sk_body, char * sk_cc, char * sk_from, + struct mailimf_date_time * sk_on, struct mailimf_date_time * sk_since, + char * sk_subject, char * sk_text, char * sk_to, + char * sk_header_name, char * sk_header_value, size_t sk_larger, + struct mail_search_key * sk_not, struct mail_search_key * sk_or1, + struct mail_search_key * sk_or2, size_t sk_smaller, + clist * sk_multiple); + +void mail_search_key_free(struct mail_search_key * key); +#endif + +/* + mail_search_result is a list of message numbers that is returned + by the mailsession_search_messages function() +*/ + +#if 0 +struct mail_search_result { + clist * sr_list; /* list of (uint32_t *) */ +}; + +struct mail_search_result * mail_search_result_new(clist * sr_list); + +void mail_search_result_free(struct mail_search_result * search_result); +#endif + + +/* + There is three kinds of identities : + - storage + - folders + - session + + A storage (struct mailstorage) represents whether a server or + a main path, + + A storage can be an IMAP server, the root path of a MH or a mbox file. + + Folders (struct mailfolder) are the mailboxes we can + choose in the server or as sub-folder of the main path. + + Folders for IMAP are the IMAP mailboxes, for MH this is one of the + folder of the MH storage, for mbox, there is only one folder, the + mbox file content; + + A mail session (struct mailsession) is whether a connection to a server + or a path that is open. It is the abstraction lower folders and storage. + It allow us to send commands. + + We have a session driver for mail session for each kind of storage. + + From a session, we can get a message (struct mailmessage) to read. + We have a message driver for each kind of storage. +*/ + +/* + maildriver is the driver structure for mail sessions + + - name is the name of the driver + + - initialize() is the function that will initializes a data structure + specific to the driver, it returns a value that will be stored + in the field data of the session. + The field data of the session is the state of the session, + the internal data structure used by the driver. + It is called when creating the mailsession structure with + mailsession_new(). + + - uninitialize() frees the structure created with initialize() + + - parameters() implements functions specific to the given mail access + + - connect_stream() connects a stream to the session + + - connect_path() notify a main path to the session + + - starttls() changes the current stream to a TLS stream + + - login() notifies the user and the password to authenticate to the + session + + - logout() exits the session and closes the stream + + - noop() does no operation on the session, but it can be + used to poll for the status of the connection. + + - build_folder_name() will return an allocated string with + that contains the complete path of the folder to create + + - create_folder() creates the folder that corresponds to the + given name + + - delete_folder() deletes the folder that corresponds to the + given name + + - rename_folder() change the name of the folder + + - check_folder() makes a checkpoint of the session + + - examine_folder() selects a mailbox as readonly + + - select_folder() selects a mailbox + + - expunge_folder() deletes all messages marked \Deleted + + - status_folder() queries the status of the folder + (number of messages, number of recent messages, number of + unseen messages) + + - messages_number() queries the number of messages in the folder + + - recent_number() queries the number of recent messages in the folder + + - unseen_number() queries the number of unseen messages in the folder + + - list_folders() returns the list of all sub-mailboxes + of the given mailbox + + - lsub_folders() returns the list of subscribed + sub-mailboxes of the given mailbox + + - subscribe_folder() subscribes to the given mailbox + + - unsubscribe_folder() unsubscribes to the given mailbox + + - append_message() adds a RFC 2822 message to the current + given mailbox + + - copy_message() copies a message whose number is given to + a given mailbox. The mailbox must be accessible from + the same session. + + - move_message() copies a message whose number is given to + a given mailbox. The mailbox must be accessible from the + same session. + + - get_messages_list() returns the list of message numbers + of the current mailbox. + + - get_envelopes_list() fills the parsed fields in the + mailmessage structures of the mailmessage_list. + + - remove_message() removes the given message from the mailbox. + The message is permanently deleted. + + - search_message() returns a list of message numbers that + corresponds to the given criteria. + + - get_message returns a mailmessage structure that corresponds + to the given message number. + + - get_message_by_uid returns a mailmessage structure that corresponds + to the given message unique identifier. + + * mandatory functions are the following : + + - connect_stream() of connect_path() + - logout() + - get_messages_list() + - get_envelopes_list() + + * we advise you to implement these functions : + + - select_folder() (in case a session can access several folders) + - noop() (to check if the server is responding) + - check_folder() (to make a checkpoint of the session) + - status_folder(), messages_number(), recent_number(), unseen_number() + (to get stat of the folder) + - append_message() (but can't be done in the case of POP3 at least) + - login() in a case of an authenticated driver. + - starttls() in a case of a stream driver, if the procotol supports + STARTTLS. + - get_message_by_uid() so that the application can remember the message + by UID and build its own list of messages. + - login_sasl() notifies the SASL information to authenticate to the + session. + + * drivers' specific : + + Everything that is specific to the driver will be implemented in this + function : + + - parameters() +*/ + +struct mailsession_driver { + char * sess_name; + + int (* sess_initialize)(mailsession * session); + void (* sess_uninitialize)(mailsession * session); + + int (* sess_parameters)(mailsession * session, + int id, void * value); + + int (* sess_connect_stream)(mailsession * session, mailstream * s); + int (* sess_connect_path)(mailsession * session, const char * path); + + int (* sess_starttls)(mailsession * session); + + int (* sess_login)(mailsession * session, const char * userid, const char * password); + int (* sess_logout)(mailsession * session); + int (* sess_noop)(mailsession * session); + + /* folders operations */ + + int (* sess_build_folder_name)(mailsession * session, const char * mb, + const char * name, char ** result); + + int (* sess_create_folder)(mailsession * session, const char * mb); + int (* sess_delete_folder)(mailsession * session, const char * mb); + int (* sess_rename_folder)(mailsession * session, const char * mb, + const char * new_name); + int (* sess_check_folder)(mailsession * session); + int (* sess_examine_folder)(mailsession * session, const char * mb); + int (* sess_select_folder)(mailsession * session, const char * mb); + int (* sess_expunge_folder)(mailsession * session); + int (* sess_status_folder)(mailsession * session, const char * mb, + uint32_t * result_num, uint32_t * result_recent, + uint32_t * result_unseen); + int (* sess_messages_number)(mailsession * session, const char * mb, + uint32_t * result); + int (* sess_recent_number)(mailsession * session, const char * mb, + uint32_t * result); + int (* sess_unseen_number)(mailsession * session, const char * mb, + uint32_t * result); + + int (* sess_list_folders)(mailsession * session, const char * mb, + struct mail_list ** result); + int (* sess_lsub_folders)(mailsession * session, const char * mb, + struct mail_list ** result); + + int (* sess_subscribe_folder)(mailsession * session, const char * mb); + int (* sess_unsubscribe_folder)(mailsession * session, const char * mb); + + /* messages operations */ + + int (* sess_append_message)(mailsession * session, + const char * message, size_t size); + int (* sess_append_message_flags)(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); + int (* sess_copy_message)(mailsession * session, + uint32_t num, const char * mb); + int (* sess_move_message)(mailsession * session, + uint32_t num, const char * mb); + + int (* sess_get_message)(mailsession * session, + uint32_t num, mailmessage ** result); + + int (* sess_get_message_by_uid)(mailsession * session, + const char * uid, mailmessage ** result); + + int (* sess_get_messages_list)(mailsession * session, + struct mailmessage_list ** result); + int (* sess_get_envelopes_list)(mailsession * session, + struct mailmessage_list * env_list); + int (* sess_remove_message)(mailsession * session, uint32_t num); + + int (* sess_login_sasl)(mailsession * session, const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); +}; + + +/* + session is the data structure for a mail session. + + - data is the internal data structure used by the driver + It is called when initializing the mailsession structure. + + - driver is the driver used for the session +*/ + +struct mailsession { + void * sess_data; + mailsession_driver * sess_driver; +}; + + + + +/* + mailmessage_driver is the driver structure to get information from messages. + + - name is the name of the driver + + - initialize() is the function that will initializes a data structure + specific to the driver, it returns a value that will be stored + in the field data of the mailsession. + The field data of the session is the state of the session, + the internal data structure used by the driver. + It is called when initializing the mailmessage structure with + mailmessage_init(). + + - uninitialize() frees the structure created with initialize(). + It will be called by mailmessage_free(). + + - flush() will free from memory all temporary structures of the message + (for example, the MIME structure of the message). + + - fetch_result_free() will free all strings resulted by fetch() or + any fetch_xxx() functions that returns a string. + + - fetch() returns the content of the message (headers and text). + + - fetch_header() returns the content of the headers. + + - fetch_body() returns the message text (message content without headers) + + - fetch_size() returns the size of the message content. + + - get_bodystructure() returns the MIME structure of the message. + + - fetch_section() returns the content of a given MIME part + + - fetch_section_header() returns the header of the message + contained by the given MIME part. + + - fetch_section_mime() returns the MIME headers of the + given MIME part. + + - fetch_section_body() returns the text (if this is a message, this is the + message content without headers) of the given MIME part. + + - fetch_envelope() returns a mailimf_fields structure, with a list of + fields chosen by the driver. + + - get_flags() returns a the flags related to the message. + When you want to get flags of a message, you have to make sure to + call get_flags() at least once before using directly message->flags. +*/ + +#define LIBETPAN_MAIL_MESSAGE_CHECK + +struct mailmessage_driver { + char * msg_name; + + int (* msg_initialize)(mailmessage * msg_info); + + void (* msg_uninitialize)(mailmessage * msg_info); + + void (* msg_flush)(mailmessage * msg_info); + + void (* msg_check)(mailmessage * msg_info); + + void (* msg_fetch_result_free)(mailmessage * msg_info, + char * msg); + + int (* msg_fetch)(mailmessage * msg_info, + char ** result, + size_t * result_len); + + int (* msg_fetch_header)(mailmessage * msg_info, + char ** result, + size_t * result_len); + + int (* msg_fetch_body)(mailmessage * msg_info, + char ** result, size_t * result_len); + + int (* msg_fetch_size)(mailmessage * msg_info, + size_t * result); + + int (* msg_get_bodystructure)(mailmessage * msg_info, + struct mailmime ** result); + + int (* msg_fetch_section)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + + int (* msg_fetch_section_header)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_section_mime)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_section_body)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_envelope)(mailmessage * msg_info, + struct mailimf_fields ** result); + + int (* msg_get_flags)(mailmessage * msg_info, + struct mail_flags ** result); +}; + + +/* + mailmessage is a data structure to get information from messages + + - session is the session linked to the given message, it can be NULL + + - driver is the message driver + + - index is the message number + + - uid, when it is not NULL, it means that the folder + the folder has persistant message numbers, the string is + the unique message number in the folder. + uid should be implemented if possible. + for drivers where we cannot generate real uid, + a suggestion is "AAAA-IIII" where AAAA is some + random session number and IIII the content of index field. + + - size, when it is not 0, is the size of the message content. + + - fields, when it is not NULL, are the header fields of the message. + + - flags, when it is not NULL, are the flags related to the message. + + - single_fields, when resolved != 0, is filled with the data of fields. + + - mime, when it is not NULL + + - cached is != 0 when the header fields were read from the cache. + + - data is data specific to the driver, this is internal data structure, + some state of the message. +*/ + +struct mailmessage { + mailsession * msg_session; + mailmessage_driver * msg_driver; + uint32_t msg_index; + char * msg_uid; + + size_t msg_size; + struct mailimf_fields * msg_fields; + struct mail_flags * msg_flags; + + int msg_resolved; + struct mailimf_single_fields msg_single_fields; + struct mailmime * msg_mime; + + /* internal data */ + + int msg_cached; + void * msg_data; + + /* + msg_folder field : + used to reference the mailfolder, this is a workaround due + to the problem with initial conception, where folder notion + did not exist. + */ + void * msg_folder; + /* user data */ + void * msg_user_data; +}; + + +/* + mailmessage_tree is a node in the messages tree (thread) + + - node_parent is the parent of the message, it is NULL if the message + is the root of the message tree. + + - node_msgid is the message ID of this node. + + - node_date is the date of the message in number of second elapsed + since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC). + + - node_msg is the message structure that is stored referenced by the node. + is msg is NULL, this is a dummy node. + + - node_children is an array that contains all the children of the node. + children are mailmessage_tree structures. + + - node_is_reply is != 0 when the message is a reply or a forward + + - node_base_subject is the extracted subject of the message. +*/ + +struct mailmessage_tree { + struct mailmessage_tree * node_parent; + char * node_msgid; + time_t node_date; + mailmessage * node_msg; + carray * node_children; /* array of (struct mailmessage_tree *) */ + + /* private, used for threading */ + int node_is_reply; + char * node_base_subject; +}; + +LIBETPAN_EXPORT +struct mailmessage_tree * +mailmessage_tree_new(char * node_msgid, time_t node_date, + mailmessage * node_msg); + +LIBETPAN_EXPORT +void mailmessage_tree_free(struct mailmessage_tree * tree); + +/* + mailmessage_tree_free_recursive + + if you want to release memory of the given tree and all the sub-trees, + you can use this function. +*/ +LIBETPAN_EXPORT +void mailmessage_tree_free_recursive(struct mailmessage_tree * tree); + + +struct generic_message_t { + int (* msg_prefetch)(mailmessage * msg_info); + void (* msg_prefetch_free)(struct generic_message_t * msg); + int msg_fetched; + char * msg_message; + size_t msg_length; + void * msg_data; +}; + +LIBETPAN_EXPORT +const char * maildriver_strerror(int err); + +/* basic malloc / free functions to be compliant with the library allocations */ +LIBETPAN_EXPORT +void *libetpan_malloc(size_t length); + +LIBETPAN_EXPORT +void libetpan_free(void* data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/interface/maildriver_types_helper.c b/Sources/libetpan/driver/interface/maildriver_types_helper.c new file mode 100644 index 00000000..9eaac5fa --- /dev/null +++ b/Sources/libetpan/driver/interface/maildriver_types_helper.c @@ -0,0 +1,108 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 200 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildriver_types_helper.c,v 1.5 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "maildriver_types_helper.h" + +#include "mail.h" + +#include "clist.h" +#include +#include + +int mail_flags_add_extension(struct mail_flags * flags, + char * ext_flag) +{ + char * str; + int r; + + if (mail_flags_has_extension(flags, ext_flag)) + return MAIL_NO_ERROR; + + str = strdup(ext_flag); + if (str == NULL) + return MAIL_ERROR_MEMORY; + + r = clist_append(flags->fl_extension, str); + if (r < 0) { + free(str); + return MAIL_ERROR_MEMORY; + } + + return MAIL_NO_ERROR; +} + +int mail_flags_remove_extension(struct mail_flags * flags, + char * ext_flag) +{ + clistiter * cur; + + cur = clist_begin(flags->fl_extension); + while (cur != NULL) { + char * flag_name; + + flag_name = clist_content(cur); + + if (strcasecmp(flag_name, ext_flag) == 0) { + free(flag_name); + cur = clist_delete(flags->fl_extension, cur); + } + else + cur = clist_next(cur); + } + + return MAIL_NO_ERROR; +} + +int mail_flags_has_extension(struct mail_flags * flags, + char * ext_flag) +{ + clistiter * cur; + + for(cur = clist_begin(flags->fl_extension) ; cur != NULL ; + cur = clist_next(cur)) { + char * flag_name; + + flag_name = clist_content(cur); + + if (strcasecmp(flag_name, ext_flag) == 0) + return TRUE; + } + + return FALSE; +} diff --git a/Sources/libetpan/driver/interface/maildriver_types_helper.h b/Sources/libetpan/driver/interface/maildriver_types_helper.h new file mode 100644 index 00000000..1890e234 --- /dev/null +++ b/Sources/libetpan/driver/interface/maildriver_types_helper.h @@ -0,0 +1,99 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildriver_types_helper.h,v 1.6 2004/11/21 21:53:35 hoa Exp $ + */ + +#ifndef MAILDRIVER_TYPES_HELPER_H + +#define MAILDRIVER_TYPES_HELPER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mail_flags_add_extension adds the given flag if it does not exists in + the flags. + + @param flags this is the flag to change + + @param ext_flag this is the name of an extension flag + the given flag name is duplicated and is no more needed after + the function call. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mail_flags_add_extension(struct mail_flags * flags, + char * ext_flag); + +/* + mail_flags_remove_extension removes the given flag if it does not exists in + the flags. + + @param flags this is the flag to change + + @param ext_flag this is the name of an extension flag + the given flag name is no more needed after the function call. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mail_flags_remove_extension(struct mail_flags * flags, + char * ext_flag); + +/* + mail_flags_has_extension returns 1 if the flags is in the given flags, + 0 is returned otherwise. + + @param flags this is the flag to change + + @param ext_flag this is the name of an extension flag + the given flag name is no more needed after the function call. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mail_flags_has_extension(struct mail_flags * flags, + char * ext_flag); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/interface/mailfolder.c b/Sources/libetpan/driver/interface/mailfolder.c new file mode 100644 index 00000000..3c70e321 --- /dev/null +++ b/Sources/libetpan/driver/interface/mailfolder.c @@ -0,0 +1,169 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailfolder.c,v 1.6 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailfolder.h" + +#include + +#include "maildriver.h" +#include "mailstorage.h" + +LIBETPAN_EXPORT +int mailfolder_noop(struct mailfolder * folder) +{ + return mailsession_noop(folder->fld_session); +} + +LIBETPAN_EXPORT +int mailfolder_check(struct mailfolder * folder) +{ + return mailsession_check_folder(folder->fld_session); +} + +LIBETPAN_EXPORT +int mailfolder_expunge(struct mailfolder * folder) +{ + return mailsession_expunge_folder(folder->fld_session); +} + +LIBETPAN_EXPORT +int mailfolder_status(struct mailfolder * folder, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + return mailsession_status_folder(folder->fld_session, + folder->fld_pathname, result_messages, + result_recent, result_unseen); +} + +LIBETPAN_EXPORT +int mailfolder_append_message(struct mailfolder * folder, + char * message, size_t size) +{ + return mailsession_append_message(folder->fld_session, message, size); +} + +LIBETPAN_EXPORT +int mailfolder_append_message_flags(struct mailfolder * folder, + char * message, size_t size, struct mail_flags * flags) +{ + return mailsession_append_message_flags(folder->fld_session, message, + size, flags); +} + +LIBETPAN_EXPORT +int mailfolder_get_messages_list(struct mailfolder * folder, + struct mailmessage_list ** result) +{ + int r; + struct mailmessage_list * msg_list; + unsigned int i; + struct mailstorage * storage; + + /* workaround for POP3 case - begin */ + storage = folder->fld_storage; + if (strcmp(storage->sto_driver->sto_name, "pop3") == 0) { + mailstorage_disconnect(storage); + r = mailstorage_connect(storage); + if (r != MAIL_NO_ERROR) + return r; + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) + return r; + } + /* workaround for POP3 case - begin */ + + r = mailsession_get_messages_list(folder->fld_session, &msg_list); + if (r != MAIL_NO_ERROR) + return r; + + for(i = 0 ; i < carray_count(msg_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(msg_list->msg_tab, i); + msg->msg_folder = folder; + } + + * result = msg_list; + + return MAIL_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailfolder_get_envelopes_list(struct mailfolder * folder, + struct mailmessage_list * result) +{ + return mailsession_get_envelopes_list(folder->fld_session, result); +} + +LIBETPAN_EXPORT +int mailfolder_get_message(struct mailfolder * folder, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg; + int r; + + r = mailsession_get_message(folder->fld_session, num, &msg); + if (r != MAIL_NO_ERROR) + return r; + + msg->msg_folder = folder; + + * result = msg; + + return MAIL_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailfolder_get_message_by_uid(struct mailfolder * folder, + const char * uid, mailmessage ** result) +{ + mailmessage * msg; + int r; + + r = mailsession_get_message_by_uid(folder->fld_session, uid, &msg); + if (r != MAIL_NO_ERROR) + return r; + + msg->msg_folder = folder; + + * result = msg; + + return MAIL_NO_ERROR; +} diff --git a/Sources/libetpan/driver/interface/mailfolder.h b/Sources/libetpan/driver/interface/mailfolder.h new file mode 100644 index 00000000..4ec60251 --- /dev/null +++ b/Sources/libetpan/driver/interface/mailfolder.h @@ -0,0 +1,80 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailfolder.h,v 1.4 2006/04/06 22:54:56 hoa Exp $ + */ + +#ifndef MAILFOLDER_H + +#define MAILFOLDER_H + +#include "mailstorage_types.h" + +LIBETPAN_EXPORT +int mailfolder_noop(struct mailfolder * folder); + +LIBETPAN_EXPORT +int mailfolder_check(struct mailfolder * folder); + +LIBETPAN_EXPORT +int mailfolder_expunge(struct mailfolder * folder); + +LIBETPAN_EXPORT +int mailfolder_status(struct mailfolder * folder, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +LIBETPAN_EXPORT +int mailfolder_append_message(struct mailfolder * folder, + char * message, size_t size); + +LIBETPAN_EXPORT +int mailfolder_append_message_flags(struct mailfolder * folder, + char * message, size_t size, struct mail_flags * flags); + +LIBETPAN_EXPORT +int mailfolder_get_messages_list(struct mailfolder * folder, + struct mailmessage_list ** result); + +LIBETPAN_EXPORT +int mailfolder_get_envelopes_list(struct mailfolder * folder, + struct mailmessage_list * result); + +LIBETPAN_EXPORT +int mailfolder_get_message(struct mailfolder * folder, + uint32_t num, mailmessage ** result); + +LIBETPAN_EXPORT +int mailfolder_get_message_by_uid(struct mailfolder * folder, + const char * uid, mailmessage ** result); + +#endif diff --git a/Sources/libetpan/driver/interface/mailmessage.c b/Sources/libetpan/driver/interface/mailmessage.c new file mode 100644 index 00000000..e49dc642 --- /dev/null +++ b/Sources/libetpan/driver/interface/mailmessage.c @@ -0,0 +1,259 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmessage.c,v 1.17 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailmessage.h" + +#include "mail.h" + +#include + +LIBETPAN_EXPORT +int mailmessage_init(mailmessage * msg_info, + mailsession * msg_session, + mailmessage_driver * msg_driver, + uint32_t msg_index, size_t msg_size) +{ + int r; + int res; + + msg_info->msg_driver = msg_driver; + msg_info->msg_session = msg_session; + msg_info->msg_index = msg_index; + msg_info->msg_uid = NULL; + + msg_info->msg_cached = FALSE; + msg_info->msg_size = msg_size; + msg_info->msg_fields = NULL; + memset(&msg_info->msg_single_fields, 0, + sizeof(struct mailimf_single_fields)); + msg_info->msg_resolved = FALSE; + msg_info->msg_flags = NULL; + + msg_info->msg_mime = NULL; + msg_info->msg_data = NULL; + msg_info->msg_folder = NULL; + msg_info->msg_user_data = NULL; + + if (msg_driver->msg_initialize != NULL) { + r = msg_driver->msg_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + + return MAIL_NO_ERROR; + + err: + msg_info->msg_driver = NULL; + msg_info->msg_session = NULL; + return res; +} + +LIBETPAN_EXPORT +int mailmessage_flush(mailmessage * msg_info) +{ + if (msg_info->msg_driver->msg_flush == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + msg_info->msg_driver->msg_flush(msg_info); + + return MAIL_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailmessage_check(mailmessage * msg_info) +{ + if (msg_info->msg_driver->msg_check == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + msg_info->msg_driver->msg_check(msg_info); + + return MAIL_NO_ERROR; +} +LIBETPAN_EXPORT +int mailmessage_fetch_result_free(mailmessage * msg_info, + char * msg) +{ + if (msg_info->msg_driver->msg_fetch_result_free == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + msg_info->msg_driver->msg_fetch_result_free(msg_info, msg); + + return MAIL_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailmessage_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + if (msg_info->msg_driver->msg_fetch == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch(msg_info, result, result_len); +} + +LIBETPAN_EXPORT +int mailmessage_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + if (msg_info->msg_driver->msg_fetch_header == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch_header(msg_info, result, result_len); +} + +LIBETPAN_EXPORT +int mailmessage_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len) +{ + if (msg_info->msg_driver->msg_fetch_body == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch_body(msg_info, result, result_len); +} + +LIBETPAN_EXPORT +int mailmessage_fetch_size(mailmessage * msg_info, + size_t * result) +{ + if (msg_info->msg_driver->msg_fetch_size == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch_size(msg_info, result); +} + +LIBETPAN_EXPORT +int mailmessage_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result) +{ + if (msg_info->msg_driver->msg_get_bodystructure == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_get_bodystructure(msg_info, result); +} + +LIBETPAN_EXPORT +int mailmessage_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + if (msg_info->msg_driver->msg_fetch_section == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch_section(msg_info, mime, result, result_len); +} + +LIBETPAN_EXPORT +int mailmessage_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + if (msg_info->msg_driver->msg_fetch_section_header == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch_section_header(msg_info, mime, + result, result_len); +} + +LIBETPAN_EXPORT +int mailmessage_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + if (msg_info->msg_driver->msg_fetch_section_mime == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch_section_mime(msg_info, mime, + result, result_len); +} + +LIBETPAN_EXPORT +int mailmessage_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + if (msg_info->msg_driver->msg_fetch_section_body == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch_section_body(msg_info, mime, + result, result_len); +} + +LIBETPAN_EXPORT +int mailmessage_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result) +{ + if (msg_info->msg_driver->msg_fetch_envelope == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch_envelope(msg_info, result); +} + +LIBETPAN_EXPORT +int mailmessage_get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + struct mail_flags * dummy; + + if (msg_info->msg_driver->msg_get_flags == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + if (result != NULL) + return msg_info->msg_driver->msg_get_flags(msg_info, result); + else + return msg_info->msg_driver->msg_get_flags(msg_info, &dummy); +} + +LIBETPAN_EXPORT +void mailmessage_resolve_single_fields(mailmessage * msg_info) +{ + if (!msg_info->msg_resolved) { + if (msg_info->msg_fields != NULL) { + mailimf_single_fields_init(&msg_info->msg_single_fields, + msg_info->msg_fields); + msg_info->msg_resolved = TRUE; + } + } +} diff --git a/Sources/libetpan/driver/interface/mailmessage.h b/Sources/libetpan/driver/interface/mailmessage.h new file mode 100644 index 00000000..45e46a0e --- /dev/null +++ b/Sources/libetpan/driver/interface/mailmessage.h @@ -0,0 +1,379 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmessage.h,v 1.17 2008/02/20 22:15:51 hoa Exp $ + */ + +#include + +#ifndef MAILMESSAGE_H + +#define MAILMESSAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mailmessage_new + + This function will initializes a new empty message. + + @return a new empty message will be returned. +*/ +LIBETPAN_EXPORT +mailmessage * mailmessage_new(void); + +/* + mailmessage_free + + This function will release the memory used by this message. +*/ +LIBETPAN_EXPORT +void mailmessage_free(mailmessage * info); + +/* + mailmessage_init + + This function will initializes a mailmessage structure + with a message from a given session. + + @param msg_info This is the message to initialize. + + @param session This is the source session of the message. It + can be NULL if the message does not get the information + through the session. + + @param driver This is the driver to use for the message. + + @param indx This is the message number in the session. 0 can + be given if the message is not attached to a session. + + @param size is an optional parameter, 0 can be given. + This is informational. This is the size of message content. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ +LIBETPAN_EXPORT +int mailmessage_init(mailmessage * msg_info, + mailsession * session, + mailmessage_driver * driver, + uint32_t indx, size_t size); + +/* + mailmessage_flush + + This function will release all the temporary resources that are not + necessary to use the mailmessage structure from memory. These + resources are for example cached information, such as the MIME + structure. + + @param info is the message to clean. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. We can assume that MAIL_NO_ERROR is always returned. +*/ +LIBETPAN_EXPORT +int mailmessage_flush(mailmessage * info); + +/* + mailmessage_check + + This function will notify the new value of the flags to the session, + it must be called before mailsession_check_folder() in case the flags have + been changed. + + @param info is the message to checkpoint. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. We can assume that MAIL_NO_ERROR is always returned. +*/ +LIBETPAN_EXPORT +int mailmessage_check(mailmessage * info); + +/* + mailmessage_fetch_result_free + + This function releases the memory used by a message returned + by any of the fetch function that returns a (char *). + + @param msg_info is the message which the given buffer is from. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. We can assume that MAIL_NO_ERROR is always returned. +*/ +LIBETPAN_EXPORT +int mailmessage_fetch_result_free(mailmessage * msg_info, + char * msg); + +/* + mailmessage_fetch + + This function returns the content of the message (headers and text). + + @param msg_info is the message from which we want to fetch information. + + @param result The content of the message is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +int mailmessage_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len); + +/* + mailmessage_fetch_header + + This function returns the header of the message as a string. + + @param msg_info is the message from which we want to fetch information. + + @param result The header of the message is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +int mailmessage_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +/* + mailmessage_fetch_body + + This function returns the content of the message (without headers). + + @param msg_info is the message from which we want to fetch information. + @param result The message text (without headers) is returned + in (* result) + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +int mailmessage_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len); + +/* + mailmessage_fetch_size + + This function returns the size of the message content. + + @param msg_info is the message from which we want to fetch information. + + @param result The length of the message content is stored in (* result). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +int mailmessage_fetch_size(mailmessage * msg_info, + size_t * result); + +/* + mailmessage_get_bodystructure + + This functions returns the MIME structure of the message. + The returned information MUST not be freed by hand. It is freed by + mailmessage_flush() or mailmessage_free(). + + @param msg_info is the message from which we want to fetch information. + + @param result The MIME structure is stored in (* result). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +int mailmessage_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result); + +/* + mailmessage_fetch_section + + This function returns the content of a MIME part. + + @param msg_info is the message from which we want to fetch information. + + @param mime is the MIME part identifier. + + @param result The content is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. + */ +LIBETPAN_EXPORT +int mailmessage_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + +/* + mailmessage_fetch_section_header + + This function returns the header of the message contained + in the given MIME part. + + @param msg_info is the message from which we want to fetch information. + + @param mime is the MIME part identifier. + + @param result The header is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +int mailmessage_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +/* + mailmessage_fetch_section_mime + + This function returns the MIME header of the given MIME part. + + @param msg_info is the message from which we want to fetch information. + + @param mime is the MIME part identifier. + + @param result The MIME header is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +int mailmessage_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +/* + mailmessage_fetch_section_body + + This function returns the text part of the message contained + in the given MIME part. + + @param msg_info is the message from which we want to fetch information. + + @param mime is the MIME part identifier. + + @param result The message text is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. + */ +LIBETPAN_EXPORT +int mailmessage_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +/* + mailmessage_fetch_envelope + + This function returns a list of parsed fields of the message, + chosen by the driver. + The returned structure must be freed with mailimf_fields_free(). + + @param msg_info is the message from which we want to fetch information. + + @param result The headers list is returned in (* result) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. + */ +LIBETPAN_EXPORT +int mailmessage_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result); + + +/* + mailmessage_get_flags + + This function returns the flags related to the message. + The returned information MUST not be freed by hand. It is freed by + mailmessage_free(). + + @param msg_info is the message from which we want to fetch information. + + @param result The flags are stored in (* result). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +int mailmessage_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +/* + mailmessage_resolve_single_fields + + This function will use the fields information to fill the single_fields + structure in the mailmessage structure. + + @param msg_info This is the msg_info to process. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +void mailmessage_resolve_single_fields(mailmessage * msg_info); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/interface/mailmessage_tools.c b/Sources/libetpan/driver/interface/mailmessage_tools.c new file mode 100644 index 00000000..c71bc083 --- /dev/null +++ b/Sources/libetpan/driver/interface/mailmessage_tools.c @@ -0,0 +1,600 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmessage_tools.c,v 1.24 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailmessage_tools.h" +#include "mailmessage.h" + +#include + +#include "maildriver.h" +#include "maildriver_tools.h" + +int +mailmessage_generic_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + + msg = malloc(sizeof(* msg)); + + if (msg == NULL) { + return MAIL_ERROR_MEMORY; + } + + msg->msg_fetched = 0; + msg->msg_message = NULL; + msg->msg_length = 0; + + msg->msg_prefetch = NULL; + msg->msg_prefetch_free = NULL; + msg->msg_data = NULL; + + msg_info->msg_data = msg; + + return MAIL_NO_ERROR; +} + +void mailmessage_generic_flush(mailmessage * msg_info) +{ + struct generic_message_t * msg; + + if (msg_info->msg_mime != NULL) { + mailmime_free(msg_info->msg_mime); + msg_info->msg_mime = NULL; + } + msg = msg_info->msg_data; + if (msg != NULL) { + if (msg->msg_prefetch_free != NULL) + msg->msg_prefetch_free(msg); + msg->msg_fetched = 0; + } +} + +void mailmessage_generic_uninitialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + + mailmessage_generic_flush(msg_info); + + msg = msg_info->msg_data; + msg_info->msg_data = NULL; + free(msg); +} + +static inline int +mailmessage_generic_prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + + msg = msg_info->msg_data; + + if (msg->msg_fetched) + return MAIL_NO_ERROR; + +#if 0 + if (msg->message != NULL) + return MAIL_NO_ERROR; +#endif + + r = msg->msg_prefetch(msg_info); + if (r != MAIL_NO_ERROR) + return r; + + msg->msg_fetched = 1; + + return MAIL_NO_ERROR; +} + +static int +mailmessage_generic_prefetch_bodystructure(mailmessage * msg_info) +{ + size_t length; + char * message; + size_t cur_token; + struct mailmime * mime; + int r; + int res; + struct generic_message_t * msg; + + if (msg_info->msg_mime != NULL) { + /* it has already been fetched */ + return MAIL_NO_ERROR; + } + +#if 0 + msg = msg_info->data; + if (msg->message == NULL) { + r = mailmessage_generic_prefetch(msg_info); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } +#endif + r = mailmessage_generic_prefetch(msg_info); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + msg = msg_info->msg_data; + message = msg->msg_message; + length = msg->msg_length; + cur_token = 0; + r = mailmime_parse(message, length, &cur_token, &mime); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_PARSE; + goto err; + } + + msg_info->msg_mime = mime; + + return MAIL_NO_ERROR; + + err: + return res; +} + +void +mailmessage_generic_fetch_result_free(mailmessage * msg_info, char * msg) +{ + mmap_string_unref(msg); +} + +int mailmessage_generic_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + int r; + char * message; + size_t length; + MMAPString * mmapstr; + int res; + struct generic_message_t * msg; + + msg = msg_info->msg_data; + r = mailmessage_generic_prefetch(msg_info); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + message = msg->msg_message; + length = msg->msg_length; + + mmapstr = mmap_string_new_len(message, length); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmap; + } + + * result = mmapstr->str; + * result_len = length; + + return MAIL_NO_ERROR; + + free_mmap: + mmap_string_free(mmapstr); + err: + return res; +} + +int mailmessage_generic_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + int r; + char * message; + size_t cur_token; + size_t length; + MMAPString * mmapstr; + char * headers; + int res; + struct generic_message_t * msg; + + msg = msg_info->msg_data; + r = mailmessage_generic_prefetch(msg_info); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + message = msg->msg_message; + length = msg->msg_length; + cur_token = 0; + + while (1) { + r = mailimf_ignore_field_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + mailimf_crlf_parse(message, length, &cur_token); + + mmapstr = mmap_string_new_len(message, cur_token); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmap; + } + + headers = mmapstr->str; + + * result = headers; + * result_len = cur_token; + + return MAIL_NO_ERROR; + + free_mmap: + mmap_string_free(mmapstr); + err: + return res; +} + +int mailmessage_generic_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len) +{ + int r; + char * message; + size_t cur_token; + MMAPString * mmapstr; + size_t length; + int res; + struct generic_message_t * msg; + + msg = msg_info->msg_data; + r = mailmessage_generic_prefetch(msg_info); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + message = msg->msg_message; + length = msg->msg_length; + cur_token = 0; + + while (1) { + r = mailimf_ignore_field_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + mailimf_crlf_parse(message, length, &cur_token); + + mmapstr = mmap_string_new_len(message + cur_token, length - cur_token); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmap; + } + + * result = mmapstr->str; + * result_len = length - cur_token; + + return MAIL_NO_ERROR; + + free_mmap: + mmap_string_free(mmapstr); + err: + return res; +} + + + + +int +mailmessage_generic_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result) +{ + int r; + + r = mailmessage_generic_prefetch_bodystructure(msg_info); + if (r != MAIL_NO_ERROR) + return r; + + * result = msg_info->msg_mime; + + return MAIL_NO_ERROR; +} + + + + +int +mailmessage_generic_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + MMAPString * mmapstr; + int r; + int res; + + mmapstr = mmap_string_new_len(mime->mm_body->dt_data.dt_text.dt_data, + mime->mm_body->dt_data.dt_text.dt_length); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmap; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + free_mmap: + mmap_string_free(mmapstr); + err: + return res; +} + +int +mailmessage_generic_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + MMAPString * mmapstr; + int r; + int res; + size_t cur_token; + + /* skip mime */ + + cur_token = 0; + + if (mime->mm_type == MAILMIME_MESSAGE) { + + while (1) { + r = mailimf_ignore_field_parse(mime->mm_body->dt_data.dt_text.dt_data, + mime->mm_body->dt_data.dt_text.dt_length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + + r = mailimf_crlf_parse(mime->mm_body->dt_data.dt_text.dt_data, + mime->mm_body->dt_data.dt_text.dt_length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = maildriver_imf_error_to_mail_error(r); + goto err; + } + } + + mmapstr = mmap_string_new_len(mime->mm_body->dt_data.dt_text.dt_data, + cur_token); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmap; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + free_mmap: + mmap_string_free(mmapstr); + err: + return res; +} + +int +mailmessage_generic_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + MMAPString * mmapstr; + int r; + int res; + size_t cur_token; + + cur_token = 0; + + /* skip header */ + + while (1) { + r = mailimf_ignore_field_parse(mime->mm_mime_start, + mime->mm_length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + + r = mailimf_crlf_parse(mime->mm_mime_start, mime->mm_length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = maildriver_imf_error_to_mail_error(r); + goto err; + } + + mmapstr = mmap_string_new_len(mime->mm_mime_start, cur_token); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmap; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + free_mmap: + mmap_string_free(mmapstr); + err: + return res; +} + +int +mailmessage_generic_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + MMAPString * mmapstr; + int r; + int res; + size_t cur_token; + + cur_token = 0; + + if (mime->mm_type == MAILMIME_MESSAGE) { + + /* skip header */ + + while (1) { + r = mailimf_ignore_field_parse(mime->mm_body->dt_data.dt_text.dt_data, + mime->mm_body->dt_data.dt_text.dt_length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + + r = mailimf_crlf_parse(mime->mm_body->dt_data.dt_text.dt_data, + mime->mm_body->dt_data.dt_text.dt_length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = maildriver_imf_error_to_mail_error(r); + goto err; + } + } + + mmapstr = mmap_string_new_len(mime->mm_body->dt_data.dt_text.dt_data + + cur_token, mime->mm_body->dt_data.dt_text.dt_length - cur_token); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmap; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + free_mmap: + mmap_string_free(mmapstr); + err: + return res; +} + +int mailmessage_generic_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result) +{ + int r; + int res; + size_t cur_token; + char * header; + size_t length; + struct mailimf_fields * fields; + + r = mailmessage_fetch_header(msg_info, &header, &length); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + cur_token = 0; + + r = mailimf_envelope_fields_parse(header, length, &cur_token, + &fields); + if (r != MAILIMF_NO_ERROR) { + res = maildriver_imf_error_to_mail_error(r); + goto free; + /* do nothing */ + } + + mailmessage_fetch_result_free(msg_info, header); + + * result = fields; + + return MAIL_NO_ERROR; + + free: + mailmessage_fetch_result_free(msg_info, header); + err: + return res; +} diff --git a/Sources/libetpan/driver/interface/mailmessage_tools.h b/Sources/libetpan/driver/interface/mailmessage_tools.h new file mode 100644 index 00000000..bfe29ebb --- /dev/null +++ b/Sources/libetpan/driver/interface/mailmessage_tools.h @@ -0,0 +1,103 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmessage_tools.h,v 1.7 2004/11/21 21:53:35 hoa Exp $ + */ + +#ifndef MAILMESSAGE_TOOLS_H + +#define MAILMESSAGE_TOOLS_H + +#include "mailmessage_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int +mailmessage_generic_initialize(mailmessage * + msg_info); + +void mailmessage_generic_uninitialize(mailmessage * + msg_info); + +void mailmessage_generic_flush(mailmessage * msg_info); + +void mailmessage_generic_fetch_result_free(mailmessage * msg_info, + char * msg); + +int mailmessage_generic_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len); + +int mailmessage_generic_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +int mailmessage_generic_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len); + +int mailmessage_generic_get_bodystructure(mailmessage * + msg_info, + struct mailmime ** result); + +int +mailmessage_generic_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + +int +mailmessage_generic_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +int +mailmessage_generic_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +int +mailmessage_generic_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +int mailmessage_generic_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/interface/mailmessage_types.c b/Sources/libetpan/driver/interface/mailmessage_types.c new file mode 100644 index 00000000..9ae2b539 --- /dev/null +++ b/Sources/libetpan/driver/interface/mailmessage_types.c @@ -0,0 +1,98 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmessage_types.c,v 1.13 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailmessage_types.h" + +#include "mail.h" + +#include +#include + +LIBETPAN_EXPORT +mailmessage * mailmessage_new(void) +{ + mailmessage * msg_info; + + msg_info = malloc(sizeof(* msg_info)); + if (msg_info == NULL) + goto err; + + msg_info->msg_driver = NULL; + msg_info->msg_session = NULL; + msg_info->msg_index = 0; + msg_info->msg_uid = NULL; + + msg_info->msg_cached = FALSE; + msg_info->msg_size = 0; + msg_info->msg_fields = NULL; + memset(&msg_info->msg_single_fields, + 0, sizeof(struct mailimf_single_fields)); + msg_info->msg_resolved = FALSE; + msg_info->msg_flags = NULL; + + msg_info->msg_mime = NULL; + msg_info->msg_data = NULL; + + msg_info->msg_folder = NULL; + msg_info->msg_user_data = NULL; + + return msg_info; + + err: + return NULL; +} + +LIBETPAN_EXPORT +void mailmessage_free(mailmessage * msg_info) +{ + if (msg_info->msg_driver != NULL) { + if (msg_info->msg_driver->msg_uninitialize != NULL) + msg_info->msg_driver->msg_uninitialize(msg_info); + } + + if (msg_info->msg_fields != NULL) + mailimf_fields_free(msg_info->msg_fields); + if (msg_info->msg_mime != NULL) + mailmime_free(msg_info->msg_mime); + if (msg_info->msg_flags != NULL) + mail_flags_free(msg_info->msg_flags); + if (msg_info->msg_uid != NULL) + free(msg_info->msg_uid); + free(msg_info); +} diff --git a/Sources/libetpan/driver/interface/mailmessage_types.h b/Sources/libetpan/driver/interface/mailmessage_types.h new file mode 100644 index 00000000..5fa77118 --- /dev/null +++ b/Sources/libetpan/driver/interface/mailmessage_types.h @@ -0,0 +1,50 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmessage_types.h,v 1.9 2004/11/21 21:53:35 hoa Exp $ + */ + +#ifndef MAILMESSAGE_TYPES_H + +#define MAILMESSAGE_TYPES_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/interface/mailstorage.c b/Sources/libetpan/driver/interface/mailstorage.c new file mode 100644 index 00000000..7f606757 --- /dev/null +++ b/Sources/libetpan/driver/interface/mailstorage.c @@ -0,0 +1,355 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstorage.c,v 1.25 2008/02/20 22:15:51 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailstorage.h" + +#include "maildriver.h" + +#include +#include + +static int mailstorage_get_folder(struct mailstorage * storage, + char * pathname, mailsession ** result); + +LIBETPAN_EXPORT +struct mailfolder * mailfolder_new(struct mailstorage * storage, + const char * pathname, const char * virtual_name) +{ + struct mailfolder * folder; + + folder = malloc(sizeof(struct mailfolder)); + if (folder == NULL) + goto err; + + if (pathname != NULL) { + folder->fld_pathname = strdup(pathname); + if (folder->fld_pathname == NULL) + goto free; + } + else + folder->fld_pathname = NULL; + + if (virtual_name != NULL) { + folder->fld_virtual_name = strdup(virtual_name); + if (folder->fld_virtual_name == NULL) + goto free_pathname; + } + else + folder->fld_virtual_name = NULL; + + folder->fld_storage = storage; + + folder->fld_session = NULL; + folder->fld_shared_session = 0; + folder->fld_pos = NULL; + + folder->fld_parent = NULL; + folder->fld_sibling_index = 0; + folder->fld_children = carray_new(128); + if (folder->fld_children == NULL) + goto free_virtualname; + + return folder; + +free_virtualname: + if (folder->fld_virtual_name != NULL) + free(folder->fld_virtual_name); +free_pathname: + if (folder->fld_pathname != NULL) + free(folder->fld_pathname); +free: + free(folder); +err: + return NULL; +} + +LIBETPAN_EXPORT +void mailfolder_free(struct mailfolder * folder) +{ + if (folder->fld_parent != NULL) + mailfolder_detach_parent(folder); + + while (carray_count(folder->fld_children) > 0) { + struct mailfolder * child; + + child = carray_get(folder->fld_children, 0); + mailfolder_detach_parent(child); + } + + carray_free(folder->fld_children); + + if (folder->fld_session != NULL) + mailfolder_disconnect(folder); + + if (folder->fld_virtual_name != NULL) + free(folder->fld_virtual_name); + if (folder->fld_pathname != NULL) + free(folder->fld_pathname); + free(folder); +} + +LIBETPAN_EXPORT +int mailfolder_connect(struct mailfolder * folder) +{ + mailsession * session; + int res; + int r; + + if (folder->fld_storage == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + if (folder->fld_storage->sto_session == NULL) { + r = mailstorage_connect(folder->fld_storage); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + + if (folder->fld_session != NULL) { + if ((folder->fld_pathname != NULL) && (folder->fld_shared_session)) { + if (folder->fld_session->sess_driver->sess_select_folder != NULL) { + r = mailsession_select_folder(folder->fld_session, + folder->fld_pathname); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + } + + return MAIL_NO_ERROR; + } + + r = mailstorage_get_folder(folder->fld_storage, folder->fld_pathname, + &session); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + folder->fld_session = session; + folder->fld_shared_session = (session == folder->fld_storage->sto_session); + if (folder->fld_shared_session) { + r = clist_append(folder->fld_storage->sto_shared_folders, folder); + if (r < 0) { + folder->fld_session = NULL; + res = MAIL_ERROR_MEMORY; + goto err; + } + folder->fld_pos = clist_end(folder->fld_storage->sto_shared_folders); + } + + return MAIL_NO_ERROR; + +err: + return res; +} + +LIBETPAN_EXPORT +void mailfolder_disconnect(struct mailfolder * folder) +{ + if (folder->fld_session == NULL) + return; + + if (folder->fld_shared_session) { + clist_delete(folder->fld_storage->sto_shared_folders, folder->fld_pos); + folder->fld_pos = NULL; + } + else { + mailsession_logout(folder->fld_session); + mailsession_free(folder->fld_session); + } + + folder->fld_session = NULL; +} + +LIBETPAN_EXPORT +int mailfolder_add_child(struct mailfolder * parent, + struct mailfolder * child) +{ + unsigned int indx; + int r; + + r = carray_add(parent->fld_children, child, &indx); + if (r < 0) + return MAIL_ERROR_MEMORY; + + child->fld_sibling_index = indx; + child->fld_parent = parent; + + return MAIL_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailfolder_detach_parent(struct mailfolder * folder) +{ + unsigned int i; + int r; + + if (folder->fld_parent == NULL) + return MAIL_ERROR_INVAL; + + r = carray_delete_slow(folder->fld_parent->fld_children, + folder->fld_sibling_index); + if (r < 0) + return MAIL_ERROR_INVAL; + + for(i = 0 ; i < carray_count(folder->fld_parent->fld_children) ; i ++) { + struct mailfolder * child; + + child = carray_get(folder->fld_parent->fld_children, i); + child->fld_sibling_index = i; + } + + folder->fld_parent = NULL; + folder->fld_sibling_index = 0; + + return MAIL_NO_ERROR; +} + +LIBETPAN_EXPORT +struct mailstorage * mailstorage_new(const char * sto_id) +{ + struct mailstorage * storage; + + storage = malloc(sizeof(struct mailstorage)); + if (storage == NULL) + goto err; + + if (sto_id != NULL) { + storage->sto_id = strdup(sto_id); + if (storage->sto_id == NULL) + goto free; + } + else + storage->sto_id = NULL; + + storage->sto_data = NULL; + storage->sto_session = NULL; + storage->sto_driver = NULL; + storage->sto_shared_folders = clist_new(); + if (storage->sto_shared_folders == NULL) + goto free_id; + + return storage; + + free_id: + if (storage->sto_id != NULL) + free(storage->sto_id); + free: + free(storage); + err: + return NULL; +} + +LIBETPAN_EXPORT +void mailstorage_free(struct mailstorage * storage) +{ + if (storage->sto_session != NULL) + mailstorage_disconnect(storage); + + if (storage->sto_driver != NULL) { + if (storage->sto_driver->sto_uninitialize != NULL) + storage->sto_driver->sto_uninitialize(storage); + } + + clist_free(storage->sto_shared_folders); + + if (storage->sto_id != NULL) + free(storage->sto_id); + + free(storage); +} + +LIBETPAN_EXPORT +int mailstorage_connect(struct mailstorage * storage) +{ + if (storage->sto_session != NULL) + return MAIL_NO_ERROR; + + if (!clist_isempty(storage->sto_shared_folders)) + return MAIL_ERROR_BAD_STATE; + + if (storage->sto_driver->sto_connect == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return storage->sto_driver->sto_connect(storage); +} + + +LIBETPAN_EXPORT +void mailstorage_disconnect(struct mailstorage * storage) +{ + clistiter * cur; + + while ((cur = clist_begin(storage->sto_shared_folders)) != NULL) { + struct mailfolder * folder; + + folder = cur->data; + mailfolder_disconnect(folder); + } + + if (storage->sto_session == NULL) + return; + + mailsession_logout(storage->sto_session); + + mailsession_free(storage->sto_session); + storage->sto_session = NULL; +} + + +LIBETPAN_EXPORT +int mailstorage_noop(struct mailstorage * storage) +{ + return mailsession_noop(storage->sto_session); +} + + +static int mailstorage_get_folder(struct mailstorage * storage, + char * pathname, mailsession ** result) +{ + if (storage->sto_driver->sto_get_folder_session == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return storage->sto_driver->sto_get_folder_session(storage, + pathname, result); +} diff --git a/Sources/libetpan/driver/interface/mailstorage.h b/Sources/libetpan/driver/interface/mailstorage.h new file mode 100644 index 00000000..3421ce29 --- /dev/null +++ b/Sources/libetpan/driver/interface/mailstorage.h @@ -0,0 +1,110 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstorage.h,v 1.17 2006/06/02 15:44:30 smarinier Exp $ + */ + +#ifndef MAIL_STORAGE_H + +#define MAIL_STORAGE_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* storage */ + +/* + mailstorage_new + + This function creates an empty storage. This storage have to be initialized. + The "driver" and "data" fields should be initialized. + + @param id is the name of the storage. It can be NULL. + The given parameter is no more needed when the creation is finished. + The given string is duplicated. + + @return The mail storage is returned. +*/ + +LIBETPAN_EXPORT +struct mailstorage * mailstorage_new(const char * sto_id); + +LIBETPAN_EXPORT +void mailstorage_free(struct mailstorage * storage); + +/* + session will be initialized on success. +*/ + +LIBETPAN_EXPORT +int mailstorage_connect(struct mailstorage * storage); + +LIBETPAN_EXPORT +void mailstorage_disconnect(struct mailstorage * storage); + +LIBETPAN_EXPORT +int mailstorage_noop(struct mailstorage * storage); + + +/* folder */ + +LIBETPAN_EXPORT +struct mailfolder * mailfolder_new(struct mailstorage * fld_storage, + const char * fld_pathname, const char * fld_virtual_name); + +LIBETPAN_EXPORT +void mailfolder_free(struct mailfolder * folder); + +LIBETPAN_EXPORT +int mailfolder_add_child(struct mailfolder * parent, + struct mailfolder * child); + +LIBETPAN_EXPORT +int mailfolder_detach_parent(struct mailfolder * folder); + +LIBETPAN_EXPORT +int mailfolder_connect(struct mailfolder * folder); + +LIBETPAN_EXPORT +void mailfolder_disconnect(struct mailfolder * folder); + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/Sources/libetpan/driver/interface/mailstorage_tools.c b/Sources/libetpan/driver/interface/mailstorage_tools.c new file mode 100644 index 00000000..e3726b6d --- /dev/null +++ b/Sources/libetpan/driver/interface/mailstorage_tools.c @@ -0,0 +1,465 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstorage_tools.c,v 1.24 2010/04/05 13:17:48 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailstorage_tools.h" + +#include "libetpan-config.h" + +#include +#include +#ifdef WIN32 +# include "win_etpan.h" +#else +# include +# include +# include +# include +# include +# include +#endif +#include +#include +#include + +#include "mail.h" +#include "mailmessage.h" +#include "maildriver.h" +#include "connect.h" + +/* tools */ + +/* connection to TCP/IP server */ + +/* connection through a shell command */ +/* SEB unsupported on Windows */ +#ifndef WIN32 + +#define ENV_BUFFER_SIZE 512 + +static void do_exec_command(int fd, const char *command, + char *servername, uint16_t port) +{ + long i, maxopen; +#ifndef HAVE_SETENV + char env_buffer[ENV_BUFFER_SIZE]; +#endif + + if (fork() > 0) { + /* Fork again to become a child of init rather than + the etpan client. */ + exit(0); + } + +#ifndef HAVE_SETENV + if (servername) + snprintf(env_buffer, ENV_BUFFER_SIZE, "ETPANSERVER=%s", servername); + else + snprintf(env_buffer, ENV_BUFFER_SIZE, "ETPANSERVER="); + putenv(env_buffer); +#else + if (servername) + setenv("ETPANSERVER", servername, 1); + else + unsetenv("ETPANSERVER"); +#endif + +#ifndef HAVE_SETENV + if (port) + snprintf(env_buffer, ENV_BUFFER_SIZE, "ETPANPORT=%d", port); + else + snprintf(env_buffer, ENV_BUFFER_SIZE, "ETPANPORT="); + putenv(env_buffer); +#else + if (port) { + char porttext[20]; + + snprintf(porttext, sizeof(porttext), "%d", port); + setenv("ETPANPORT", porttext, 1); + } + else { + unsetenv("ETPANPORT"); + } +#endif + + /* Not a lot we can do if there's an error other than bail. */ + if (dup2(fd, 0) == -1) + exit(1); + if (dup2(fd, 1) == -1) + exit(1); + + /* Should we close stderr and reopen /dev/null? */ + + maxopen = sysconf(_SC_OPEN_MAX); + for (i=3; i < maxopen; i++) + close((int) i); + +#ifdef TIOCNOTTY + /* Detach from the controlling tty if we have one. Otherwise, + SSH might do something stupid like trying to use it instead + of running $SSH_ASKPASS. Doh. */ + fd = open("/dev/tty", O_RDONLY); + if (fd != -1) { + ioctl(fd, TIOCNOTTY, NULL); + close(fd); + } +#endif /* TIOCNOTTY */ + + execl("/bin/sh", "/bin/sh", "-c", command, NULL); + + /* Eep. Shouldn't reach this */ + exit(1); +} +#endif /* WIN32 */ + +static int subcommand_connect(char *command, char *servername, uint16_t port) +{ +/* SEB unsupported on Windows */ +#ifdef WIN32 + return -1; +#else + + int sockfds[2]; + pid_t childpid; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) + return -1; + + childpid = fork(); + if (!childpid) { + do_exec_command(sockfds[1], command, servername, port); + } + else if (childpid == -1) { + close(sockfds[0]); + close(sockfds[1]); + return -1; + } + + close(sockfds[1]); + + /* Reap child, leaving grandchild process to run */ + waitpid(childpid, NULL, 0); + + return sockfds[0]; +#endif /* WIN32 */ +} + +int mailstorage_generic_connect(mailsession_driver * driver, + char * servername, + uint16_t port, + char * command, + int connection_type, + int cache_function_id, + char * cache_directory, + int flags_function_id, + char * flags_directory, + mailsession ** result) +{ + return mailstorage_generic_connect_with_local_address(driver, + servername, + port, + NULL, + 0, + command, + connection_type, + cache_function_id, + cache_directory, + flags_function_id, + flags_directory, + result); +} + +int mailstorage_generic_connect_with_local_address(mailsession_driver * driver, + char * servername, + uint16_t port, + char * local_address, + uint16_t local_port, + char * command, + int connection_type, + int cache_function_id, + char * cache_directory, + int flags_function_id, + char * flags_directory, + mailsession ** result) +{ + int r; + int res; + mailstream * stream = NULL; + int fd = -1; + mailsession * session; + int connect_result; + switch (connection_type) { + case CONNECTION_TYPE_PLAIN: + case CONNECTION_TYPE_TRY_STARTTLS: + case CONNECTION_TYPE_STARTTLS: + case CONNECTION_TYPE_TLS: +#if HAVE_CFNETWORK + if (mailstream_cfstream_enabled) { + stream = mailstream_cfstream_open_voip(servername, port, mailstream_cfstream_voip_enabled); + if (stream == NULL) { + res = MAIL_ERROR_CONNECT; + goto err; + } + } +#endif + if (stream == NULL) { + fd = mail_tcp_connect_with_local_address(servername, port, + local_address, local_port); + if (fd == -1) { + res = MAIL_ERROR_CONNECT; + goto err; + } + } + break; + + case CONNECTION_TYPE_COMMAND: + case CONNECTION_TYPE_COMMAND_TRY_STARTTLS: + case CONNECTION_TYPE_COMMAND_STARTTLS: + case CONNECTION_TYPE_COMMAND_TLS: + fd = subcommand_connect(command, servername, port); + break; + default: + fd = -1; + break; + } + + if (fd == -1 && stream == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + switch (connection_type) { + case CONNECTION_TYPE_PLAIN: + case CONNECTION_TYPE_TRY_STARTTLS: + case CONNECTION_TYPE_STARTTLS: + case CONNECTION_TYPE_COMMAND: + case CONNECTION_TYPE_COMMAND_TRY_STARTTLS: + case CONNECTION_TYPE_COMMAND_STARTTLS: + if (stream == NULL) { + stream = mailstream_socket_open(fd); + } + break; + + case CONNECTION_TYPE_TLS: + case CONNECTION_TYPE_COMMAND_TLS: +#if HAVE_CFNETWORK + if (mailstream_cfstream_enabled) { + int ssl_level = MAILSTREAM_CFSTREAM_SSL_LEVEL_NEGOCIATED_SSL; + mailstream_cfstream_set_ssl_level(stream, ssl_level); + mailstream_cfstream_set_ssl_verification_mask(stream, MAILSTREAM_CFSTREAM_SSL_NO_VERIFICATION); + r = mailstream_cfstream_set_ssl_enabled(stream, 1); + if (r < 0) { + mailstream_close(stream); + return MAIL_ERROR_SSL; + } + } +#endif + if (stream == NULL) { + stream = mailstream_ssl_open(fd); + } + break; + + default: + stream = NULL; + break; + } + + if (stream == NULL) { + res = MAIL_ERROR_STREAM; +#ifdef WIN32 + closesocket(fd); +#else + close(fd); +#endif + goto err; + } + + session = mailsession_new(driver); + if (session == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_stream; + } + + if (cache_directory != NULL) { + char cache_directory_server[PATH_MAX]; + + snprintf(cache_directory_server, PATH_MAX, "%s/%s", + cache_directory, servername); + + r = mailsession_parameters(session, + cache_function_id, + cache_directory_server); + if (r != MAIL_NO_ERROR) { + res = r; + goto close_stream; + } + } + + if (flags_directory != NULL) { + char flags_directory_server[PATH_MAX]; + + snprintf(flags_directory_server, PATH_MAX, "%s/%s", + flags_directory, servername); + + r = mailsession_parameters(session, + flags_function_id, + flags_directory_server); + if (r != MAIL_NO_ERROR) { + res = r; + goto close_stream; + } + } + + r = mailsession_connect_stream(session, stream); + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto free; + } + + connect_result = r; + + switch (connection_type) { + case CONNECTION_TYPE_TRY_STARTTLS: + case CONNECTION_TYPE_COMMAND_TRY_STARTTLS: + r = mailsession_starttls(session); + if ((r != MAIL_NO_ERROR) && (r != MAIL_ERROR_NO_TLS)) { + res = r; + goto free; + } + break; + + case CONNECTION_TYPE_STARTTLS: + case CONNECTION_TYPE_COMMAND_STARTTLS: + r = mailsession_starttls(session); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + } + + * result = session; + + return connect_result; + + close_stream: + mailstream_close(stream); + free: + mailsession_free(session); + err: + return res; +} + + + + + +int mailstorage_generic_auth(mailsession * session, + int connect_result, + int auth_type, + char * login, + char * password) +{ + return mailstorage_generic_auth_sasl(session, + connect_result, + NULL, NULL, NULL, NULL, + login, login, + password, NULL); +} + +int mailstorage_generic_auth_sasl(mailsession * session, + int connect_result, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm) +{ + int must_auth; + int r; + int res; + + r = connect_result; + + must_auth = FALSE; + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + must_auth = TRUE; + break; + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto err; + } + + if (must_auth) { + if (auth_type != NULL) { + r = mailsession_login_sasl(session, auth_type, + server_fqdn, + local_ip_port, + remote_ip_port, + login, auth_name, + password, realm); + } + else { + if ((login == NULL) || (password == NULL)) { + r = MAIL_NO_ERROR; + } + else { + r = mailsession_login(session, login, password); + } + } + if (r != MAIL_NO_ERROR) { + mailsession_logout(session); + res = r; + goto err; + } + } + + return MAIL_NO_ERROR; + + err: + return res; +} diff --git a/Sources/libetpan/driver/interface/mailstorage_tools.h b/Sources/libetpan/driver/interface/mailstorage_tools.h new file mode 100644 index 00000000..bd1b21f3 --- /dev/null +++ b/Sources/libetpan/driver/interface/mailstorage_tools.h @@ -0,0 +1,89 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstorage_tools.h,v 1.8 2007/06/30 12:58:21 hoa Exp $ + */ + +#include "mailstorage.h" + +#ifndef MAILSTORAGE_TOOLS_H + +#define MAILSTORAGE_TOOLS_H + +#ifdef __cplusplus +extern "C" { +#endif + +int mailstorage_generic_connect(mailsession_driver * driver, + char * servername, + uint16_t port, + char * command, + int connection_type, + int cache_function_id, + char * cache_directory, + int flags_function_id, + char * flags_directory, + mailsession ** result); + +int mailstorage_generic_connect_with_local_address(mailsession_driver * driver, + char * servername, + uint16_t port, + char * local_address, + uint16_t local_port, + char * command, + int connection_type, + int cache_function_id, + char * cache_directory, + int flags_function_id, + char * flags_directory, + mailsession ** result); + +int mailstorage_generic_auth(mailsession * session, + int connect_result, + int auth_type, + char * login, + char * password); + +int mailstorage_generic_auth_sasl(mailsession * session, + int connect_result, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/interface/mailstorage_types.h b/Sources/libetpan/driver/interface/mailstorage_types.h new file mode 100644 index 00000000..96bd2d4b --- /dev/null +++ b/Sources/libetpan/driver/interface/mailstorage_types.h @@ -0,0 +1,203 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstorage_types.h,v 1.9 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifndef MAILSTORAGE_TYPES_H + +#define MAILSTORAGE_TYPES_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct mailstorage; + +typedef struct mailstorage_driver mailstorage_driver; + + +/* + There is three kinds of identities : + - storage + - folders + - session + + A storage (struct mailstorage) represents whether a server or + a main path, + + A storage can be an IMAP server, the root path of a MH or a mbox file. + + Folders (struct mailfolder) are the mailboxes we can + choose in the server or as sub-folder of the main path. + + Folders for IMAP are the IMAP mailboxes, for MH this is one of the + folder of the MH storage, for mbox, there is only one folder, the + mbox file content; + + A mail session (struct mailsession) is whether a connection to a server + or a path that is open. It is the abstraction lower folders and storage. + It allow us to send commands. + + We have a session driver for mail session for each kind of storage. + + From a session, we can get a message (struct mailmessage) to read. + We have a message driver for each kind of storage. +*/ + +/* + mailstorage_driver is the driver structure for mail storages + + - name is the name of the driver + + - connect() connects the storage to the remote access or to + the path in the local filesystem. + + - get_folder() can have two kinds of behaviour. + Either it creates a new session and independant from the session + used by the storage and select the given mailbox or + it selects the given mailbox in the current session. + It depends on the efficiency of the mail driver. + + - uninitialize() frees the data created with mailstorage constructor. +*/ + +struct mailstorage_driver { + char * sto_name; + int (* sto_connect)(struct mailstorage * storage); + int (* sto_get_folder_session)(struct mailstorage * storage, + char * pathname, mailsession ** result); + void (* sto_uninitialize)(struct mailstorage * storage); +}; + +/* + mailstorage is the data structure for a storage + + - id is the name of the storage, it can be NULL. + + - data is the data specific to the driver. + This is the internal state of the storage. + + - session is the session related to the storage. + + - driver is the driver for the storage. + + - shared_folders is the list of folders returned by the storage. +*/ + +struct mailstorage { + char * sto_id; + void * sto_data; + mailsession * sto_session; + mailstorage_driver * sto_driver; + clist * sto_shared_folders; /* list of (struct mailfolder *) */ + + void * sto_user_data; +}; + + + +/* + mailfolder is the data structure for a mailbox + + - pathname is the path of the mailbox on the storage + + - virtual_name is the folder identifier, it can be a path, + a name or NULL. + + - storage is the storage to which the folder belongs to. + + - session is the session related to the folder. It can be + different of the session of the storage. + + - shared_session is != 0 if the session is the same as the + session of the storage. + + - pos is the position of the folder in the "shared_folders" field + of the storage. + + folders can be chained into a tree. + + - parent is the parent of the folder. + + - sibling_index is the index of the folder in the list of children + of the parent. + + - children is the folder. +*/ + +struct mailfolder { + char * fld_pathname; + char * fld_virtual_name; + + struct mailstorage * fld_storage; + + mailsession * fld_session; + int fld_shared_session; + clistiter * fld_pos; + + struct mailfolder * fld_parent; + unsigned int fld_sibling_index; + carray * fld_children; /* array of (struct mailfolder *) */ + + void * fld_user_data; +}; + +/* + this is the type of socket connection +*/ + +enum { + CONNECTION_TYPE_PLAIN, /* when the connection is plain text */ + CONNECTION_TYPE_STARTTLS, /* when the connection is first plain, + then, we want to switch to + TLS (secure connection) */ + CONNECTION_TYPE_TRY_STARTTLS, /* the connection is first plain, + then, we will try to switch to TLS */ + CONNECTION_TYPE_TLS, /* the connection is over TLS */ + CONNECTION_TYPE_COMMAND, /* the connection is over a shell command */ + CONNECTION_TYPE_COMMAND_STARTTLS, /* the connection is over a shell + command and STARTTLS will be used */ + CONNECTION_TYPE_COMMAND_TRY_STARTTLS, /* the connection is over + a shell command and STARTTLS will + be tried */ + CONNECTION_TYPE_COMMAND_TLS /* the connection is over a shell + command in TLS */ +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/tools/Makefile.am b/Sources/libetpan/driver/tools/Makefile.am new file mode 100644 index 00000000..a671d50f --- /dev/null +++ b/Sources/libetpan/driver/tools/Makefile.am @@ -0,0 +1,47 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +etpaninclude_HEADERS = \ + generic_cache_types.h \ + mailthread.h mailthread_types.h + +AM_CPPFLAGS = -I$(top_builddir)/include \ + -I$(top_srcdir)/src/low-level/imf \ + -I$(top_srcdir)/src/low-level/mime \ + -I$(top_srcdir)/src/data-types \ + -I$(top_srcdir)/src/driver/interface + +noinst_LTLIBRARIES = libtools.la + +libtools_la_SOURCES = \ + generic_cache.h generic_cache.c \ + imfcache.h imfcache.c \ + mailthread.c mailthread_types.c diff --git a/Sources/libetpan/driver/tools/generic_cache.c b/Sources/libetpan/driver/tools/generic_cache.c new file mode 100644 index 00000000..f5f39401 --- /dev/null +++ b/Sources/libetpan/driver/tools/generic_cache.c @@ -0,0 +1,759 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: generic_cache.c,v 1.34 2008/02/20 22:15:51 hoa Exp $ + */ +#define HAVE_CONFIG_H 1 + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "generic_cache.h" + +#include "libetpan-config.h" + +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_SYS_MMAN_H +# include +#endif +#ifdef WIN32 +# include "win_etpan.h" +#endif +#include +#include +#include +#include +#include +#include + +#include "maildriver_types.h" +#include "imfcache.h" +#include "chash.h" +#include "mailmessage.h" +#include "mail_cache_db.h" + +int generic_cache_create_dir(char * dirname) +{ + struct stat buf; + int r; + + r = stat(dirname, &buf); + if (r != 0) { + +#ifdef WIN32 + r = mkdir(dirname); +#else + r = mkdir(dirname, 0700); +#endif + + if (r < 0) + return MAIL_ERROR_FILE; + } + else { + if (!S_ISDIR(buf.st_mode)) + return MAIL_ERROR_FILE; + } + + return MAIL_NO_ERROR; +} + +int generic_cache_store(char * filename, char * content, size_t length) +{ + int fd; + char * str; + + fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); + if (fd == -1) + return MAIL_ERROR_FILE; + + if (ftruncate(fd, length) < 0) { + close(fd); + return MAIL_ERROR_FILE; + } + + str = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (str == (char *)MAP_FAILED) { + close(fd); + return MAIL_ERROR_FILE; + } + + memcpy(str, content, length); + msync(str, length, MS_SYNC); + munmap(str, length); + + close(fd); + + return MAIL_NO_ERROR; +} + +int generic_cache_read(char * filename, char ** result, size_t * result_len) +{ + int fd; + char * str; + struct stat buf; + MMAPString * mmapstr; + char * content; + int res; + + if (stat(filename, &buf) < 0) { + res = MAIL_ERROR_CACHE_MISS; + goto err; + } + + fd = open(filename, O_RDONLY); + if (fd == -1) { + res = MAIL_ERROR_CACHE_MISS; + goto err; + } + + str = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (str == (char *)MAP_FAILED) { + res = MAIL_ERROR_FILE; + goto close; + } + + mmapstr = mmap_string_new_len(str, buf.st_size); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto unmap; + } + + if (mmap_string_ref(mmapstr) < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + content = mmapstr->str; + + munmap(str, buf.st_size); + close(fd); + + * result = content; + * result_len = buf.st_size; + + return MAIL_NO_ERROR; + + free: + mmap_string_free(mmapstr); + unmap: + munmap(str, buf.st_size); + close: + close(fd); + err: + return res; +} + +static int flags_extension_read(MMAPString * mmapstr, size_t * indx, + clist ** result) +{ + clist * list; + int r; + uint32_t count; + uint32_t i; + int res; + + r = mailimf_cache_int_read(mmapstr, indx, &count); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < count ; i++) { + char * str; + + r = mailimf_cache_string_read(mmapstr, indx, &str); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(list, str); + if (r < 0) { + free(str); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + * result = list; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + err: + return res; +} + +static int generic_flags_read(MMAPString * mmapstr, size_t * indx, + struct mail_flags ** result) +{ + clist * ext; + int r; + struct mail_flags * flags; + uint32_t value; + int res; + + r = mailimf_cache_int_read(mmapstr, indx, &value); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + ext = NULL; + r = flags_extension_read(mmapstr, indx, &ext); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + flags = mail_flags_new(value, ext); + if (flags == NULL) { + res = r; + goto free; + } + + * result = flags; + + return MAIL_NO_ERROR; + + free: + clist_foreach(ext, (clist_func) free, NULL); + clist_free(ext); + err: + return res; +} + +static int flags_extension_write(MMAPString * mmapstr, size_t * indx, + clist * ext) +{ + int r; + clistiter * cur; + + r = mailimf_cache_int_write(mmapstr, indx, clist_count(ext)); + if (r != MAIL_NO_ERROR) + return r; + + for(cur = clist_begin(ext) ; cur != NULL ; cur = clist_next(cur)) { + char * ext_flag; + + ext_flag = clist_content(cur); + r = mailimf_cache_string_write(mmapstr, indx, + ext_flag, strlen(ext_flag)); + if (r != MAIL_NO_ERROR) + return r; + } + + return MAIL_NO_ERROR; +} + +static int generic_flags_write(MMAPString * mmapstr, size_t * indx, + struct mail_flags * flags) +{ + int r; + + r = mailimf_cache_int_write(mmapstr, indx, + flags->fl_flags & ~MAIL_FLAG_NEW); + if (r != MAIL_NO_ERROR) + return r; + + r = flags_extension_write(mmapstr, indx, + flags->fl_extension); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; +} + + + + +static struct mail_flags * mail_flags_dup(struct mail_flags * flags) +{ + clist * list; + struct mail_flags * new_flags; + int r; + clistiter * cur; + + list = clist_new(); + if (list == NULL) { + goto err; + } + + for(cur = clist_begin(flags->fl_extension) ; cur != NULL ; + cur = clist_next(cur)) { + char * ext; + char * original_ext; + + original_ext = clist_content(cur); + ext = strdup(original_ext); + if (ext == NULL) { + goto free; + } + + r = clist_append(list, ext); + if (r < 0) { + free(ext); + goto free; + } + } + + new_flags = mail_flags_new(flags->fl_flags, list); + if (new_flags == NULL) { + goto free; + } + + return new_flags; + + free: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + err: + return NULL; +} + +static mailmessage * mailmessage_build(mailmessage * msg) +{ + mailmessage * new_msg; + + new_msg = malloc(sizeof(* new_msg)); + if (new_msg == NULL) + goto err; + + new_msg->msg_session = msg->msg_session; + new_msg->msg_driver = msg->msg_driver; + new_msg->msg_index = msg->msg_index; + if (msg->msg_uid == NULL) + new_msg->msg_uid = NULL; + else { + new_msg->msg_uid = strdup(msg->msg_uid); + if (new_msg->msg_uid == NULL) + goto free; + } + + new_msg->msg_cached = msg->msg_cached; + new_msg->msg_size = msg->msg_size; + new_msg->msg_fields = NULL; + new_msg->msg_flags = mail_flags_dup(msg->msg_flags); + if (new_msg->msg_flags == NULL) { + free(new_msg->msg_uid); + goto free; + } + + new_msg->msg_mime = NULL; + new_msg->msg_data = NULL; + + return new_msg; + + free: + free(new_msg); + err: + return NULL; +} + +struct mail_flags_store * mail_flags_store_new(void) +{ + struct mail_flags_store * flags_store; + + flags_store = malloc(sizeof(struct mail_flags_store)); + if (flags_store == NULL) + goto err; + + flags_store->fls_tab = carray_new(128); + if (flags_store->fls_tab == NULL) + goto free; + + flags_store->fls_hash = chash_new(128, CHASH_COPYALL); + if (flags_store->fls_hash == NULL) + goto free_tab; + + return flags_store; + + free_tab: + carray_free(flags_store->fls_tab); + free: + free(flags_store); + err: + return NULL; +} + +void mail_flags_store_clear(struct mail_flags_store * flags_store) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { + chashdatum key; + mailmessage * msg; + + msg = carray_get(flags_store->fls_tab, i); + + key.data = &msg->msg_index; + key.len = sizeof(msg->msg_index); + chash_delete(flags_store->fls_hash, &key, NULL); + + mailmessage_free(msg); + } + carray_set_size(flags_store->fls_tab, 0); +} + +void mail_flags_store_free(struct mail_flags_store * flags_store) +{ + mail_flags_store_clear(flags_store); + chash_free(flags_store->fls_hash); + carray_free(flags_store->fls_tab); + free(flags_store); +} + +int mail_flags_store_set(struct mail_flags_store * flags_store, + mailmessage * msg) +{ + chashdatum key; + chashdatum value; + unsigned int indx; + int res; + int r; + mailmessage * new_msg; + + if (msg->msg_flags == NULL) { + res = MAIL_NO_ERROR; + goto err; + } + + /* duplicate needed message info */ + new_msg = mailmessage_build(msg); + if (new_msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + key.data = &new_msg->msg_index; + key.len = sizeof(new_msg->msg_index); + + r = chash_get(flags_store->fls_hash, &key, &value); + if (r == 0) { + mailmessage * old_msg; + + indx = * (unsigned int *) value.data; + old_msg = carray_get(flags_store->fls_tab, indx); + mailmessage_free(old_msg); + } + else { + r = carray_set_size(flags_store->fls_tab, + carray_count(flags_store->fls_tab) + 1); + if (r != 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + indx = carray_count(flags_store->fls_tab) - 1; + } + + carray_set(flags_store->fls_tab, indx, new_msg); + + value.data = &indx; + value.len = sizeof(indx); + + r = chash_set(flags_store->fls_hash, &key, &value, NULL); + if (r < 0) { + carray_delete(flags_store->fls_tab, indx); + res = MAIL_ERROR_MEMORY; + goto free; + } + + return MAIL_NO_ERROR; + + free: + mailmessage_free(new_msg); + err: + return res; +} + +static int msg_index_compare(mailmessage ** msg1, mailmessage ** msg2) +{ + return (* msg1)->msg_index - (* msg2)->msg_index; +} + +void mail_flags_store_sort(struct mail_flags_store * flags_store) +{ + qsort(carray_data(flags_store->fls_tab), + carray_count(flags_store->fls_tab), sizeof(mailmessage *), + (int (*)(const void *, const void *)) msg_index_compare); +} + +struct mail_flags * +mail_flags_store_get(struct mail_flags_store * flags_store, uint32_t indx) +{ + struct mail_flags * flags; + chashdatum key; + chashdatum value; + int r; + unsigned int tab_index; + mailmessage * msg; + + key.data = &indx; + key.len = sizeof(indx); + + r = chash_get(flags_store->fls_hash, &key, &value); + + if (r < 0) + return NULL; + +#if 0 + flags = mail_flags_dup((struct mail_flags *) value.data); +#endif + tab_index = * (unsigned int *) value.data; + msg = carray_get(flags_store->fls_tab, tab_index); + if (msg->msg_flags == NULL) + return NULL; + + flags = mail_flags_dup(msg->msg_flags); + + return flags; +} + +int mail_flags_compare(struct mail_flags * flags1, struct mail_flags * flags2) +{ + clistiter * cur1; + + if (clist_count(flags1->fl_extension) != clist_count(flags2->fl_extension)) + return -1; + + for(cur1 = clist_begin(flags1->fl_extension) ; cur1 != NULL ; + cur1 = clist_next(cur1)) { + char * flag1; + clistiter * cur2; + int found; + + flag1 = clist_content(cur1); + + found = 0; + for(cur2 = clist_begin(flags2->fl_extension) ; cur2 != NULL ; + cur2 = clist_next(cur2)) { + char * flag2; + + flag2 = clist_content(cur2); + + if (strcasecmp(flag1, flag2) == 0) { + found = 1; + break; + } + } + + if (!found) + return -1; + } + + return flags1->fl_flags - flags2->fl_flags; +} + +int generic_cache_fields_read(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mailimf_fields ** result) +{ + int r; + int res; + size_t cur_token; + struct mailimf_fields * fields; + void * data; + size_t data_len; + + r = mail_cache_db_get(cache_db, keyname, strlen(keyname), &data, &data_len); + if (r != 0) { + res = MAIL_ERROR_CACHE_MISS; + goto err; + } + + r = mail_serialize_clear(mmapstr, &cur_token); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + if (mmap_string_append_len(mmapstr, data, data_len) == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailimf_cache_fields_read(mmapstr, &cur_token, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = fields; + + return MAIL_NO_ERROR; + + err: + return res; +} + +int generic_cache_fields_write(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mailimf_fields * fields) +{ + int r; + int res; + size_t cur_token; + + r = mail_serialize_clear(mmapstr, &cur_token); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_cache_fields_write(mmapstr, &cur_token, fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = mail_cache_db_put(cache_db, keyname, strlen(keyname), + mmapstr->str, mmapstr->len); + if (r != 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +int generic_cache_flags_read(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mail_flags ** result) +{ + int r; + int res; + size_t cur_token; + struct mail_flags * flags; + void * data; + size_t data_len; + + data = NULL; + data_len = 0; + r = mail_cache_db_get(cache_db, keyname, strlen(keyname), &data, &data_len); + if (r != 0) { + res = MAIL_ERROR_CACHE_MISS; + goto err; + } + + r = mail_serialize_clear(mmapstr, &cur_token); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + if (mmap_string_append_len(mmapstr, data, data_len) == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + flags = NULL; + r = generic_flags_read(mmapstr, &cur_token, &flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = flags; + + return MAIL_NO_ERROR; + + err: + return res; +} + +int generic_cache_flags_write(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mail_flags * flags) +{ + int r; + int res; + size_t cur_token; + + r = mail_serialize_clear(mmapstr, &cur_token); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = generic_flags_write(mmapstr, &cur_token, flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = mail_cache_db_put(cache_db, keyname, strlen(keyname), + mmapstr->str, mmapstr->len); + if (r != 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + +int generic_cache_delete(struct mail_cache_db * cache_db, + char * keyname) +{ + int r; + int res; + + r = mail_cache_db_del(cache_db, keyname, strlen(keyname)); + if (r != 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + diff --git a/Sources/libetpan/driver/tools/generic_cache.h b/Sources/libetpan/driver/tools/generic_cache.h new file mode 100644 index 00000000..b5858aa2 --- /dev/null +++ b/Sources/libetpan/driver/tools/generic_cache.h @@ -0,0 +1,109 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: generic_cache.h,v 1.18 2008/02/20 22:15:51 hoa Exp $ + */ + +#ifndef GENERIC_CACHE_H + +#define GENERIC_CACHE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "generic_cache_types.h" +#include "mailmessage_types.h" +#include "chash.h" +#include "carray.h" +#include "mail_cache_db_types.h" + +int generic_cache_create_dir(char * dirname); + +int generic_cache_store(char * filename, char * content, size_t length); +int generic_cache_read(char * filename, char ** result, size_t * result_len); + +int generic_cache_fields_read(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mailimf_fields ** result); + +int generic_cache_fields_write(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mailimf_fields * fields); + +int generic_cache_flags_read(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mail_flags ** result); + +int generic_cache_flags_write(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mail_flags * flags); + +int generic_cache_delete(struct mail_cache_db * cache_db, char * keyname); + +#if 0 +int generic_cache_fields_read(DB * dbp, MMAPString * mmapstr, + char * keyname, struct mailimf_fields ** result); + +int generic_cache_fields_write(DB * dbp, MMAPString * mmapstr, + char * keyname, struct mailimf_fields * fields); + +int generic_cache_flags_read(DB * dbp, MMAPString * mmapstr, + char * keyname, struct mail_flags ** result); + +int generic_cache_flags_write(DB * dbp, MMAPString * mmapstr, + char * keyname, struct mail_flags * flags); + +int generic_cache_delete(DB * dbp, char * keyname); +#endif + +struct mail_flags_store * mail_flags_store_new(void); + +void mail_flags_store_clear(struct mail_flags_store * flags_store); + +void mail_flags_store_free(struct mail_flags_store * flags_store); + +int mail_flags_store_set(struct mail_flags_store * flags_store, + mailmessage * msg); + +void mail_flags_store_sort(struct mail_flags_store * flags_store); + +struct mail_flags * +mail_flags_store_get(struct mail_flags_store * flags_store, uint32_t indx); + +int mail_flags_compare(struct mail_flags * flags1, struct mail_flags * flags2); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/tools/generic_cache_types.h b/Sources/libetpan/driver/tools/generic_cache_types.h new file mode 100644 index 00000000..bc30d4ea --- /dev/null +++ b/Sources/libetpan/driver/tools/generic_cache_types.h @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: generic_cache_types.h,v 1.6 2004/11/21 21:53:35 hoa Exp $ + */ + +#ifndef GENERIC_CACHE_TYPE_H + +#define GENERIC_CACHE_TYPE_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct mail_flags_store { + carray * fls_tab; + chash * fls_hash; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/tools/imfcache.c b/Sources/libetpan/driver/tools/imfcache.c new file mode 100644 index 00000000..f962a0f1 --- /dev/null +++ b/Sources/libetpan/driver/tools/imfcache.c @@ -0,0 +1,1430 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imfcache.c,v 1.20 2009/07/23 19:46:46 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "imfcache.h" + +#include +#include + +static int mailimf_cache_field_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_field * field); +static int mailimf_cache_orig_date_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_orig_date * date); +static int mailimf_cache_date_time_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_date_time * date_time); +static int mailimf_cache_from_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_from * from); +static int mailimf_cache_sender_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_sender * sender); +static int mailimf_cache_reply_to_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_reply_to * reply_to); +static int mailimf_cache_to_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_to * to); +static int mailimf_cache_cc_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_cc * to); +static int mailimf_cache_bcc_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_bcc * to); +static int mailimf_cache_message_id_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_message_id * message_id); +static int mailimf_cache_msg_id_list_write(MMAPString * mmapstr, size_t * indx, + clist * list); +static int mailimf_cache_in_reply_to_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_in_reply_to * + in_reply_to); +static int mailimf_cache_references_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_references * references); +static int mailimf_cache_subject_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_subject * subject); +static int mailimf_cache_address_list_write(MMAPString * mmapstr, + size_t * indx, + struct mailimf_address_list * + addr_list); +static int mailimf_cache_address_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_address * addr); +static int mailimf_cache_group_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_group * group); +static int mailimf_cache_mailbox_list_write(MMAPString * mmapstr, + size_t * indx, + struct mailimf_mailbox_list * mb_list); +static int mailimf_cache_mailbox_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_mailbox * mb); + + +static int mailimf_cache_field_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_field ** result); +static int mailimf_cache_orig_date_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_orig_date ** result); +static int mailimf_cache_date_time_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_date_time ** result); +static int mailimf_cache_from_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_from ** result); +static int mailimf_cache_sender_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_sender ** result); +static int mailimf_cache_reply_to_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_reply_to ** result); +static int mailimf_cache_to_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_to ** result); +static int mailimf_cache_cc_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_cc ** result); +static int mailimf_cache_bcc_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_bcc ** result); +static int mailimf_cache_message_id_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_message_id ** result); +static int mailimf_cache_msg_id_list_read(MMAPString * mmapstr, size_t * indx, + clist ** result); +static int +mailimf_cache_in_reply_to_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_in_reply_to ** result); + +static int mailimf_cache_references_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_references ** result); +static int mailimf_cache_subject_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_subject ** result); +static int mailimf_cache_address_list_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_address_list ** result); +static int mailimf_cache_address_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_address ** result); +static int mailimf_cache_group_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_group ** result); +static int +mailimf_cache_mailbox_list_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_mailbox_list ** result); +static int mailimf_cache_mailbox_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_mailbox ** result); + +enum { + CACHE_NULL_POINTER = 0, + CACHE_NOT_NULL = 1 +}; + +int mail_serialize_clear(MMAPString * mmapstr, size_t * indx) +{ + if (mmap_string_set_size(mmapstr, 0) == NULL) + return MAIL_ERROR_MEMORY; + + * indx = 0; + + return MAIL_NO_ERROR; +} + +int mail_serialize_write(MMAPString * mmapstr, size_t * indx, + char * buf, size_t size) +{ + if (mmap_string_append_len(mmapstr, buf, size) == NULL) + return MAIL_ERROR_MEMORY; + + * indx = * indx + size; + + return MAIL_NO_ERROR; +} + +int mail_serialize_read(MMAPString * mmapstr, size_t * indx, + char * buf, size_t size) +{ + size_t cur_token; + + cur_token = * indx; + + if (cur_token + size > mmapstr->len) + return MAIL_ERROR_STREAM; + + memcpy(buf, mmapstr->str + cur_token, size); + * indx = cur_token + size; + + return MAIL_NO_ERROR; +} + +int mailimf_cache_int_write(MMAPString * mmapstr, size_t * indx, + uint32_t value) +{ + unsigned char ch; + int r; + int i; + + for(i = 0 ; i < 4 ; i ++) { + ch = value % 256; + + r = mail_serialize_write(mmapstr, indx, (char *) &ch, 1); + if (r != MAIL_NO_ERROR) + return r; + value /= 256; + } + + return MAIL_NO_ERROR; +} + +int mailimf_cache_int_read(MMAPString * mmapstr, size_t * indx, + uint32_t * result) +{ + unsigned char ch; + uint32_t value; + int i; + int r; + + value = 0; + for(i = 0 ; i < 4 ; i ++) { + r = mail_serialize_read(mmapstr, indx, (char *) &ch, 1); + if (r != MAIL_NO_ERROR) + return r; + value = value | ch << (i << 3); + } + + * result = value; + + return MAIL_NO_ERROR; +} + + +int mailimf_cache_string_write(MMAPString * mmapstr, size_t * indx, + char * str, size_t length) +{ + int r; + + if (str == NULL) { + r = mailimf_cache_int_write(mmapstr, indx, CACHE_NULL_POINTER); + if (r != MAIL_NO_ERROR) + return r; + } + else { + r = mailimf_cache_int_write(mmapstr, indx, CACHE_NOT_NULL); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, indx, (uint32_t) length); + if (r != MAIL_NO_ERROR) + return r; + + if (length != 0) { + r = mail_serialize_write(mmapstr, indx, str, length); + if (r != MAIL_NO_ERROR) + return MAIL_ERROR_FILE; + } + } + + return MAIL_NO_ERROR; +} + +int mailimf_cache_string_read(MMAPString * mmapstr, size_t * indx, + char ** result) +{ + int r; + uint32_t length; + char * str; + uint32_t type; + + r = mailimf_cache_int_read(mmapstr, indx, &type); + if (r != MAIL_NO_ERROR) + return r; + + if (type == CACHE_NULL_POINTER) { + str = NULL; + } + else { + r = mailimf_cache_int_read(mmapstr, indx, &length); + if (r != MAIL_NO_ERROR) + return r; + + str = malloc(length + 1); + if (str == NULL) + return MAIL_ERROR_MEMORY; + + r = mail_serialize_read(mmapstr, indx, str, length); + if (r != MAIL_NO_ERROR) { + free(str); + return MAIL_ERROR_FILE; + } + + str[length] = 0; + } + + * result = str; + + return MAIL_NO_ERROR; +} + +int mailimf_cache_fields_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_fields * fields) +{ + clistiter * cur; + int r; + + r = mailimf_cache_int_write(mmapstr, indx, + clist_count(fields->fld_list)); + if (r != MAIL_NO_ERROR) + return r; + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + r = mailimf_cache_field_write(mmapstr, indx, clist_content(cur)); + if (r != MAIL_NO_ERROR) + return r; + } + + return MAIL_NO_ERROR; +} + +int mailimf_cache_fields_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_fields ** result) +{ + clist * list; + int r; + uint32_t count; + uint32_t i; + struct mailimf_fields * fields; + int res; + + r = mailimf_cache_int_read(mmapstr, indx, &count); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < count ; i++) { + struct mailimf_field * field; + + field = NULL; + r = mailimf_cache_field_read(mmapstr, indx, &field); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = fields; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + err: + return res; +} + + +static int mailimf_cache_field_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_field * field) +{ + int r; + + r = mailimf_cache_int_write(mmapstr, indx, field->fld_type); + if (r != MAIL_NO_ERROR) + return r; + + switch (field->fld_type) { + case MAILIMF_FIELD_ORIG_DATE: + r = mailimf_cache_orig_date_write(mmapstr, indx, + field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_FROM: + r = mailimf_cache_from_write(mmapstr, indx, + field->fld_data.fld_from); + break; + case MAILIMF_FIELD_SENDER: + r = mailimf_cache_sender_write(mmapstr, indx, + field->fld_data.fld_sender); + break; + case MAILIMF_FIELD_REPLY_TO: + r = mailimf_cache_reply_to_write(mmapstr, indx, + field->fld_data.fld_reply_to); + break; + case MAILIMF_FIELD_TO: + r = mailimf_cache_to_write(mmapstr, indx, + field->fld_data.fld_to); + break; + case MAILIMF_FIELD_CC: + r = mailimf_cache_cc_write(mmapstr, indx, + field->fld_data.fld_cc); + break; + case MAILIMF_FIELD_BCC: + r = mailimf_cache_bcc_write(mmapstr, indx, + field->fld_data.fld_bcc); + break; + case MAILIMF_FIELD_MESSAGE_ID: + r = mailimf_cache_message_id_write(mmapstr, indx, + field->fld_data.fld_message_id); + break; + case MAILIMF_FIELD_IN_REPLY_TO: + r = mailimf_cache_in_reply_to_write(mmapstr, indx, + field->fld_data.fld_in_reply_to); + break; + case MAILIMF_FIELD_REFERENCES: + r = mailimf_cache_references_write(mmapstr, indx, + field->fld_data.fld_references); + break; + case MAILIMF_FIELD_SUBJECT: + r = mailimf_cache_subject_write(mmapstr, indx, + field->fld_data.fld_subject); + break; + } + + return r; +} + + +static int mailimf_cache_field_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_field ** result) +{ + int r; + uint32_t type; + struct mailimf_orig_date * orig_date; + struct mailimf_from * from; + struct mailimf_sender * sender; + struct mailimf_to * to; + struct mailimf_reply_to * reply_to; + struct mailimf_cc * cc; + struct mailimf_bcc * bcc; + struct mailimf_message_id * message_id; + struct mailimf_in_reply_to * in_reply_to; + struct mailimf_references * references; + struct mailimf_subject * subject; + struct mailimf_field * field; + int res; + + orig_date = NULL; + from = NULL; + sender = NULL; + to = NULL; + reply_to = NULL; + cc = NULL; + bcc = NULL; + message_id = NULL; + in_reply_to = NULL; + references = NULL; + subject = NULL; + field = NULL; + + r = mailimf_cache_int_read(mmapstr, indx, &type); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + switch (type) { + case MAILIMF_FIELD_ORIG_DATE: + r = mailimf_cache_orig_date_read(mmapstr, indx, &orig_date); + break; + case MAILIMF_FIELD_FROM: + r = mailimf_cache_from_read(mmapstr, indx, &from); + break; + case MAILIMF_FIELD_SENDER: + r = mailimf_cache_sender_read(mmapstr, indx, &sender); + break; + case MAILIMF_FIELD_REPLY_TO: + r = mailimf_cache_reply_to_read(mmapstr, indx, &reply_to); + break; + case MAILIMF_FIELD_TO: + r = mailimf_cache_to_read(mmapstr, indx, &to); + break; + case MAILIMF_FIELD_CC: + r = mailimf_cache_cc_read(mmapstr, indx, &cc); + break; + case MAILIMF_FIELD_BCC: + r = mailimf_cache_bcc_read(mmapstr, indx, &bcc); + break; + case MAILIMF_FIELD_MESSAGE_ID: + r = mailimf_cache_message_id_read(mmapstr, indx, &message_id); + break; + case MAILIMF_FIELD_IN_REPLY_TO: + r = mailimf_cache_in_reply_to_read(mmapstr, indx, &in_reply_to); + break; + case MAILIMF_FIELD_REFERENCES: + r = mailimf_cache_references_read(mmapstr, indx, &references); + break; + case MAILIMF_FIELD_SUBJECT: + r = mailimf_cache_subject_read(mmapstr, indx, &subject); + break; + default: + r = MAIL_ERROR_INVAL; + break; + } + + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + field = mailimf_field_new(type, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, orig_date, from, sender, reply_to, + to, cc, bcc, message_id, + in_reply_to, references, + subject, NULL, NULL, NULL); + if (field == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + * result = field; + + return MAIL_NO_ERROR; + + free: + if (orig_date != NULL) + mailimf_orig_date_free(orig_date); + if (from != NULL) + mailimf_from_free(from); + if (sender != NULL) + mailimf_sender_free(sender); + if (reply_to != NULL) + mailimf_reply_to_free(reply_to); + if (to != NULL) + mailimf_to_free(to); + if (cc != NULL) + mailimf_cc_free(cc); + if (bcc != NULL) + mailimf_bcc_free(bcc); + if (message_id != NULL) + mailimf_message_id_free(message_id); + if (in_reply_to != NULL) + mailimf_in_reply_to_free(in_reply_to); + if (references != NULL) + mailimf_references_free(references); + if (subject != NULL) + mailimf_subject_free(subject); + err: + return res; +} + +static int mailimf_cache_orig_date_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_orig_date * date) +{ + return mailimf_cache_date_time_write(mmapstr, indx, date->dt_date_time); +} + +static int mailimf_cache_orig_date_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_orig_date ** result) +{ + int r; + struct mailimf_date_time * date_time; + struct mailimf_orig_date * orig_date; + + r = mailimf_cache_date_time_read(mmapstr, indx, &date_time); + if (r != MAIL_NO_ERROR) + return r; + + orig_date = mailimf_orig_date_new(date_time); + if (orig_date == NULL) { + mailimf_date_time_free(date_time); + return MAIL_ERROR_MEMORY; + } + + * result = orig_date; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_date_time_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_date_time * date_time) +{ + int r; + + r = mailimf_cache_int_write(mmapstr, indx, date_time->dt_day); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, indx, date_time->dt_month); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, indx, date_time->dt_year); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, indx, date_time->dt_hour); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, indx, date_time->dt_min); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, indx, date_time->dt_sec); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, indx, date_time->dt_zone); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_date_time_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_date_time ** result) +{ + int r; + uint32_t day; + uint32_t month; + uint32_t year; + uint32_t hour; + uint32_t min; + uint32_t sec; + uint32_t zone; + struct mailimf_date_time * date_time; + + r = mailimf_cache_int_read(mmapstr, indx, &day); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_read(mmapstr, indx, &month); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_read(mmapstr, indx, &year); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_read(mmapstr, indx, &hour); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_read(mmapstr, indx, &min); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_read(mmapstr, indx, &sec); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_read(mmapstr, indx, &zone); + if (r != MAIL_NO_ERROR) + return r; + + date_time = mailimf_date_time_new(day, month, year, hour, min, sec, zone); + if (date_time == NULL) + return MAIL_ERROR_MEMORY; + + * result = date_time; + + return MAIL_NO_ERROR; + +} + + +static int mailimf_cache_from_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_from * from) +{ + return mailimf_cache_mailbox_list_write(mmapstr, indx, from->frm_mb_list); +} + +static int mailimf_cache_from_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_from ** result) +{ + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + int r; + + r = mailimf_cache_mailbox_list_read(mmapstr, indx, &mb_list); + if (r != MAIL_NO_ERROR) + return r; + + from = mailimf_from_new(mb_list); + if (from == NULL) { + mailimf_mailbox_list_free(mb_list); + return MAIL_ERROR_MEMORY; + } + + * result = from; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_sender_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_sender * sender) +{ + return mailimf_cache_mailbox_write(mmapstr, indx, sender->snd_mb); +} + +static int mailimf_cache_sender_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_sender ** result) +{ + int r; + struct mailimf_mailbox * mb; + struct mailimf_sender * sender; + + r = mailimf_cache_mailbox_read(mmapstr, indx, &mb); + if (r != MAIL_NO_ERROR) + return r; + + sender = mailimf_sender_new(mb); + if (sender == NULL) { + mailimf_mailbox_free(mb); + return MAIL_ERROR_MEMORY; + } + + * result = sender; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_reply_to_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_reply_to * reply_to) +{ + return mailimf_cache_address_list_write(mmapstr, indx, + reply_to->rt_addr_list); +} + +static int mailimf_cache_reply_to_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_reply_to ** result) +{ + int r; + struct mailimf_address_list * addr_list; + struct mailimf_reply_to * reply_to; + + r = mailimf_cache_address_list_read(mmapstr, indx, &addr_list); + if (r != MAIL_NO_ERROR) + return r; + + reply_to = mailimf_reply_to_new(addr_list); + if (reply_to == NULL) { + mailimf_address_list_free(addr_list); + return MAIL_ERROR_MEMORY; + } + + * result = reply_to; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_to_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_to * to) +{ + return mailimf_cache_address_list_write(mmapstr, indx, to->to_addr_list); +} + +static int mailimf_cache_to_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_to ** result) +{ + int r; + struct mailimf_address_list * addr_list; + struct mailimf_to * to; + + r = mailimf_cache_address_list_read(mmapstr, indx, &addr_list); + if (r != MAIL_NO_ERROR) + return r; + + to = mailimf_to_new(addr_list); + if (to == NULL) { + mailimf_address_list_free(addr_list); + return MAIL_ERROR_MEMORY; + } + + * result = to; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_cc_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_cc * cc) +{ + return mailimf_cache_address_list_write(mmapstr, indx, cc->cc_addr_list); +} + +static int mailimf_cache_cc_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_cc ** result) +{ + int r; + struct mailimf_address_list * addr_list; + struct mailimf_cc * cc; + + r = mailimf_cache_address_list_read(mmapstr, indx, &addr_list); + if (r != MAIL_NO_ERROR) + return r; + + cc = mailimf_cc_new(addr_list); + if (cc == NULL) { + mailimf_address_list_free(addr_list); + return MAIL_ERROR_MEMORY; + } + + * result = cc; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_bcc_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_bcc * bcc) +{ + return mailimf_cache_address_list_write(mmapstr, indx, bcc->bcc_addr_list); +} + +static int mailimf_cache_bcc_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_bcc ** result) +{ + int r; + struct mailimf_address_list * addr_list; + struct mailimf_bcc * bcc; + + r = mailimf_cache_address_list_read(mmapstr, indx, &addr_list); + if (r != MAIL_NO_ERROR) + return r; + + bcc = mailimf_bcc_new(addr_list); + if (bcc == NULL) { + mailimf_address_list_free(addr_list); + return MAIL_ERROR_MEMORY; + } + + * result = bcc; + + return MAIL_NO_ERROR; +} + +static int +mailimf_cache_message_id_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_message_id * message_id) +{ + return mailimf_cache_string_write(mmapstr, indx, + message_id->mid_value, strlen(message_id->mid_value)); +} + +static int mailimf_cache_message_id_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_message_id ** result) +{ + struct mailimf_message_id * message_id; + char * str; + int r; + + r = mailimf_cache_string_read(mmapstr, indx, &str); + if (r != MAIL_NO_ERROR) + return r; + + message_id = mailimf_message_id_new(str); + if (message_id == NULL) { + free(str); + return MAIL_ERROR_MEMORY; + } + + * result = message_id; + + return MAIL_NO_ERROR; +} + +static int +mailimf_cache_msg_id_list_write(MMAPString * mmapstr, size_t * indx, + clist * list) +{ + clistiter * cur; + int r; + + r = mailimf_cache_int_write(mmapstr, indx, clist_count(list)); + if (r != MAIL_NO_ERROR) + return r; + + for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) { + char * msgid; + + msgid = clist_content(cur); + + r = mailimf_cache_string_write(mmapstr, indx, msgid, strlen(msgid)); + if (r != MAIL_NO_ERROR) + return r; + } + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_msg_id_list_read(MMAPString * mmapstr, size_t * indx, + clist ** result) +{ + clist * list; + int r; + uint32_t count; + uint32_t i; + int res; + + r = mailimf_cache_int_read(mmapstr, indx, &count); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < count ; i++) { + char * msgid; + + r = mailimf_cache_string_read(mmapstr, indx, &msgid); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = clist_append(list, msgid); + if (r < 0) { + free(msgid); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + * result = list; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + err: + return res; +} + +static int +mailimf_cache_in_reply_to_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_in_reply_to * in_reply_to) +{ + return mailimf_cache_msg_id_list_write(mmapstr, indx, + in_reply_to->mid_list); +} + +static int mailimf_cache_in_reply_to_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_in_reply_to ** result) +{ + int r; + clist * msg_id_list; + struct mailimf_in_reply_to * in_reply_to; + + r = mailimf_cache_msg_id_list_read(mmapstr, indx, &msg_id_list); + if (r != MAIL_NO_ERROR) + return r; + + in_reply_to = mailimf_in_reply_to_new(msg_id_list); + if (in_reply_to == NULL) { + clist_foreach(msg_id_list, (clist_func) free, NULL); + clist_free(msg_id_list); + return MAIL_ERROR_MEMORY; + } + + * result = in_reply_to; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_references_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_references * references) +{ + return mailimf_cache_msg_id_list_write(mmapstr, indx, + references->mid_list); +} + +static int mailimf_cache_references_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_references ** result) +{ + int r; + clist * msg_id_list; + struct mailimf_references * references; + + r = mailimf_cache_msg_id_list_read(mmapstr, indx, &msg_id_list); + if (r != MAIL_NO_ERROR) + return r; + + references = mailimf_references_new(msg_id_list); + if (references == NULL) { + clist_foreach(msg_id_list, (clist_func) free, NULL); + clist_free(msg_id_list); + return MAIL_ERROR_MEMORY; + } + + * result = references; + + return MAIL_NO_ERROR; +} + + +static int mailimf_cache_subject_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_subject * subject) +{ + return mailimf_cache_string_write(mmapstr, indx, + subject->sbj_value, strlen(subject->sbj_value)); +} + +static int mailimf_cache_subject_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_subject ** result) +{ + char * str; + struct mailimf_subject * subject; + int r; + + r = mailimf_cache_string_read(mmapstr, indx, &str); + if (r != MAIL_NO_ERROR) + return r; + + if (str == NULL) { + str = strdup(""); + if (str == NULL) + return MAIL_ERROR_MEMORY; + } + + subject = mailimf_subject_new(str); + if (subject == NULL) { + free(str); + return MAIL_ERROR_MEMORY; + } + + * result = subject; + + return MAIL_NO_ERROR; +} + + +static int +mailimf_cache_address_list_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_address_list * addr_list) +{ + clistiter * cur; + int r; + + if (addr_list == NULL) { + r = mailimf_cache_int_write(mmapstr, indx, CACHE_NULL_POINTER); + if (r != MAIL_NO_ERROR) + return r; + } + else { + r = mailimf_cache_int_write(mmapstr, indx, CACHE_NOT_NULL); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, indx, + clist_count(addr_list->ad_list)); + if (r != MAIL_NO_ERROR) + return r; + + for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_address * addr; + + addr = clist_content(cur); + + r = mailimf_cache_address_write(mmapstr, indx, addr); + if (r != MAIL_NO_ERROR) + return r; + } + } + + return MAIL_NO_ERROR; +} + +static int +mailimf_cache_address_list_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_address_list ** result) +{ + struct mailimf_address_list * addr_list; + uint32_t count; + uint32_t i; + int r; + clist * list; + int res; + uint32_t type; + + r = mailimf_cache_int_read(mmapstr, indx, &type); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + if (type == CACHE_NULL_POINTER) { + * result = NULL; + return MAIL_NO_ERROR; + } + + r = mailimf_cache_int_read(mmapstr, indx, &count); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < count ; i++) { + struct mailimf_address * addr; + + r = mailimf_cache_address_read(mmapstr, indx, &addr); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(list, addr); + if (r < 0) { + mailimf_address_free(addr); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + addr_list = mailimf_address_list_new(list); + if (addr_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = addr_list; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_address_free, NULL); + clist_free(list); + err: + return res; +} + +static int mailimf_cache_address_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_address * addr) +{ + int r; + + r = mailimf_cache_int_write(mmapstr, indx, addr->ad_type); + if (r != MAIL_NO_ERROR) + return r; + + switch(addr->ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + r = mailimf_cache_mailbox_write(mmapstr, indx, addr->ad_data.ad_mailbox); + if (r != MAIL_NO_ERROR) + return r; + + break; + + case MAILIMF_ADDRESS_GROUP: + r = mailimf_cache_group_write(mmapstr, indx, addr->ad_data.ad_group); + if (r != MAIL_NO_ERROR) + return r; + + break; + } + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_address_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_address ** result) +{ + uint32_t type; + int r; + struct mailimf_mailbox * mailbox; + struct mailimf_group * group; + struct mailimf_address * addr; + + r = mailimf_cache_int_read(mmapstr, indx, &type); + if (r != MAIL_NO_ERROR) + return r; + + mailbox = NULL; + group = NULL; + + switch (type) { + case MAILIMF_ADDRESS_MAILBOX: + r = mailimf_cache_mailbox_read(mmapstr, indx, &mailbox); + if (r != MAIL_NO_ERROR) + return r; + + break; + + case MAILIMF_ADDRESS_GROUP: + r = mailimf_cache_group_read(mmapstr, indx, &group); + if (r != MAIL_NO_ERROR) + return r; + + break; + } + + addr = mailimf_address_new(type, mailbox, group); + if (addr == NULL) + goto free; + + * result = addr; + + return MAIL_NO_ERROR; + + free: + if (mailbox != NULL) + mailimf_mailbox_free(mailbox); + if (group != NULL) + mailimf_group_free(group); + return MAIL_ERROR_MEMORY; +} + +static int mailimf_cache_group_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_group * group) +{ + int r; + + r = mailimf_cache_string_write(mmapstr, indx, group->grp_display_name, + strlen(group->grp_display_name)); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_mailbox_list_write(mmapstr, indx, group->grp_mb_list); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_group_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_group ** result) +{ + int r; + char * display_name; + struct mailimf_mailbox_list * mb_list; + struct mailimf_group * group; + int res; + + r = mailimf_cache_string_read(mmapstr, indx, &display_name); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_cache_mailbox_list_read(mmapstr, indx, &mb_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_dsp_name; + } + + group = mailimf_group_new(display_name, mb_list); + if (group == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_mb_list; + } + + * result = group; + + return MAIL_NO_ERROR; + + free_mb_list: + mailimf_mailbox_list_free(mb_list); + free_dsp_name: + free(display_name); + err: + return res; +} + +static int +mailimf_cache_mailbox_list_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_mailbox_list * mb_list) +{ + clistiter * cur; + int r; + + if (mb_list == NULL) { + r = mailimf_cache_int_write(mmapstr, indx, CACHE_NULL_POINTER); + if (r != MAIL_NO_ERROR) + return r; + } + else { + r = mailimf_cache_int_write(mmapstr, indx, CACHE_NOT_NULL); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, indx, + clist_count(mb_list->mb_list)); + if (r != MAIL_NO_ERROR) + return r; + + for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = clist_content(cur); + + r = mailimf_cache_mailbox_write(mmapstr, indx, mb); + if (r != MAIL_NO_ERROR) + return r; + } + } + + return MAIL_NO_ERROR; +} + +static int +mailimf_cache_mailbox_list_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_mailbox_list ** result) +{ + clist * list; + int r; + uint32_t count; + uint32_t i; + struct mailimf_mailbox_list * mb_list; + int res; + uint32_t type; + + r = mailimf_cache_int_read(mmapstr, indx, &type); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + if (type == CACHE_NULL_POINTER) { + * result = NULL; + return MAIL_NO_ERROR; + } + + r = mailimf_cache_int_read(mmapstr, indx, &count); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < count ; i++) { + struct mailimf_mailbox * mb; + + r = mailimf_cache_mailbox_read(mmapstr, indx, &mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(list, mb); + if (r < 0) { + mailimf_mailbox_free(mb); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + mb_list = mailimf_mailbox_list_new(list); + if (mb_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = mb_list; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL); + clist_free(list); + err: + return res; +} + +static int mailimf_cache_mailbox_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_mailbox * mb) +{ + int r; + + if (mb->mb_display_name) { + r = mailimf_cache_string_write(mmapstr, indx, + mb->mb_display_name, strlen(mb->mb_display_name)); + if (r != MAIL_NO_ERROR) + return r; + } + else { + r = mailimf_cache_string_write(mmapstr, indx, NULL, 0); + if (r != MAIL_NO_ERROR) + return r; + } + + r = mailimf_cache_string_write(mmapstr, indx, + mb->mb_addr_spec, strlen(mb->mb_addr_spec)); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_mailbox_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_mailbox ** result) +{ + int r; + char * dsp_name; + char * addr_spec; + struct mailimf_mailbox * mb; + + dsp_name = NULL; + + r = mailimf_cache_string_read(mmapstr, indx, &dsp_name); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_string_read(mmapstr, indx, &addr_spec); + if (r != MAIL_NO_ERROR) + goto free_dsp_name; + + mb = mailimf_mailbox_new(dsp_name, addr_spec); + if (mb == NULL) + goto free_addr; + + * result = mb; + + return MAIL_NO_ERROR; + + free_addr: + free(addr_spec); + free_dsp_name: + if (dsp_name != NULL) + free(dsp_name); + return MAIL_ERROR_MEMORY; +} diff --git a/Sources/libetpan/driver/tools/imfcache.h b/Sources/libetpan/driver/tools/imfcache.h new file mode 100644 index 00000000..8122822f --- /dev/null +++ b/Sources/libetpan/driver/tools/imfcache.h @@ -0,0 +1,75 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imfcache.h,v 1.10 2008/02/20 22:15:51 hoa Exp $ + */ + +#ifndef IMFCACHE_H + +#define IMFCACHE_H + +#include +#include "mailimf.h" +#include "maildriver_types.h" +#include "mmapstring.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int mail_serialize_clear(MMAPString * mmapstr, size_t * indx); + +int mail_serialize_write(MMAPString * mmapstr, size_t * indx, + char * buf, size_t size); + +int mail_serialize_read(MMAPString * mmapstr, size_t * indx, + char * buf, size_t size); + +int mailimf_cache_int_write(MMAPString * mmapstr, size_t * indx, + uint32_t value); +int mailimf_cache_string_write(MMAPString * mmapstr, size_t * indx, + char * str, size_t length); +int mailimf_cache_int_read(MMAPString * mmapstr, size_t * indx, + uint32_t * result); +int mailimf_cache_string_read(MMAPString * mmapstr, size_t * indx, + char ** result); + +int mailimf_cache_fields_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_fields * fields); +int mailimf_cache_fields_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_fields ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/tools/mailthread.c b/Sources/libetpan/driver/tools/mailthread.c new file mode 100644 index 00000000..4b3bb62a --- /dev/null +++ b/Sources/libetpan/driver/tools/mailthread.c @@ -0,0 +1,1684 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailthread.c,v 1.32 2008/02/20 22:35:48 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailthread.h" +#include "mailthread_types.h" + +#include +#include +#include +#include + +#include "mail.h" +#include "chash.h" +#include "carray.h" +#include "clist.h" +#include "mailmessage.h" +#include "timeutils.h" +#ifdef WIN32 +# include "win_etpan.h" +#endif + +/* SEB */ +#ifdef NO_MACROS +# define inline +#endif + +static inline char * get_msg_id(mailmessage * msg) +{ + if (msg->msg_single_fields.fld_message_id != NULL) + return msg->msg_single_fields.fld_message_id->mid_value; + else + return NULL; +} + +static inline clist * get_ref(mailmessage * msg) +{ + if (msg->msg_single_fields.fld_references != NULL) + return msg->msg_single_fields.fld_references->mid_list; + else + return NULL; +} + +static inline clist * get_in_reply_to(mailmessage * msg) +{ + if (msg->msg_single_fields.fld_in_reply_to != NULL) + return msg->msg_single_fields.fld_in_reply_to->mid_list; + else + return NULL; +} + +static inline int skip_subj_blob(char * subj, size_t * begin, + size_t length) +{ + /* subj-blob = "[" *BLOBCHAR "]" *WSP */ + size_t cur_token; + + cur_token = * begin; + + if (subj[cur_token] != '[') + return FALSE; + + cur_token ++; + + while (1) { + if (cur_token >= length) + return FALSE; + + if (subj[cur_token] == '[') + return FALSE; + + if (subj[cur_token] == ']') + break; + + cur_token ++; + } + + cur_token ++; + + while (1) { + if (cur_token >= length) + break; + + if (subj[cur_token] != ' ') + break; + + cur_token ++; + } + + * begin = cur_token; + + return TRUE; +} + +static inline int skip_subj_refwd(char * subj, size_t * begin, + size_t length) +{ + /* subj-refwd = ("re" / ("fw" ["d"])) *WSP [subj-blob] ":" */ + size_t cur_token; + int prefix; + + cur_token = * begin; + + prefix = FALSE; + if (length >= 3) { + if (strncasecmp(subj + cur_token, "fwd", 3) == 0) { + cur_token += 3; + prefix = TRUE; + } + } + if (!prefix) { + if (length >= 2) { + if (strncasecmp(subj + cur_token, "fw", 2) == 0) { + cur_token += 2; + prefix = TRUE; + } + else if (strncasecmp(subj + cur_token, "re", 2) == 0) { + cur_token += 2; + prefix = TRUE; + } + } + } + + if (!prefix) + return FALSE; + + while (1) { + if (cur_token >= length) + break; + + if (subj[cur_token] != ' ') + break; + + cur_token ++; + } + + skip_subj_blob(subj, &cur_token, length); + + if (subj[cur_token] != ':') + return FALSE; + + cur_token ++; + + * begin = cur_token; + + return TRUE; +} + +static inline int skip_subj_leader(struct mailmessage_tree * tree, + char * subj, size_t * begin, + size_t length) +{ + size_t cur_token; + + cur_token = * begin; + + /* subj-leader = (*subj-blob subj-refwd) / WSP */ + + if (subj[cur_token] == ' ') { + cur_token ++; + } + else { + while (cur_token < length) { + if (!skip_subj_blob(subj, &cur_token, length)) + break; + } + if (!skip_subj_refwd(subj, &cur_token, length)) + return FALSE; + tree->node_is_reply = TRUE; + } + + * begin = cur_token; + + return TRUE; +} + + +static char * extract_subject(char * default_from, + struct mailmessage_tree * tree, + char * str) +{ + char * subj; + char * cur; + char * write_pos; + size_t len; + size_t begin; + + char * decoded; + size_t cur_token; + + int do_repeat_5; + int do_repeat_6; + int r; + + /* + (1) Convert any RFC 2047 encoded-words in the subject to + UTF-8. + */ + + decoded = NULL; + + cur_token = 0; + r = mailmime_encoded_phrase_parse(default_from, str, strlen(str), + &cur_token, "utf-8", + &decoded); + + if (r == MAILIMF_NO_ERROR) { + subj = decoded; + } + else + subj = strdup(str); + + if (subj == NULL) + return NULL; + + len = strlen(subj); + + /* + Convert all tabs and continuations to space. + Convert all multiple spaces to a single space. + */ + + cur = subj; + write_pos = subj; + while (* cur != '\0') { + int cont; + + switch (* cur) { + case '\t': + case '\r': + case '\n': + cont = TRUE; + + cur ++; + while (* cur && cont) { + switch (* cur) { + case '\t': + case '\r': + case '\n': + cont = TRUE; + break; + default: + cont = FALSE; + break; + } + cur ++; + } + + * write_pos = ' '; + write_pos ++; + + break; + + default: + * write_pos = * cur; + write_pos ++; + + cur ++; + + break; + } + } + * write_pos = '\0'; + + begin = 0; + + do { + do_repeat_6 = FALSE; + + /* + (2) Remove all trailing text of the subject that matches + the subj-trailer ABNF, repeat until no more matches are + possible. + */ + + while (len > 0) { + /* subj-trailer = "(fwd)" / WSP */ + if (subj[len - 1] == ' ') { + subj[len - 1] = '\0'; + len --; + } + else { + if (len < 5) + break; + + if (strncasecmp(subj + len - 5, "(fwd)", 5) != 0) + break; + + subj[len - 5] = '\0'; + len -= 5; + tree->node_is_reply = TRUE; + } + } + + do { + size_t saved_begin; + + do_repeat_5 = FALSE; + + /* + (3) Remove all prefix text of the subject that matches the + subj-leader ABNF. + */ + + if (skip_subj_leader(tree, subj, &begin, len)) + do_repeat_5 = TRUE; + + /* + (4) If there is prefix text of the subject that matches the + subj-blob ABNF, and removing that prefix leaves a non-empty + subj-base, then remove the prefix text. + */ + + saved_begin = begin; + if (skip_subj_blob(subj, &begin, len)) { + if (begin == len) { + /* this will leave a empty subject base */ + begin = saved_begin; + } + else + do_repeat_5 = TRUE; + } + + /* + (5) Repeat (3) and (4) until no matches remain. + Note: it is possible to defer step (2) until step (6), + but this requires checking for subj-trailer in step (4). + */ + + } + while (do_repeat_5); + + /* + (6) If the resulting text begins with the subj-fwd-hdr ABNF + and ends with the subj-fwd-trl ABNF, remove the + subj-fwd-hdr and subj-fwd-trl and repeat from step (2). + */ + + if ((len >= 5) && (strncasecmp(subj + begin, "[fwd:", 5) == 0)) { + begin += 5; + + if (subj[len - 1] == ']') { + tree->node_is_reply = TRUE; + + subj[len - 1] = '\0'; + len --; + do_repeat_6 = TRUE; + } + } + + } + while (do_repeat_6); + + /* + (7) The resulting text is the "base subject" used in + threading. + */ + + /* convert to upper case */ + + cur = subj + begin; + write_pos = subj; + + while (* cur != '\0') { + * write_pos = (char) toupper((unsigned char) * cur); + cur ++; + write_pos ++; + } + * write_pos = '\0'; + + return subj; +} + +static int get_extracted_subject(char * default_from, + struct mailmessage_tree * tree, + char ** result) +{ + if (tree->node_msg->msg_single_fields.fld_subject != NULL) { + char * subj; + + subj = extract_subject(default_from, + tree, tree->node_msg->msg_single_fields.fld_subject->sbj_value); + if (subj == NULL) + return MAIL_ERROR_MEMORY; + + * result = subj; + + return MAIL_NO_ERROR; + } + + return MAIL_ERROR_SUBJECT_NOT_FOUND; +} + +static int get_thread_subject(char * default_from, + struct mailmessage_tree * tree, + char ** result) +{ + char * thread_subject; + int r; + unsigned int i; + + if (tree->node_msg != NULL) { + if (tree->node_msg->msg_fields != NULL) { + r = get_extracted_subject(default_from, tree, &thread_subject); + + if (r != MAIL_NO_ERROR) + return r; + + * result = thread_subject; + return MAIL_NO_ERROR; + } + } + + for(i = 0 ; i < carray_count(tree->node_children) ; i ++) { + struct mailmessage_tree * child; + + child = carray_get(tree->node_children, i); + + r = get_thread_subject(default_from, child, &thread_subject); + + switch (r) { + case MAIL_NO_ERROR: + * result = thread_subject; + return MAIL_NO_ERROR; + + case MAIL_ERROR_SUBJECT_NOT_FOUND: + /* do nothing */ + break; + + default: + return r; + } + } + + return MAIL_ERROR_SUBJECT_NOT_FOUND; +} + + + +static inline time_t get_date(mailmessage * msg) +{ + struct tm tmval; + time_t timeval; + struct mailimf_date_time * date_time; + + if (msg->msg_single_fields.fld_orig_date == NULL) + return (time_t) -1; + + date_time = msg->msg_single_fields.fld_orig_date->dt_date_time; + + tmval.tm_sec = date_time->dt_sec; + tmval.tm_min = date_time->dt_min; + tmval.tm_hour = date_time->dt_hour; + tmval.tm_sec = date_time->dt_sec; + tmval.tm_mday = date_time->dt_day; + tmval.tm_mon = date_time->dt_month - 1; + tmval.tm_year = date_time->dt_year - 1900; + + timeval = mail_mkgmtime(&tmval); + + timeval -= date_time->dt_zone * 36; + + return timeval; +} + +static inline int is_descendant(struct mailmessage_tree * node, + struct mailmessage_tree * maybe_child) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(node->node_children) ; i++) { + struct mailmessage_tree * tree; + + tree = carray_get(node->node_children, i); + if (tree == maybe_child) + return TRUE; + if (carray_count(tree->node_children) != 0) + if (is_descendant(tree, maybe_child)) + return TRUE; + } + + return FALSE; +} + +static int delete_dummy(carray * rootlist, carray * sibling_list, + unsigned int cur, unsigned int * pnext) +{ + struct mailmessage_tree * env_tree; + int res; + int r; + unsigned int cur_child; + unsigned int next; + + env_tree = carray_get(sibling_list, cur); + + cur_child = 0; + while (cur_child < carray_count(env_tree->node_children)) { + delete_dummy(rootlist, env_tree->node_children, cur_child, &cur_child); + } + + if (env_tree->node_msg == NULL) { + if (carray_count(env_tree->node_children) == 0) { + + /* If it is a dummy message with NO children, delete it. */ + mailmessage_tree_free(env_tree); + carray_delete(sibling_list, cur); + next = cur; + } + else { + /* If it is a dummy message with children, delete it, but + promote its children to the current level. */ + + /* + Do not promote the children if doing so would make them + children of the root, unless there is only one child. + */ + + cur_child = 0; + if ((sibling_list != rootlist) || + (carray_count(env_tree->node_children) == 1)) { + while (cur_child < carray_count(env_tree->node_children)) { + struct mailmessage_tree * child; + + child = carray_get(env_tree->node_children, cur_child); + r = carray_add(sibling_list, child, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + /* set new parent of the children */ + child->node_parent = env_tree->node_parent; + + carray_delete(env_tree->node_children, cur_child); + } + mailmessage_tree_free(env_tree); + carray_delete(sibling_list, cur); + next = cur; + } + else + next = cur + 1; + } + } + else + next = cur + 1; + + * pnext = next; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static inline time_t tree_get_date(struct mailmessage_tree * tree) +{ + if (tree->node_msg != NULL) { + return tree->node_date; + } + else { + struct mailmessage_tree * subtree; + + if (carray_count(tree->node_children) == 0) + return (time_t) -1; + + subtree = carray_get(tree->node_children, 0); + + return subtree->node_date; + } +} + +static inline uint32_t tree_get_index(struct mailmessage_tree * tree) +{ + if (tree->node_msg == NULL) + return 0; + + return tree->node_msg->msg_index; +} + +int mailthread_tree_timecomp(struct mailmessage_tree ** ptree1, + struct mailmessage_tree ** ptree2) +{ + time_t date1; + time_t date2; + + date1 = tree_get_date(* ptree1); + date2 = tree_get_date(* ptree2); + + if ((date1 == (time_t) -1) || (date2 == (time_t) -1)) { + uint32_t index1; + uint32_t index2; + + index1 = tree_get_index(* ptree1); + index2 = tree_get_index(* ptree2); + return (int) ((long) index1 - (long) index2); + } + + return (int) ((long) date1 - (long) date2); +} + +static int tree_subj_time_comp(struct mailmessage_tree ** ptree1, + struct mailmessage_tree ** ptree2) +{ + char * subj1; + char * subj2; + time_t date1; + time_t date2; + int r; + + subj1 = (* ptree1)->node_base_subject; + subj2 = (* ptree2)->node_base_subject; + + if ((subj1 != NULL) && (subj2 != NULL)) + r = strcmp(subj1, subj2); + else { + if ((subj1 == NULL) && (subj2 == NULL)) + r = 0; + else if (subj1 == NULL) + r = -1; + else /* subj2 == NULL */ + r = 1; + } + + if (r != 0) + return r; + + date1 = (* ptree1)->node_date; + date2 = (* ptree2)->node_date; + + if ((date1 == (time_t) -1) || (date2 == (time_t) -1)) + return ((int32_t) (* ptree1)->node_msg->msg_index) - + ((int32_t) (* ptree2)->node_msg->msg_index); + + return (int) ((long) date1 - (long) date2); +} + + + +int mail_thread_sort(struct mailmessage_tree * tree, + int (* comp_func)(struct mailmessage_tree **, + struct mailmessage_tree **), + int sort_sub) +{ + unsigned int cur; + int r; + int res; + + for(cur = 0 ; cur < carray_count(tree->node_children) ; cur ++) { + struct mailmessage_tree * subtree; + + subtree = carray_get(tree->node_children, cur); + + if (sort_sub) { + r = mail_thread_sort(subtree, comp_func, sort_sub); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + } + + qsort(carray_data(tree->node_children), carray_count(tree->node_children), + sizeof(struct mailmessage_tree *), + (int (*)(const void *, const void *)) comp_func); + + return MAIL_NO_ERROR; + + err: + return res; +} + + +static int +mail_build_thread_references(char * default_from, + struct mailmessage_list * env_list, + struct mailmessage_tree ** result, + int use_subject, + int (* comp_func)(struct mailmessage_tree **, + struct mailmessage_tree **)) +{ + int r; + int res; + chash * msg_id_hash; + unsigned int cur; + struct mailmessage_tree * root; + carray * rootlist; + carray * msg_list; + unsigned int i; + chash * subject_hash; + + msg_id_hash = chash_new(128, CHASH_COPYNONE); + if (msg_id_hash == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + root = mailmessage_tree_new(NULL, (time_t) -1, NULL); + if (root == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_hash; + } + rootlist = root->node_children; + + msg_list = carray_new(128); + if (msg_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_root; + } + + /* collect message-ID */ + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + char * msgid; + struct mailmessage_tree * env_tree; + chashdatum hashkey; + chashdatum hashdata; + chashdatum hashold; + time_t date; + + msg = carray_get(env_list->msg_tab, i); + + if (msg == NULL) + continue; + + if (msg->msg_fields != NULL) { + msgid = get_msg_id(msg); + + if (msgid == NULL) { + msgid = mailimf_get_message_id(); + } + else { + hashkey.data = msgid; + hashkey.len = (unsigned int) strlen(msgid); + + if (chash_get(msg_id_hash, &hashkey, &hashdata) == 0) + msgid = mailimf_get_message_id(); + else + msgid = strdup(msgid); + } + + if (msgid == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + date = get_date(msg); + + env_tree = mailmessage_tree_new(msgid, date, msg); + if (env_tree == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = carray_add(msg_list, env_tree, NULL); + if (r < 0) { + mailmessage_tree_free(env_tree); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + hashkey.data = msgid; + hashkey.len = (unsigned int) strlen(msgid); + + hashdata.data = env_tree; + hashdata.len = 0; + + r = chash_set(msg_id_hash, &hashkey, &hashdata, &hashold); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + /* (1) for all messages */ + + for(cur = 0 ; cur < carray_count(msg_list) ; cur ++) { + struct mailmessage_tree * env_tree; + mailmessage * msg; + clist * ref; + + env_tree = carray_get(msg_list, cur); + + msg = env_tree->node_msg; + + ref = NULL; + if (msg != NULL) { + ref = get_ref(msg); + if (ref == NULL) + ref = get_in_reply_to(msg); + } + + /* (A) Using the Message IDs in the message's references, link + the corresponding messages (those whose Message-ID header + line contains the given reference Message ID) together as + parent/child. + */ + + if (ref != NULL) { + /* try to start a tree */ + + clistiter * cur_ref; + chashdatum hashkey; + chashdatum hashdata; + chashdatum hashold; + struct mailmessage_tree * env_cur_tree; + struct mailmessage_tree * last_env_cur_tree; + + env_cur_tree = NULL; + for(cur_ref = clist_begin(ref) ; cur_ref != NULL ; + cur_ref = clist_next(cur_ref)) { + char * msgid; + + last_env_cur_tree = env_cur_tree; + + msgid = clist_content(cur_ref); + + hashkey.data = msgid; + hashkey.len = (unsigned int) strlen(msgid); + + r = chash_get(msg_id_hash, &hashkey, &hashdata); + if (r < 0) { + /* not found, create a dummy message */ + msgid = strdup(msgid); + if (msgid == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + env_cur_tree = mailmessage_tree_new(msgid, (time_t) -1, NULL); + if (env_cur_tree == NULL) { + free(msgid); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = carray_add(msg_list, env_cur_tree, NULL); + if (r < 0) { + mailmessage_tree_free(env_cur_tree); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + hashkey.data = msgid; + hashkey.len = (unsigned int) strlen(msgid); + + hashdata.data = env_cur_tree; + hashdata.len = 0; + + r = chash_set(msg_id_hash, &hashkey, &hashdata, &hashold); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + else { + env_cur_tree = hashdata.data; + } + + if (last_env_cur_tree != NULL) { + if (env_cur_tree->node_parent == NULL) { + /* make it one child */ + if (env_cur_tree != last_env_cur_tree) { + if (!is_descendant(env_cur_tree, last_env_cur_tree)) { + /* set parent */ + env_cur_tree->node_parent = last_env_cur_tree; + r = carray_add(last_env_cur_tree->node_children, + env_cur_tree, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + } + } + } + + /* (B) Create a parent/child link between the last reference + (or NIL if there are no references) and the current message. + If the current message already has a parent, it is probably + the result of a truncated References header line, so break + the current parent/child link before creating the new + correct one. + */ + + last_env_cur_tree = env_cur_tree; + + if (last_env_cur_tree != NULL) { + if (env_tree->node_parent == NULL) { + if (last_env_cur_tree != env_tree) { + if (!is_descendant(env_tree, last_env_cur_tree)) { + /* set parent */ + env_tree->node_parent = last_env_cur_tree; + r = carray_add(last_env_cur_tree->node_children, env_tree, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + } + } + } + } + + chash_free(msg_id_hash); + msg_id_hash = NULL; + + /* (2) Gather together all of the messages that have no parents + and make them all children (siblings of one another) of a dummy + parent (the "root"). + */ + + for(cur = 0 ; cur < carray_count(msg_list) ; cur ++) { + struct mailmessage_tree * env_tree; + + env_tree = carray_get(msg_list, cur); + if (env_tree->node_parent == NULL) { + r = carray_add(rootlist, env_tree, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + /* set parent */ + env_tree->node_parent = root; + } + } + + carray_free(msg_list); + msg_list = NULL; + + /* (3) Prune dummy messages from the thread tree. + */ + + cur = 0; + while (cur < carray_count(rootlist)) { + r = delete_dummy(rootlist, rootlist, cur, &cur); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + } + + /* (4) Sort the messages under the root (top-level siblings only) + by sent date. + */ + + r = mail_thread_sort(root, mailthread_tree_timecomp, FALSE); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + if (use_subject) { + + /* (5) Gather together messages under the root that have the same + extracted subject text. + + (A) Create a table for associating extracted subjects with + messages. + */ + + subject_hash = chash_new(128, CHASH_COPYVALUE); + if (subject_hash == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + /* + (B) Populate the subject table with one message per + extracted subject. For each child of the root: + */ + + for(cur = 0 ; cur < carray_count(rootlist) ; cur ++) { + struct mailmessage_tree * env_tree; + chashdatum key; + chashdatum data; + char * base_subject; + + env_tree = carray_get(rootlist, cur); + + /* + (i) Find the subject of this thread by extracting the + base subject from the current message, or its first child + if the current message is a dummy. + */ + + r = get_thread_subject(default_from, env_tree, &base_subject); + + /* + (ii) If the extracted subject is empty, skip this + message. + */ + + if (r == MAIL_ERROR_SUBJECT_NOT_FOUND) { + /* no subject found */ + continue; + } + else if (r == MAIL_NO_ERROR) { + if (* base_subject == '\0') { + /* subject empty */ + free(base_subject); + continue; + } + else { + /* do nothing */ + } + } + else { + res = r; + goto free_subject_hash; + } + + env_tree->node_base_subject = base_subject; + + /* + (iii) Lookup the message associated with this extracted + subject in the table. + */ + + key.data = base_subject; + key.len = (unsigned int) strlen(base_subject); + + r = chash_get(subject_hash, &key, &data); + + if (r < 0) { + /* + (iv) If there is no message in the table with this + subject, add the current message and the extracted + subject to the subject table. + */ + + data.data = &cur; + data.len = sizeof(cur); + + r = chash_set(subject_hash, &key, &data, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + } + else { + /* + Otherwise, replace the message in the table with the + current message if the message in the table is not a + dummy AND either of the following criteria are true: + The current message is a dummy, OR + The message in the table is a reply or forward (its + original subject contains a subj-refwd part and/or a + "(fwd)" subj-trailer) and the current message is not. + */ + struct mailmessage_tree * msg_in_table; + int replace; + + msg_in_table = carray_get(rootlist, cur); + + replace = FALSE; + /* message is dummy if info is NULL */ + if (msg_in_table->node_msg != NULL) { + + if (env_tree->node_msg == NULL) + replace = TRUE; + else { + if (!env_tree->node_is_reply) + replace = TRUE; + } + } + + if (replace) { + data.data = &cur; + data.len = sizeof(cur); + + r = chash_set(subject_hash, &key, &data, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + } + } + } + + /* + (C) Merge threads with the same subject. For each child of + the root: + */ + + cur = 0; + while (cur < carray_count(rootlist)) { + struct mailmessage_tree * env_tree; + chashdatum key; + chashdatum data; + struct mailmessage_tree * main_tree; + unsigned int * main_cur; + + env_tree = carray_get(rootlist, cur); + + if (env_tree == NULL) + goto next_msg; + + /* + (i) Find the subject of this thread as in step 4.B.i + above. + */ + + /* already done in tree->node_base_subject */ + + /* + (ii) If the extracted subject is empty, skip this + message. + */ + + if (env_tree->node_base_subject == NULL) + goto next_msg; + + if (* env_tree->node_base_subject == '\0') + goto next_msg; + + /* + (iii) Lookup the message associated with this extracted + subject in the table. + */ + + key.data = env_tree->node_base_subject; + key.len = (unsigned int) strlen(env_tree->node_base_subject); + + r = chash_get(subject_hash, &key, &data); + if (r < 0) + goto next_msg; + + /* + (iv) If the message in the table is the current message, + skip this message. + */ + + main_cur = data.data; + if (* main_cur == cur) + goto next_msg; + + /* + Otherwise, merge the current message with the one in the + table using the following rules: + */ + + main_tree = carray_get(rootlist, * main_cur); + + /* + If both messages are dummies, append the current + message's children to the children of the message in + the table (the children of both messages become + siblings), and then delete the current message. + */ + + if ((env_tree->node_msg == NULL) && (main_tree->node_msg == NULL)) { + unsigned int old_size; + + old_size = carray_count(main_tree->node_children); + + r = carray_set_size(main_tree->node_children, old_size + + carray_count(env_tree->node_children)); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + + for(i = 0 ; i < carray_count(env_tree->node_children) ; i ++) { + struct mailmessage_tree * child; + + child = carray_get(env_tree->node_children, i); + carray_set(main_tree->node_children, old_size + i, child); + /* set parent */ + child->node_parent = main_tree; + } + carray_set_size(env_tree->node_children, 0); + /* this is the only case where children can be NULL, + this is before freeing it */ + mailmessage_tree_free(env_tree); + carray_delete_fast(rootlist, cur); + } + + /* + If the message in the table is a dummy and the current + message is not, make the current message a child of + the message in the table (a sibling of it's children). + */ + + else if (main_tree->node_msg == NULL) { + r = carray_add(main_tree->node_children, env_tree, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + /* set parent */ + env_tree->node_parent = main_tree; + + carray_delete_fast(rootlist, cur); + } + + /* + If the current message is a reply or forward and the + message in the table is not, make the current message + a child of the message in the table (a sibling of it's + children). + */ + + else if (env_tree->node_is_reply && !main_tree->node_is_reply) { + r = carray_add(main_tree->node_children, env_tree, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + /* set parent */ + env_tree->node_parent = main_tree; + + carray_delete_fast(rootlist, cur); + } + + /* + Otherwise, create a new dummy message and make both + the current message and the message in the table + children of the dummy. Then replace the message in + the table with the dummy message. + Note: Subject comparisons are case-insensitive, as + described under "Internationalization + Considerations." + */ + + else { + struct mailmessage_tree * new_main_tree; + char * base_subject; + unsigned int last; + + new_main_tree = mailmessage_tree_new(NULL, (time_t) -1, NULL); + if (new_main_tree == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + + /* main_tree->node_base_subject is never NULL */ + + base_subject = strdup(main_tree->node_base_subject); + if (base_subject == NULL) { + mailmessage_tree_free(new_main_tree); + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + + new_main_tree->node_base_subject = base_subject; + + r = carray_add(rootlist, new_main_tree, &last); + if (r < 0) { + mailmessage_tree_free(new_main_tree); + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + + r = carray_add(new_main_tree->node_children, main_tree, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + /* set parent */ + main_tree->node_parent = new_main_tree; + + carray_delete_fast(rootlist, * main_cur); + + r = carray_add(new_main_tree->node_children, env_tree, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + /* set parent */ + env_tree->node_parent = new_main_tree; + + carray_delete_fast(rootlist, cur); + + data.data = &last; + data.len = sizeof(last); + + r = chash_set(subject_hash, &key, &data, NULL); + + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + } + + continue; + + next_msg: + cur ++; + continue; + } + + i = 0; + for(cur = 0 ; cur < carray_count(rootlist) ; cur ++) { + struct mailmessage_tree * env_tree; + + env_tree = carray_get(rootlist, cur); + if (env_tree == NULL) + continue; + + carray_set(rootlist, i, env_tree); + i ++; + } + carray_set_size(rootlist, i); + + chash_free(subject_hash); + } + + /* + (6) Traverse the messages under the root and sort each set of + siblings by sent date. Traverse the messages in such a way + that the "youngest" set of siblings are sorted first, and the + "oldest" set of siblings are sorted last (grandchildren are + sorted before children, etc). + + In the case of an exact match on + sent date or if either of the Date: headers used in a + comparison can not be parsed, use the order in which the + messages appear in the mailbox (that is, by sequence number) to + determine the order. In the case of a dummy message (which can + only occur with top-level siblings), use its first child for + sorting. + */ + +#if 0 + if (comp_func != NULL) { + r = mail_thread_sort(root, comp_func, TRUE); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + } +#endif + if (comp_func == NULL) + comp_func = mailthread_tree_timecomp; + + r = mail_thread_sort(root, comp_func, TRUE); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + * result = root; + + return MAIL_NO_ERROR; + + free_subject_hash: + chash_free(subject_hash); + free_list: + if (msg_list != NULL) { + for(i = 0 ; i < carray_count(msg_list) ; i ++) + mailmessage_tree_free(carray_get(msg_list, i)); + carray_free(msg_list); + } + free_root: + mailmessage_tree_free_recursive(root); + free_hash: + if (msg_id_hash != NULL) + chash_free(msg_id_hash); + err: + return res; +} + + + +static int +mail_build_thread_orderedsubject(char * default_from, + struct mailmessage_list * env_list, + struct mailmessage_tree ** result, + int (* comp_func)(struct mailmessage_tree **, + struct mailmessage_tree **)) +{ + unsigned int i; + carray * rootlist; + unsigned int cur; + struct mailmessage_tree * root; + int res; + int r; + struct mailmessage_tree * current_thread; + + root = mailmessage_tree_new(NULL, (time_t) -1, NULL); + if (root == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + rootlist = root->node_children; + + /* + The ORDEREDSUBJECT threading algorithm is also referred to as + "poor man's threading." + */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailmessage_tree * env_tree; + char * base_subject; + time_t date; + + msg = carray_get(env_list->msg_tab, i); + + if (msg == NULL) + continue; + + if (msg->msg_fields != NULL) { + + date = get_date(msg); + + env_tree = mailmessage_tree_new(NULL, date, msg); + if (env_tree == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + /* set parent */ + env_tree->node_parent = root; + r = carray_add(rootlist, env_tree, NULL); + if (r < 0) { + mailmessage_tree_free(env_tree); + res = MAIL_ERROR_MEMORY; + goto free; + } + + r = get_extracted_subject(default_from, env_tree, &base_subject); + switch (r) { + case MAIL_NO_ERROR: + env_tree->node_base_subject = base_subject; + break; + + case MAIL_ERROR_SUBJECT_NOT_FOUND: + break; + + default: + res = r; + goto free; + } + } + } + + /* + The searched messages are sorted by + subject and then by the sent date. + */ + + r = mail_thread_sort(root, tree_subj_time_comp, FALSE); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + /* + The messages are then split + into separate threads, with each thread containing messages + with the same extracted subject text. + */ + + current_thread = NULL; + + cur = 0; + while (cur < carray_count(rootlist)) { + struct mailmessage_tree * cur_env_tree; + + cur_env_tree = carray_get(rootlist, cur); + if (current_thread == NULL) { + current_thread = cur_env_tree; + cur ++; + continue; + } + + if ((cur_env_tree->node_base_subject == NULL) || + (current_thread->node_base_subject == NULL)) { + current_thread = cur_env_tree; + cur ++; + continue; + } + + if (strcmp(cur_env_tree->node_base_subject, + current_thread->node_base_subject) == 0) { + + /* set parent */ + cur_env_tree->node_parent = current_thread; + r = carray_add(current_thread->node_children, cur_env_tree, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + carray_delete(rootlist, cur); + } + else + cur ++; + current_thread = cur_env_tree; + } + + /* + Finally, the threads are + sorted by the sent date of the first message in the thread. + Note that each message in a thread is a child (as opposed to a + sibling) of the previous message. + */ + +#if 0 + if (comp_func != NULL) { + r = mail_thread_sort(root, comp_func, FALSE); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + } +#endif + + if (comp_func == NULL) + comp_func = mailthread_tree_timecomp; + + r = mail_thread_sort(root, comp_func, FALSE); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + * result = root; + + return MAIL_NO_ERROR; + + free: + mailmessage_tree_free_recursive(root); + err: + return res; +} + + +static int +mail_build_thread_none(char * default_from, + struct mailmessage_list * env_list, + struct mailmessage_tree ** result, + int (* comp_func)(struct mailmessage_tree **, + struct mailmessage_tree **)) +{ + unsigned int i; + carray * rootlist; + struct mailmessage_tree * root; + int res; + int r; + + root = mailmessage_tree_new(NULL, (time_t) -1, NULL); + if (root == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + rootlist = root->node_children; + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailmessage_tree * env_tree; + char * base_subject; + time_t date; + + msg = carray_get(env_list->msg_tab, i); + + if (msg == NULL) + continue; + + if (msg->msg_fields != NULL) { + + date = get_date(msg); + + env_tree = mailmessage_tree_new(NULL, date, msg); + if (env_tree == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + /* set parent */ + env_tree->node_parent = root; + r = carray_add(rootlist, env_tree, NULL); + if (r < 0) { + mailmessage_tree_free(env_tree); + res = MAIL_ERROR_MEMORY; + goto free; + } + + r = get_extracted_subject(default_from, env_tree, &base_subject); + switch (r) { + case MAIL_NO_ERROR: + env_tree->node_base_subject = base_subject; + break; + + case MAIL_ERROR_SUBJECT_NOT_FOUND: + break; + + default: + res = r; + goto free; + } + } + } + + if (comp_func == NULL) + comp_func = mailthread_tree_timecomp; + + r = mail_thread_sort(root, comp_func, FALSE); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + * result = root; + + return MAIL_NO_ERROR; + + free: + mailmessage_tree_free_recursive(root); + err: + return res; +} + + +int mail_build_thread(int type, char * default_from, + struct mailmessage_list * env_list, + struct mailmessage_tree ** result, + int (* comp_func)(struct mailmessage_tree **, + struct mailmessage_tree **)) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) + mailmessage_resolve_single_fields(carray_get(env_list->msg_tab, i)); + + switch (type) { + case MAIL_THREAD_REFERENCES: + return mail_build_thread_references(default_from, + env_list, result, TRUE, comp_func); + + case MAIL_THREAD_REFERENCES_NO_SUBJECT: + return mail_build_thread_references(default_from, + env_list, result, FALSE, comp_func); + + case MAIL_THREAD_ORDEREDSUBJECT: + return mail_build_thread_orderedsubject(default_from, + env_list, result, comp_func); + + case MAIL_THREAD_NONE: + return mail_build_thread_none(default_from, + env_list, result, comp_func); + + default: + return MAIL_ERROR_NOT_IMPLEMENTED; + } +} diff --git a/Sources/libetpan/driver/tools/mailthread.h b/Sources/libetpan/driver/tools/mailthread.h new file mode 100644 index 00000000..86884f22 --- /dev/null +++ b/Sources/libetpan/driver/tools/mailthread.h @@ -0,0 +1,111 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailthread.h,v 1.15 2007/12/10 21:32:59 hoa Exp $ + */ + +#ifndef MAILTHREAD_H + +#define MAILTHREAD_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mail_build_thread constructs a tree with the message using the + given style. + + @param type is the type of threading to apply, the value can be + MAIL_THREAD_REFERENCES, MAIL_THREAD_REFERENCES_NO_SUBJECT, + MAIL_THREAD_ORDEREDSUBJECT or MAIL_THREAD_NONE, + + @param default_from is the default charset to use whenever the + subject is not tagged with a charset. "US-ASCII" can be used + if you don't know what to use. + + @param env_list is the message list (with header fields fetched) + to use to build the message tree. + + @param result * result) will contain the resulting message tree. + + @param if comp_func is NULL, no sorting algorithm is used. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mail_build_thread(int type, char * default_from, + struct mailmessage_list * env_list, + struct mailmessage_tree ** result, + int (* comp_func)(struct mailmessage_tree **, + struct mailmessage_tree **)); + +/* + mail_thread_sort sort the messages in the message tree, using the + given sort function. + + @param tree is the message tree to sort. + + @param comp_func is the sort function to use (this is the same kind of + functions than those used for qsort()). mailthread_tree_timecomp can be + used for default sort. + + @param sort_sub if this value is 0, only the children of the root message + are sorted. +*/ + +LIBETPAN_EXPORT +int mail_thread_sort(struct mailmessage_tree * tree, + int (* comp_func)(struct mailmessage_tree **, + struct mailmessage_tree **), + int sort_sub); + +/* + mailthread_tree_timecomp is the default sort function. + + The message are compared by date, then by message numbers. + The tree are given in (* ptree1) and (* ptree2). +*/ + +LIBETPAN_EXPORT +int mailthread_tree_timecomp(struct mailmessage_tree ** ptree1, + struct mailmessage_tree ** ptree2); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/driver/tools/mailthread_types.c b/Sources/libetpan/driver/tools/mailthread_types.c new file mode 100644 index 00000000..68295594 --- /dev/null +++ b/Sources/libetpan/driver/tools/mailthread_types.c @@ -0,0 +1,99 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailthread_types.c,v 1.12 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailthread_types.h" + +#include "mail.h" +#include + +struct mailmessage_tree * +mailmessage_tree_new(char * node_msgid, time_t node_date, + mailmessage * node_msg) +{ + struct mailmessage_tree * tree; + carray * array; + + array = carray_new(16); + if (array == NULL) + return NULL; + + tree = malloc(sizeof(* tree)); + if (tree == NULL) { + carray_free(array); + return NULL; + } + + tree->node_parent = NULL; + tree->node_date = node_date; + tree->node_msgid = node_msgid; + tree->node_msg = node_msg; + tree->node_children = array; + tree->node_base_subject = NULL; + tree->node_is_reply = FALSE; + + return tree; +} + +void mailmessage_tree_free(struct mailmessage_tree * tree) +{ + if (tree->node_base_subject != NULL) + free(tree->node_base_subject); + + if (tree->node_children != NULL) + carray_free(tree->node_children); + if (tree->node_msgid != NULL) + free(tree->node_msgid); + + free(tree); +} + +void mailmessage_tree_free_recursive(struct mailmessage_tree * tree) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(tree->node_children) ; i++) { + struct mailmessage_tree * child; + + child = carray_get(tree->node_children, i); + + mailmessage_tree_free_recursive(child); + } + + mailmessage_tree_free(tree); +} diff --git a/Sources/libetpan/driver/tools/mailthread_types.h b/Sources/libetpan/driver/tools/mailthread_types.h new file mode 100644 index 00000000..d094eaf4 --- /dev/null +++ b/Sources/libetpan/driver/tools/mailthread_types.h @@ -0,0 +1,64 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailthread_types.h,v 1.9 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifndef MAILTHREAD_TYPES_H + +#define MAILTHREAD_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/* + This is the type of tree construction to apply. +*/ + +enum { + MAIL_THREAD_REFERENCES, /* this is threading using + References fields only) */ + MAIL_THREAD_REFERENCES_NO_SUBJECT, /* this is threading using References + fields, then subject */ + MAIL_THREAD_ORDEREDSUBJECT, /* this is threading using only subject */ + MAIL_THREAD_NONE /* no thread */ +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/engine/Makefile.am b/Sources/libetpan/engine/Makefile.am new file mode 100644 index 00000000..0df3442d --- /dev/null +++ b/Sources/libetpan/engine/Makefile.am @@ -0,0 +1,52 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +etpaninclude_HEADERS = \ + mailengine.h \ + mailprivacy.h \ + mailprivacy_gnupg.h \ + mailprivacy_smime.h \ + mailprivacy_types.h \ + mailprivacy_tools.h + +AM_CPPFLAGS = -I$(top_builddir)/include \ + -I$(top_srcdir)/src/driver/interface \ + -I$(top_srcdir)/src/driver/implementation/imap + +noinst_LTLIBRARIES = libengine.la + +libengine_la_SOURCES = \ + mailprivacy_tools_private.h \ + mailengine.c \ + mailprivacy.c \ + mailprivacy_gnupg.c \ + mailprivacy_smime.c \ + mailprivacy_tools.c diff --git a/Sources/libetpan/engine/mailengine.c b/Sources/libetpan/engine/mailengine.c new file mode 100644 index 00000000..aecebe6c --- /dev/null +++ b/Sources/libetpan/engine/mailengine.c @@ -0,0 +1,1488 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailengine.c,v 1.11 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailengine.h" + +#include "mailfolder.h" +#include "maildriver.h" +#include "imapdriver_cached.h" +#include "mailstorage.h" +#include "imapdriver_cached_message.h" +#include +#include "mailprivacy.h" +#ifdef LIBETPAN_REENTRANT +#if defined(HAVE_PTHREAD_H) && !defined(IGNORE_PTHREAD_H) +#include +#elif (defined WIN32) +#include +#endif +#endif +#include + + +/* ************************************************************* */ +/* Message ref info */ + +struct message_ref_elt { + mailmessage * msg; + int ref_count; + int mime_ref_count; + struct mailfolder * folder; + int lost; +#ifdef LIBETPAN_REENTRANT +#if defined(HAVE_PTHREAD_H) && !defined(IGNORE_PTHREAD_H) + pthread_mutex_t lock; +#else + CRITICAL_SECTION lock; +#endif +#endif +}; + +#ifdef LIBETPAN_REENTRANT +#if defined(HAVE_PTHREAD_H) && !defined(IGNORE_PTHREAD_H) +#define LOCK(lock) pthread_mutex_lock(&lock); +#define UNLOCK(lock) pthread_mutex_unlock(&lock); +#elif (defined WIN32) +#define LOCK(lock) EnterCriticalSection(&lock); +#define UNLOCK(lock) LeaveCriticalSection(&lock); +#endif +#else +#define LOCK(lock) do {} while (0) +#define UNLOCK(lock) do {} while (0) +#endif + +static struct message_ref_elt * +message_ref_elt_new(struct mailfolder * folder, mailmessage * msg) +{ + struct message_ref_elt * ref; + int r; + + ref = malloc(sizeof(* ref)); + if (ref == NULL) + goto err; + +#ifdef LIBETPAN_REENTRANT +#if defined(HAVE_PTHREAD_H) && !defined(IGNORE_PTHREAD_H) + r = pthread_mutex_init(&ref->lock, NULL); + if (r != 0) + goto free; +#else + InitializeCriticalSection(&ref->lock); +#endif +#endif + + ref->msg = msg; + ref->ref_count = 0; + ref->mime_ref_count = 0; + ref->folder = folder; + ref->lost = 0; + + return ref; + + free: + free(ref); + err: + return NULL; +} + +static void message_ref_elt_free(struct message_ref_elt * ref_elt) +{ +#ifdef LIBETPAN_REENTRANT +#if defined(HAVE_PTHREAD_H) && !defined(IGNORE_PTHREAD_H) + pthread_mutex_destroy(&ref_elt->lock); +#else + DeleteCriticalSection(&ref_elt->lock); +#endif +#endif + free(ref_elt); +} + +static inline int message_ref(struct message_ref_elt * ref_elt) +{ + int count; + + LOCK(ref_elt->lock); + ref_elt->ref_count ++; + count = ref_elt->ref_count; + UNLOCK(ref_elt->lock); + + return count; +} + +static inline int message_unref(struct message_ref_elt * ref_elt) +{ + int count; + + LOCK(ref_elt->lock); + ref_elt->ref_count --; + count = ref_elt->ref_count; + UNLOCK(ref_elt->lock); + + return count; +} + + +static inline int message_mime_ref(struct mailprivacy * privacy, + struct message_ref_elt * ref_elt) +{ + int r; + int count; + + if (ref_elt->mime_ref_count == 0) { + struct mailmime * mime; + + r = mailprivacy_msg_get_bodystructure(privacy, ref_elt->msg, &mime); + if (r != MAIL_NO_ERROR) + return -r; + } + + message_ref(ref_elt); + + LOCK(ref_elt->lock); + ref_elt->mime_ref_count ++; + count = ref_elt->mime_ref_count; + UNLOCK(ref_elt->lock); + + return count; +} + +static inline int message_mime_unref(struct mailprivacy * privacy, + struct message_ref_elt * ref_elt) +{ + int count; + + message_unref(ref_elt); + + LOCK(ref_elt->lock); + ref_elt->mime_ref_count --; + + if (ref_elt->mime_ref_count == 0) + mailprivacy_msg_flush(privacy, ref_elt->msg); + + count = ref_elt->mime_ref_count; + + UNLOCK(ref_elt->lock); + + return count; +} + + +/* ************************************************************* */ +/* Folder ref info */ + +struct folder_ref_info { + struct mailfolder * folder; + + /* msg => msg_ref_info */ + chash * msg_hash; + + /* uid => msg */ + chash * uid_hash; + + int lost_session; +}; + +static struct folder_ref_info * +folder_ref_info_new(struct mailfolder * folder + /*, struct message_folder_finder * msg_folder_finder */) +{ + struct folder_ref_info * ref_info; + + ref_info = malloc(sizeof(* ref_info)); + if (ref_info == NULL) + goto err; + + ref_info->folder = folder; + + ref_info->msg_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + if (ref_info->msg_hash == NULL) + goto free; + + ref_info->uid_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYNONE); + if (ref_info->uid_hash == NULL) + goto free_msg_hash; + + ref_info->lost_session = 1; + + return ref_info; + + free_msg_hash: + chash_free(ref_info->msg_hash); + free: + free(ref_info); + err: + return NULL; +} + +static void folder_ref_info_free(struct folder_ref_info * ref_info) +{ + chash_free(ref_info->uid_hash); + chash_free(ref_info->msg_hash); + free(ref_info); +} + +static struct message_ref_elt * +folder_info_get_msg_ref(struct folder_ref_info * ref_info, mailmessage * msg) +{ + chashdatum key; + chashdatum data; + struct message_ref_elt * ref_elt; + int r; + + key.data = &msg; + key.len = sizeof(msg); + r = chash_get(ref_info->msg_hash, &key, &data); + if (r < 0) + return NULL; + + ref_elt = data.data; + + return ref_elt; +} + +static mailmessage * +folder_info_get_msg_by_uid(struct folder_ref_info * ref_info, + char * uid) +{ + chashdatum key; + chashdatum data; + mailmessage * msg; + int r; + + key.data = uid; + key.len = (unsigned int) strlen(uid); + r = chash_get(ref_info->uid_hash, &key, &data); + if (r < 0) + return NULL; + + msg = data.data; + + return msg; +} + +static int folder_message_ref(struct folder_ref_info * ref_info, + mailmessage * msg) +{ + struct message_ref_elt * msg_ref; + + msg_ref = folder_info_get_msg_ref(ref_info, msg); + return message_ref(msg_ref); +} + +static void folder_message_remove(struct folder_ref_info * ref_info, + mailmessage * msg); + +#ifdef DEBUG_ENGINE +#include "etpan-app.h" + +void * engine_app = NULL; +#endif + +static int folder_message_unref(struct folder_ref_info * ref_info, + mailmessage * msg) +{ + struct message_ref_elt * msg_ref; + int count; + + msg_ref = folder_info_get_msg_ref(ref_info, msg); + + if (msg_ref->ref_count == 0) { +#ifdef ETPAN_APP_DEBUG + ETPAN_APP_DEBUG((engine_app, "** BUG detected negative ref count !")); +#endif + } + + count = message_unref(msg_ref); + if (count == 0) { + folder_message_remove(ref_info, msg); + mailmessage_free(msg); + } + + return count; +} + +static int folder_message_mime_ref(struct mailprivacy * privacy, + struct folder_ref_info * ref_info, + mailmessage * msg) +{ + struct message_ref_elt * msg_ref; + + msg_ref = folder_info_get_msg_ref(ref_info, msg); + + return message_mime_ref(privacy, msg_ref); +} + +static int folder_message_mime_unref(struct mailprivacy * privacy, + struct folder_ref_info * ref_info, + mailmessage * msg) +{ + struct message_ref_elt * msg_ref; + + msg_ref = folder_info_get_msg_ref(ref_info, msg); + return message_mime_unref(privacy, msg_ref); +} + +static int folder_message_add(struct folder_ref_info * ref_info, + mailmessage * msg) +{ + chashdatum key; + chashdatum data; + struct message_ref_elt * msg_ref; + int r; + + msg_ref = message_ref_elt_new(ref_info->folder, msg); + if (msg_ref == NULL) + goto err; + + key.data = &msg; + key.len = sizeof(msg); + data.data = msg_ref; + data.len = 0; + + r = chash_set(ref_info->msg_hash, &key, &data, NULL); + if (r < 0) + goto free_msg_ref; + + if (msg->msg_uid != NULL) { + key.data = msg->msg_uid; + key.len = (unsigned int) strlen(msg->msg_uid); + data.data = msg; + data.len = 0; + + r = chash_set(ref_info->uid_hash, &key, &data, NULL); + if (r < 0) + goto remove_msg_ref; + } + + return MAIL_NO_ERROR; + + remove_msg_ref: + key.data = &msg; + key.len = sizeof(msg); + chash_delete(ref_info->msg_hash, &key, NULL); + free_msg_ref: + message_ref_elt_free(msg_ref); + err: + return MAIL_ERROR_MEMORY; +} + + +static void folder_message_remove(struct folder_ref_info * ref_info, + mailmessage * msg) +{ + chashdatum key; + struct message_ref_elt * msg_ref; + + if (msg->msg_uid != NULL) { + key.data = msg->msg_uid; + key.len = (unsigned int) strlen(msg->msg_uid); + + chash_delete(ref_info->uid_hash, &key, NULL); + } + + msg_ref = folder_info_get_msg_ref(ref_info, msg); + message_ref_elt_free(msg_ref); + + key.data = &msg; + key.len = sizeof(msg); + + chash_delete(ref_info->msg_hash, &key, NULL); +} + + +static int folder_update_msg_list(struct folder_ref_info * ref_info, + struct mailmessage_list ** p_new_msg_list, + struct mailmessage_list ** p_lost_msg_list) +{ + int r; + int res; + struct mailmessage_list * new_env_list; + unsigned int i; + carray * lost_msg_tab; + struct mailmessage_list * lost_msg_list; + unsigned int free_start_index; + chashiter * iter; + unsigned int lost_count; + + r = mailfolder_get_messages_list(ref_info->folder, &new_env_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + for(iter = chash_begin(ref_info->msg_hash) ; iter != NULL ; + iter = chash_next(ref_info->msg_hash, iter)) { + struct message_ref_elt * msg_ref; + chashdatum data; + + chash_value(iter, &data); + msg_ref = data.data; + msg_ref->lost = 1; + } + + lost_count = chash_count(ref_info->msg_hash); + + for(i = 0 ; i < carray_count(new_env_list->msg_tab) ; i ++) { + mailmessage * msg; + mailmessage * old_msg; + + msg = carray_get(new_env_list->msg_tab, i); + + if (msg->msg_uid == NULL) + continue; + + old_msg = folder_info_get_msg_by_uid(ref_info, msg->msg_uid); + if (old_msg != NULL) { + struct message_ref_elt * msg_ref; + + /* replace old message */ + old_msg->msg_index = msg->msg_index; + carray_set(new_env_list->msg_tab, i, old_msg); + mailmessage_free(msg); + + msg_ref = folder_info_get_msg_ref(ref_info, old_msg); + msg_ref->lost = 0; + lost_count --; + } + else { + /* set new message */ + r = folder_message_add(ref_info, msg); + if (r != MAIL_NO_ERROR) { + free_start_index = i; + res = r; + goto free_remaining; + } + } + } + + /* build the table of lost messages */ + lost_msg_tab = carray_new(lost_count); + if (lost_msg_tab == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_env_list; + } + + carray_set_size(lost_msg_tab, lost_count); + + i = 0; + for(iter = chash_begin(ref_info->msg_hash) ; iter != NULL ; + iter = chash_next(ref_info->msg_hash, iter)) { + struct message_ref_elt * msg_ref; + chashdatum key; + chashdatum value; + mailmessage * msg; + + chash_key(iter, &key); + memcpy(&msg, key.data, sizeof(msg)); + + chash_value(iter, &value); + msg_ref = value.data; + if (msg_ref->lost) { + carray_set(lost_msg_tab, i, msg); + i ++; + } + } + + lost_msg_list = mailmessage_list_new(lost_msg_tab); + if (lost_msg_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_lost_msg_tab; + } + + /* reference messages */ + for(i = 0 ; i < carray_count(new_env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(new_env_list->msg_tab, i); + folder_message_ref(ref_info, msg); + } + + * p_new_msg_list = new_env_list; + * p_lost_msg_list = lost_msg_list; + + return MAIL_NO_ERROR; + + free_lost_msg_tab: + carray_free(lost_msg_tab); + free_env_list: + for(i = 0 ; i < carray_count(new_env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct message_ref_elt * msg_ref; + + msg = carray_get(new_env_list->msg_tab, i); + msg_ref = folder_info_get_msg_ref(ref_info, msg); + if (msg_ref != NULL) { + if (msg_ref->ref_count == 0) + folder_message_remove(ref_info, msg); + } + } + carray_set_size(new_env_list->msg_tab, 0); + mailmessage_list_free(new_env_list); + goto err; + free_remaining: + for(i = 0 ; i < carray_count(new_env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct message_ref_elt * msg_ref; + + msg = carray_get(new_env_list->msg_tab, i); + msg_ref = folder_info_get_msg_ref(ref_info, msg); + if (msg_ref != NULL) { + if (msg_ref->ref_count == 0) + folder_message_remove(ref_info, msg); + } + } + for(i = free_start_index ; i < carray_count(new_env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(new_env_list->msg_tab, i); + mailmessage_free(msg); + } + carray_set_size(new_env_list->msg_tab, 0); + mailmessage_list_free(new_env_list); + err: + return res; +} + +/* + folder_fetch_env_list() +*/ + +static int folder_fetch_env_list(struct folder_ref_info * ref_info, + struct mailmessage_list * msg_list) +{ + return mailfolder_get_envelopes_list(ref_info->folder, msg_list); +} + +static void folder_free_msg_list(struct folder_ref_info * ref_info, + struct mailmessage_list * env_list) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + folder_message_unref(ref_info, msg); + } + carray_set_size(env_list->msg_tab, 0); + mailmessage_list_free(env_list); +} + + +/* ************************************************************* */ +/* Storage ref info */ + +struct storage_ref_info { + struct mailstorage * storage; + + /* folder => folder_ref_info */ + chash * folder_ref_info; +}; + +static struct storage_ref_info * +storage_ref_info_new(struct mailstorage * storage + /*, struct message_folder_finder * msg_folder_finder */) +{ + struct storage_ref_info * ref_info; + + ref_info = malloc(sizeof(* ref_info)); + if (ref_info == NULL) + goto err; + + ref_info->storage = storage; + + ref_info->folder_ref_info = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + if (ref_info->folder_ref_info == NULL) + goto free; + + return ref_info; + + free: + free(ref_info); + err: + return NULL; +} + +static void storage_ref_info_free(struct storage_ref_info * ref_info) +{ + chash_free(ref_info->folder_ref_info); + free(ref_info); +} + + +static struct folder_ref_info * +storage_get_folder_ref(struct storage_ref_info * ref_info, + struct mailfolder * folder) +{ + struct folder_ref_info * folder_ref; + chashdatum key; + chashdatum value; + int r; + + key.data = &folder; + key.len = sizeof(folder); + r = chash_get(ref_info->folder_ref_info, &key, &value); + if (r < 0) + return NULL; + + folder_ref = value.data; + + return folder_ref; +} + +static struct folder_ref_info * +storage_folder_add_ref(struct storage_ref_info * ref_info, + struct mailfolder * folder) +{ + struct folder_ref_info * folder_ref; + chashdatum key; + chashdatum value; + int r; + + folder_ref = folder_ref_info_new(folder /*, ref_info->msg_folder_finder */); + if (folder_ref == NULL) + goto err; + + key.data = &folder; + key.len = sizeof(folder); + value.data = folder_ref; + value.len = 0; + r = chash_set(ref_info->folder_ref_info, &key, &value, NULL); + if (r < 0) + goto free; + + return folder_ref; + + free: + folder_ref_info_free(folder_ref); + err: + return NULL; +} + + +static void storage_folder_remove_ref(struct storage_ref_info * ref_info, + struct mailfolder * folder) +{ + struct folder_ref_info * folder_ref; + chashdatum key; + chashdatum value; + int r; + + key.data = &folder; + key.len = sizeof(folder); + r = chash_get(ref_info->folder_ref_info, &key, &value); + if (r < 0) + return; + + folder_ref = value.data; + + if (folder_ref == NULL) + return; + + folder_ref_info_free(folder_ref); + + chash_delete(ref_info->folder_ref_info, &key, &value); +} + +static int storage_folder_get_msg_list(struct storage_ref_info * ref_info, + struct mailfolder * folder, + struct mailmessage_list ** p_new_msg_list, + struct mailmessage_list ** p_lost_msg_list) +{ + struct folder_ref_info * folder_ref_info; + + folder_ref_info = storage_get_folder_ref(ref_info, folder); + if (folder_ref_info == NULL) + return MAIL_ERROR_INVAL; + + return folder_update_msg_list(folder_ref_info, + p_new_msg_list, p_lost_msg_list); +} + +static int storage_folder_fetch_env_list(struct storage_ref_info * ref_info, + struct mailfolder * folder, + struct mailmessage_list * msg_list) +{ + struct folder_ref_info * folder_ref_info; + + folder_ref_info = storage_get_folder_ref(ref_info, folder); + if (folder_ref_info == NULL) + return MAIL_ERROR_INVAL; + + return folder_fetch_env_list(folder_ref_info, msg_list); +} + +static void +storage_folder_free_msg_list(struct storage_ref_info * ref_info, + struct mailfolder * folder, + struct mailmessage_list * env_list) +{ + struct folder_ref_info * folder_ref_info; + + folder_ref_info = storage_get_folder_ref(ref_info, folder); + + folder_free_msg_list(folder_ref_info, env_list); +} + + +/* connection and disconnection */ + +static void +folder_restore_session(struct folder_ref_info * ref_info) +{ + chashiter * iter; + mailsession * session; + + session = ref_info->folder->fld_session; + + for(iter = chash_begin(ref_info->msg_hash) ; iter != NULL ; + iter = chash_next(ref_info->msg_hash, iter)) { + chashdatum key; + mailmessage * msg; + + chash_key(iter, &key); + memcpy(&msg, key.data, sizeof(msg)); + msg->msg_session = session; + + if (msg->msg_driver == imap_cached_message_driver) { + struct imap_cached_session_state_data * imap_cached_data; + mailmessage * ancestor_msg; + + imap_cached_data = ref_info->folder->fld_session->sess_data; + ancestor_msg = msg->msg_data; + ancestor_msg->msg_session = imap_cached_data->imap_ancestor; + } + } +} + +static void +storage_restore_message_session(struct storage_ref_info * ref_info) +{ + chashiter * iter; + + for(iter = chash_begin(ref_info->folder_ref_info) ; iter != NULL ; + iter = chash_next(ref_info->folder_ref_info, iter)) { + chashdatum data; + struct folder_ref_info * folder_ref_info; + + chash_value(iter, &data); + folder_ref_info = data.data; + if (folder_ref_info->lost_session) { + if (folder_ref_info->folder->fld_session != NULL) { + /* restore folder session */ + folder_restore_session(folder_ref_info); + + folder_ref_info->lost_session = 0; + } + } + } +} + + +static int do_storage_connect(struct storage_ref_info * ref_info) +{ + int r; + + r = mailstorage_connect(ref_info->storage); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; +} + +static void do_storage_disconnect(struct storage_ref_info * ref_info) +{ + clistiter * cur; + + /* storage is disconnected, session is lost */ + for(cur = clist_begin(ref_info->storage->sto_shared_folders) ; cur != NULL ; + cur = clist_next(cur)) { + struct folder_ref_info * folder_ref_info; + struct mailfolder * folder; + + folder = clist_content(cur); + /* folder is disconnected (in storage), session is lost */ + + folder_ref_info = storage_get_folder_ref(ref_info, folder); + folder_ref_info->lost_session = 1; + } + + /* storage is disconnected */ + mailstorage_disconnect(ref_info->storage); +} + + + +static int folder_connect(struct storage_ref_info * ref_info, + struct mailfolder * folder) +{ + int r; + + r = do_storage_connect(ref_info); + if (r != MAIL_NO_ERROR) + return r; + + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; +} + + +static void folder_disconnect(struct storage_ref_info * ref_info, + struct mailfolder * folder) +{ + struct folder_ref_info * folder_ref_info; + + folder_ref_info = storage_get_folder_ref(ref_info, folder); + + /* folder is disconnected, session is lost */ + folder_ref_info->lost_session = 1; + mailfolder_disconnect(folder); + + if (folder->fld_shared_session) + do_storage_disconnect(ref_info); +} + + +static int storage_folder_connect(struct storage_ref_info * ref_info, + struct mailfolder * folder) +{ + int r; + int res; + struct folder_ref_info * folder_ref_info; + + folder_ref_info = storage_get_folder_ref(ref_info, folder); + if (folder_ref_info == NULL) { + folder_ref_info = storage_folder_add_ref(ref_info, folder); + if (folder_ref_info == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + } + + /* connect folder */ + + r = folder_connect(ref_info, folder); + if (r == MAIL_ERROR_STREAM) { + /* properly handles disconnection */ + + /* reconnect */ + folder_disconnect(ref_info, folder); + r = folder_connect(ref_info, folder); + } + + if (r != MAIL_NO_ERROR) { + res = r; + goto remove_ref; + } + + /* test folder connection */ + r = mailfolder_noop(folder); + if (r == MAIL_ERROR_STREAM) { + /* reconnect */ + folder_disconnect(ref_info, folder); + r = folder_connect(ref_info, folder); + } + + if ((r != MAIL_ERROR_NOT_IMPLEMENTED) && (r != MAIL_NO_ERROR)) { + res = r; + goto disconnect; + } + + storage_restore_message_session(ref_info); + + return MAIL_NO_ERROR; + + disconnect: + folder_disconnect(ref_info, folder); + remove_ref: + storage_folder_remove_ref(ref_info, folder); + err: + return res; +} + +static void storage_folder_disconnect(struct storage_ref_info * ref_info, + struct mailfolder * folder) +{ + mailfolder_disconnect(folder); + storage_folder_remove_ref(ref_info, folder); +} + +static int storage_connect(struct storage_ref_info * ref_info) +{ + int r; + int res; + + /* connect storage */ + + /* properly handles disconnection */ + r = do_storage_connect(ref_info); + if (r == MAIL_ERROR_STREAM) { + /* reconnect storage */ + do_storage_disconnect(ref_info); + r = do_storage_connect(ref_info); + } + + if (r != MAIL_NO_ERROR) { + res = r; + goto disconnect; + } + + /* test storage connection */ + + r = mailsession_noop(ref_info->storage->sto_session); + if ((r != MAIL_ERROR_NOT_IMPLEMENTED) && (r != MAIL_NO_ERROR)) { + /* properly handles disconnection */ + + /* reconnect storage */ + do_storage_disconnect(ref_info); + r = do_storage_connect(ref_info); + } + + if (r != MAIL_NO_ERROR) { + res = r; + goto disconnect; + } + + storage_restore_message_session(ref_info); + + return MAIL_NO_ERROR; + + disconnect: + do_storage_disconnect(ref_info); + return res; +} + + +static void storage_disconnect(struct storage_ref_info * ref_info) +{ + chashiter * iter; + + /* disconnect folders */ + while ((iter = chash_begin(ref_info->folder_ref_info)) != NULL) { + chashdatum key; + struct mailfolder * folder; + + chash_key(iter, &key); + memcpy(&folder, key.data, sizeof(folder)); + + storage_folder_disconnect(ref_info, folder); + } + + /* disconnect storage */ + do_storage_disconnect(ref_info); +} + + +/* ************************************************************* */ +/* interface for mailengine */ + +struct mailengine { + struct mailprivacy * privacy; + +#ifdef LIBETPAN_REENTRANT +#if defined(HAVE_PTHREAD_H) && !defined(IGNORE_PTHREAD_H) + pthread_mutex_t storage_hash_lock; +#elif (defined WIN32) + CRITICAL_SECTION storage_hash_lock; +#endif +#endif + /* storage => storage_ref_info */ + chash * storage_hash; +}; + +static struct storage_ref_info * +get_storage_ref_info(struct mailengine * engine, + struct mailstorage * storage) +{ + chashdatum key; + chashdatum data; + int r; + struct storage_ref_info * ref_info; + + key.data = &storage; + key.len = sizeof(storage); + LOCK(engine->storage_hash_lock); + r = chash_get(engine->storage_hash, &key, &data); + UNLOCK(engine->storage_hash_lock); + if (r < 0) + return NULL; + + ref_info = data.data; + + return ref_info; +} + +static struct storage_ref_info * +add_storage_ref_info(struct mailengine * engine, + struct mailstorage * storage) +{ + chashdatum key; + chashdatum data; + int r; + struct storage_ref_info * ref_info; + + ref_info = storage_ref_info_new(storage + /* , &engine->msg_folder_finder */); + if (ref_info == NULL) + goto err; + + key.data = &storage; + key.len = sizeof(storage); + data.data = ref_info; + data.len = 0; + + LOCK(engine->storage_hash_lock); + r = chash_set(engine->storage_hash, &key, &data, NULL); + UNLOCK(engine->storage_hash_lock); + if (r < 0) + goto free; + + ref_info = data.data; + + return ref_info; + + free: + storage_ref_info_free(ref_info); + err: + return NULL; +} + +static void +remove_storage_ref_info(struct mailengine * engine, + struct mailstorage * storage) +{ + chashdatum key; + chashdatum data; + struct storage_ref_info * ref_info; + + key.data = &storage; + key.len = sizeof(storage); + + LOCK(engine->storage_hash_lock); + + chash_get(engine->storage_hash, &key, &data); + ref_info = data.data; + + if (ref_info != NULL) { + storage_ref_info_free(ref_info); + + chash_delete(engine->storage_hash, &key, NULL); + } + + LOCK(engine->storage_hash_lock); +} + +struct mailengine * +libetpan_engine_new(struct mailprivacy * privacy) +{ + struct mailengine * engine; + int r; + + engine = malloc(sizeof(* engine)); + if (engine == NULL) + goto err; + + engine->privacy = privacy; + +#ifdef LIBETPAN_REENTRANT +#if defined(HAVE_PTHREAD_H) && !defined(IGNORE_PTHREAD_H) + r = pthread_mutex_init(&engine->storage_hash_lock, NULL); + if (r != 0) + goto free; +#elif (defined WIN32) + InitializeCriticalSection(&engine->storage_hash_lock); +#endif +#endif + + engine->storage_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + if (engine->storage_hash == NULL) + goto destroy_mutex; + + return engine; + + destroy_mutex: +#ifdef LIBETPAN_REENTRANT +#if defined(HAVE_PTHREAD_H) && !defined(IGNORE_PTHREAD_H) + pthread_mutex_destroy(&engine->storage_hash_lock); +#elif (defined WIN32) + DeleteCriticalSection(&engine->storage_hash_lock); +#endif +#endif + free: + free(engine); + err: + return NULL; +} + +void libetpan_engine_free(struct mailengine * engine) +{ + chash_free(engine->storage_hash); +#ifdef LIBETPAN_REENTRANT +#if defined(HAVE_PTHREAD_H) && !defined(IGNORE_PTHREAD_H) + pthread_mutex_destroy(&engine->storage_hash_lock); +#elif (defined WIN32) + DeleteCriticalSection(&engine->storage_hash_lock); +#endif +#endif + free(engine); +} + +static struct folder_ref_info * +message_get_folder_ref(struct mailengine * engine, + mailmessage * msg) +{ + struct mailfolder * folder; + struct mailstorage * storage; + struct storage_ref_info * storage_ref_info; + struct folder_ref_info * folder_ref_info; + + folder = msg->msg_folder; + if (folder == NULL) + storage = NULL; + else + storage = folder->fld_storage; + + storage_ref_info = get_storage_ref_info(engine, storage); + + folder_ref_info = storage_get_folder_ref(storage_ref_info, folder); + + return folder_ref_info; +} + +int libetpan_message_ref(struct mailengine * engine, + mailmessage * msg) +{ + struct folder_ref_info * ref_info; + + ref_info = message_get_folder_ref(engine, msg); + + return folder_message_ref(ref_info, msg); +} + +int libetpan_message_unref(struct mailengine * engine, + mailmessage * msg) +{ + struct folder_ref_info * ref_info; + + ref_info = message_get_folder_ref(engine, msg); + + return folder_message_unref(ref_info, msg); +} + + +int libetpan_message_mime_ref(struct mailengine * engine, + mailmessage * msg) +{ + struct folder_ref_info * ref_info; + + ref_info = message_get_folder_ref(engine, msg); + + return folder_message_mime_ref(engine->privacy, ref_info, msg); +} + +int libetpan_message_mime_unref(struct mailengine * engine, + mailmessage * msg) +{ + struct folder_ref_info * ref_info; + + ref_info = message_get_folder_ref(engine, msg); + + return folder_message_mime_unref(engine->privacy, ref_info, msg); +} + +int libetpan_folder_get_msg_list(struct mailengine * engine, + struct mailfolder * folder, + struct mailmessage_list ** p_new_msg_list, + struct mailmessage_list ** p_lost_msg_list) +{ + struct storage_ref_info * ref_info; + + ref_info = get_storage_ref_info(engine, folder->fld_storage); + + return storage_folder_get_msg_list(ref_info, folder, + p_new_msg_list, p_lost_msg_list); +} + +int libetpan_folder_fetch_env_list(struct mailengine * engine, + struct mailfolder * folder, + struct mailmessage_list * msg_list) +{ + struct storage_ref_info * ref_info; + + ref_info = get_storage_ref_info(engine, folder->fld_storage); + + return storage_folder_fetch_env_list(ref_info, folder, msg_list); +} + +void libetpan_folder_free_msg_list(struct mailengine * engine, + struct mailfolder * folder, + struct mailmessage_list * env_list) +{ + struct storage_ref_info * ref_info; + + ref_info = get_storage_ref_info(engine, folder->fld_storage); + + storage_folder_free_msg_list(ref_info, folder, env_list); +} + + +int libetpan_storage_add(struct mailengine * engine, + struct mailstorage * storage) +{ + struct storage_ref_info * storage_ref_info; + struct folder_ref_info * folder_ref_info; + + storage_ref_info = add_storage_ref_info(engine, storage); + if (storage_ref_info == NULL) + goto err; + + if (storage == NULL) { + folder_ref_info = storage_folder_add_ref(storage_ref_info, NULL); + if (folder_ref_info == NULL) + goto remove_storage_ref_info; + } + + return MAIL_NO_ERROR; + + remove_storage_ref_info: + remove_storage_ref_info(engine, storage); + err: + return MAIL_ERROR_MEMORY; +} + +void libetpan_storage_remove(struct mailengine * engine, + struct mailstorage * storage) +{ + struct storage_ref_info * storage_ref_info; + + storage_ref_info = get_storage_ref_info(engine, storage); + if (storage == NULL) { + storage_folder_remove_ref(storage_ref_info, NULL); + } + + remove_storage_ref_info(engine, storage); +} + +int libetpan_storage_connect(struct mailengine * engine, + struct mailstorage * storage) +{ + struct storage_ref_info * ref_info; + + ref_info = get_storage_ref_info(engine, storage); + + return storage_connect(ref_info); +} + + +void libetpan_storage_disconnect(struct mailengine * engine, + struct mailstorage * storage) +{ + struct storage_ref_info * ref_info; + + ref_info = get_storage_ref_info(engine, storage); + + storage_disconnect(ref_info); +} + +int libetpan_storage_used(struct mailengine * engine, + struct mailstorage * storage) +{ + struct storage_ref_info * ref_info; + + ref_info = get_storage_ref_info(engine, storage); + + return (chash_count(ref_info->folder_ref_info) != 0); +} + + +int libetpan_folder_connect(struct mailengine * engine, + struct mailfolder * folder) +{ + struct storage_ref_info * ref_info; + + ref_info = get_storage_ref_info(engine, folder->fld_storage); + + return storage_folder_connect(ref_info, folder); +} + + +void libetpan_folder_disconnect(struct mailengine * engine, + struct mailfolder * folder) +{ + struct storage_ref_info * ref_info; + + ref_info = get_storage_ref_info(engine, folder->fld_storage); + + storage_folder_disconnect(ref_info, folder); +} + + +struct mailfolder * +libetpan_message_get_folder(struct mailengine * engine, + mailmessage * msg) +{ + return msg->msg_folder; +} + + +struct mailstorage * +libetpan_message_get_storage(struct mailengine * engine, + mailmessage * msg) +{ + struct mailfolder * folder; + + folder = libetpan_message_get_folder(engine, msg); + + if (folder == NULL) + return NULL; + else + return folder->fld_storage; +} + + +int libetpan_message_register(struct mailengine * engine, + struct mailfolder * folder, + mailmessage * msg) +{ + struct storage_ref_info * storage_ref_info; + int r; + int res; + struct folder_ref_info * folder_ref_info; + struct mailstorage * storage; + + if (folder != NULL) + storage = folder->fld_storage; + else + storage = NULL; + + storage_ref_info = get_storage_ref_info(engine, storage); + + folder_ref_info = storage_get_folder_ref(storage_ref_info, folder); + + r = folder_message_add(folder_ref_info, msg); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +struct mailprivacy * +libetpan_engine_get_privacy(struct mailengine * engine) +{ + return engine->privacy; +} + + +static void folder_debug(struct folder_ref_info * folder_ref_info, FILE * f) +{ + fprintf(f, "folder debug -- begin\n"); + if (folder_ref_info->folder == NULL) { + fprintf(f, "NULL folder\n"); + } + else { + if (folder_ref_info->folder->fld_virtual_name != NULL) + fprintf(f, "folder %s\n", folder_ref_info->folder->fld_virtual_name); + else + fprintf(f, "folder [no name]\n"); + } + + fprintf(f, "message count: %i\n", chash_count(folder_ref_info->msg_hash)); + fprintf(f, "UID count: %i\n", chash_count(folder_ref_info->uid_hash)); + fprintf(f, "folder debug -- end\n"); +} + +static void storage_debug(struct storage_ref_info * storage_ref_info, FILE * f) +{ + chashiter * iter; + + fprintf(f, "storage debug -- begin\n"); + if (storage_ref_info->storage == NULL) { + fprintf(f, "NULL storage\n"); + } + else { + if (storage_ref_info->storage->sto_id != NULL) + fprintf(f, "storage %s\n", storage_ref_info->storage->sto_id); + else + fprintf(f, "storage [no name]\n"); + } + fprintf(f, "folder count: %i\n", + chash_count(storage_ref_info->folder_ref_info)); + + for(iter = chash_begin(storage_ref_info->folder_ref_info) ; iter != NULL ; + iter = chash_next(storage_ref_info->folder_ref_info, iter)) { + chashdatum data; + struct folder_ref_info * folder_ref_info; + + chash_value(iter, &data); + folder_ref_info = data.data; + + folder_debug(folder_ref_info, f); + } + fprintf(f, "storage debug -- end\n"); +} + +void libetpan_engine_debug(struct mailengine * engine, FILE * f) +{ + chashiter * iter; + + fprintf(f, "mail engine debug -- begin\n"); + + for(iter = chash_begin(engine->storage_hash) ; iter != NULL ; + iter = chash_next(engine->storage_hash, iter)) { + chashdatum data; + struct storage_ref_info * storage_ref_info; + + chash_value(iter, &data); + storage_ref_info = data.data; + + storage_debug(storage_ref_info, f); + } + + fprintf(f, "mail engine debug -- end\n"); +} + diff --git a/Sources/libetpan/engine/mailengine.h b/Sources/libetpan/engine/mailengine.h new file mode 100644 index 00000000..4fafe72d --- /dev/null +++ b/Sources/libetpan/engine/mailengine.h @@ -0,0 +1,190 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailengine.h,v 1.3 2004/11/21 21:53:35 hoa Exp $ + */ + +#ifndef MAILENGINE_H + +#define MAILENGINE_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + to run things in thread, you must protect the storage again concurrency. +*/ + + +/* + storage data +*/ + +struct mailengine * +libetpan_engine_new(struct mailprivacy * privacy); + +void libetpan_engine_free(struct mailengine * engine); + + +struct mailprivacy * +libetpan_engine_get_privacy(struct mailengine * engine); + + +/* + message ref and unref +*/ + +/* + these function can only take messages returned by get_msg_list() + as arguments. + + these functions cannot fail. +*/ + +int libetpan_message_ref(struct mailengine * engine, + mailmessage * msg); + +int libetpan_message_unref(struct mailengine * engine, + mailmessage * msg); + + +/* + when you want to access the MIME structure of the message + with msg->mime, you have to call libetpan_message_mime_ref() + and libetpan_message_mime_unref() when you have finished. + + if libetpan_mime_ref() returns a value <= 0, it means this failed. + the value is -MAIL_ERROR_XXX +*/ + +int libetpan_message_mime_ref(struct mailengine * engine, + mailmessage * msg); + +int libetpan_message_mime_unref(struct mailengine * engine, + mailmessage * msg); + +/* + message list +*/ + +/* + libetpan_folder_get_msg_list() + + This function returns two list. + - List of lost message (the messages that were previously returned + but that does no more exist) (p_lost_msg_list) + - List of valid messages (p_new_msg_list). + + These two list can only be freed by libetpan_folder_free_msg_list() +*/ + +int libetpan_folder_get_msg_list(struct mailengine * engine, + struct mailfolder * folder, + struct mailmessage_list ** p_new_msg_list, + struct mailmessage_list ** p_lost_msg_list); + +int libetpan_folder_fetch_env_list(struct mailengine * engine, + struct mailfolder * folder, + struct mailmessage_list * msg_list); + +void libetpan_folder_free_msg_list(struct mailengine * engine, + struct mailfolder * folder, + struct mailmessage_list * env_list); + + +/* + connect and disconnect storage +*/ + +int libetpan_storage_add(struct mailengine * engine, + struct mailstorage * storage); + +void libetpan_storage_remove(struct mailengine * engine, + struct mailstorage * storage); + +int libetpan_storage_connect(struct mailengine * engine, + struct mailstorage * storage); + +void libetpan_storage_disconnect(struct mailengine * engine, + struct mailstorage * storage); + +int libetpan_storage_used(struct mailengine * engine, + struct mailstorage * storage); + + +/* + libetpan_folder_connect() + libetpan_folder_disconnect() + + You can disconnect the folder only when you have freed all the message + you were given. +*/ + +int libetpan_folder_connect(struct mailengine * engine, + struct mailfolder * folder); + +void libetpan_folder_disconnect(struct mailengine * engine, + struct mailfolder * folder); + + +struct mailfolder * +libetpan_message_get_folder(struct mailengine * engine, + mailmessage * msg); + +struct mailstorage * +libetpan_message_get_storage(struct mailengine * engine, + mailmessage * msg); + + +/* + register a message +*/ + +int libetpan_message_register(struct mailengine * engine, + struct mailfolder * folder, + mailmessage * msg); + + +void libetpan_engine_debug(struct mailengine * engine, FILE * f); + +extern void * engine_app; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/engine/mailprivacy.c b/Sources/libetpan/engine/mailprivacy.c new file mode 100644 index 00000000..f093c9e2 --- /dev/null +++ b/Sources/libetpan/engine/mailprivacy.c @@ -0,0 +1,938 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailprivacy.c,v 1.9 2010/04/05 14:21:35 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailprivacy.h" + +#include +#include +#include +#include +#include +#ifdef WIN32 +# include "win_etpan.h" +#else +# include +#endif +#include +#include +#include "mailprivacy_tools.h" + +carray * mailprivacy_get_protocols(struct mailprivacy * privacy) +{ + return privacy->protocols; +} + +static int recursive_check_privacy(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime); + +struct mailprivacy * mailprivacy_new(char * tmp_dir, int make_alternative) +{ + struct mailprivacy * privacy; + + privacy = malloc(sizeof(* privacy)); + if (privacy == NULL) + goto err; + + privacy->tmp_dir = strdup(tmp_dir); + if (privacy->tmp_dir == NULL) + goto free; + + privacy->msg_ref = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + if (privacy->msg_ref == NULL) + goto free_tmp_dir; + + privacy->mmapstr = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + if (privacy->mmapstr == NULL) + goto free_msg_ref; + + privacy->mime_ref = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + if (privacy->mime_ref == NULL) + goto free_mmapstr; + + privacy->protocols = carray_new(16); + if (privacy->protocols == NULL) + goto free_mime_ref; + + privacy->make_alternative = make_alternative; + + return privacy; + + free_mime_ref: + chash_free(privacy->mime_ref); + free_mmapstr: + chash_free(privacy->mmapstr); + free_msg_ref: + chash_free(privacy->msg_ref); + free_tmp_dir: + free(privacy->tmp_dir); + free: + free(privacy); + err: + return NULL; +} + +void mailprivacy_free(struct mailprivacy * privacy) +{ + carray_free(privacy->protocols); + chash_free(privacy->mime_ref); + chash_free(privacy->mmapstr); + chash_free(privacy->msg_ref); + free(privacy->tmp_dir); + free(privacy); +} + +static int msg_is_modified(struct mailprivacy * privacy, + mailmessage * msg) +{ + chashdatum key; + chashdatum data; + int r; + + if (privacy == NULL) + return 0; + + key.data = &msg; + key.len = sizeof(msg); + + r = chash_get(privacy->msg_ref, &key, &data); + if (r < 0) + return 0; + else + return 1; +} + +static int register_msg(struct mailprivacy * privacy, + mailmessage * msg) +{ + chashdatum key; + chashdatum data; + int r; + + if (privacy == NULL) + return MAIL_NO_ERROR; + + key.data = &msg; + key.len = sizeof(msg); + data.data = msg; + data.len = 0; + + r = chash_set(privacy->msg_ref, &key, &data, NULL); + if (r < 0) + return MAIL_ERROR_MEMORY; + else + return MAIL_NO_ERROR; +} + +static void unregister_message(struct mailprivacy * privacy, + mailmessage * msg) +{ + chashdatum key; + + key.data = &msg; + key.len = sizeof(msg); + + chash_delete(privacy->msg_ref, &key, NULL); +} + +static int result_is_mmapstr(struct mailprivacy * privacy, char * str) +{ + chashdatum key; + chashdatum data; + int r; + + key.data = &str; + key.len = sizeof(str); + + r = chash_get(privacy->mmapstr, &key, &data); + if (r < 0) + return 0; + else + return 1; +} + +static int register_result_mmapstr(struct mailprivacy * privacy, + char * content) +{ + chashdatum key; + chashdatum data; + int r; + + key.data = &content; + key.len = sizeof(content); + data.data = content; + data.len = 0; + + r = chash_set(privacy->mmapstr, &key, &data, NULL); + if (r < 0) + return MAIL_ERROR_MEMORY; + + return 0; +} + +static void unregister_result_mmapstr(struct mailprivacy * privacy, + char * str) +{ + chashdatum key; + + mmap_string_unref(str); + + key.data = &str; + key.len = sizeof(str); + + chash_delete(privacy->mmapstr, &key, NULL); +} + +static int register_mime(struct mailprivacy * privacy, + struct mailmime * mime) +{ + chashdatum key; + chashdatum data; + int r; + + key.data = &mime; + key.len = sizeof(mime); + data.data = mime; + data.len = 0; + + r = chash_set(privacy->mime_ref, &key, &data, NULL); + if (r < 0) + return MAIL_ERROR_MEMORY; + else + return MAIL_NO_ERROR; +} + +static void unregister_mime(struct mailprivacy * privacy, + struct mailmime * mime) +{ + chashdatum key; + + key.data = &mime; + key.len = sizeof(mime); + + chash_delete(privacy->mime_ref, &key, NULL); +} + +static int mime_is_registered(struct mailprivacy * privacy, + struct mailmime * mime) +{ + chashdatum key; + chashdatum data; + int r; + + key.data = &mime; + key.len = sizeof(mime); + + r = chash_get(privacy->mime_ref, &key, &data); + if (r < 0) + return 0; + else + return 1; +} + +static int recursive_register_mime(struct mailprivacy * privacy, + struct mailmime * mime) +{ + clistiter * cur; + int r; + + r = register_mime(privacy, mime); + if (r != MAIL_NO_ERROR) + return r; + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + break; + + case MAILMIME_MULTIPLE: + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * child; + + child = clist_content(cur); + + r = recursive_register_mime(privacy, child); + if (r != MAIL_NO_ERROR) + return r; + } + break; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_msg_mime) { + r = recursive_register_mime(privacy, + mime->mm_data.mm_message.mm_msg_mime); + if (r != MAIL_NO_ERROR) + return r; + } + break; + } + + return MAIL_NO_ERROR; +} + +void mailprivacy_recursive_unregister_mime(struct mailprivacy * privacy, + struct mailmime * mime) +{ + clistiter * cur; + + unregister_mime(privacy, mime); + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + break; + + case MAILMIME_MULTIPLE: + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * child; + + child = clist_content(cur); + + mailprivacy_recursive_unregister_mime(privacy, child); + } + break; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_msg_mime) + mailprivacy_recursive_unregister_mime(privacy, + mime->mm_data.mm_message.mm_msg_mime); + break; + } +} + +static void recursive_clear_registered_mime(struct mailprivacy * privacy, + struct mailmime * mime) +{ + clistiter * cur; + struct mailmime_data * data; + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + if (mime_is_registered(privacy, mime)) { + data = mime->mm_data.mm_single; + if (data != NULL) { + if (data->dt_type == MAILMIME_DATA_FILE) + unlink(data->dt_data.dt_filename); + } + } + break; + + case MAILMIME_MULTIPLE: + if (mime_is_registered(privacy, mime)) { + data = mime->mm_data.mm_multipart.mm_preamble; + if (data != NULL) { + if (data->dt_type == MAILMIME_DATA_FILE) + unlink(data->dt_data.dt_filename); + } + data = mime->mm_data.mm_multipart.mm_epilogue; + if (data != NULL) { + if (data->dt_type == MAILMIME_DATA_FILE) + unlink(data->dt_data.dt_filename); + } + } + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * child; + + child = clist_content(cur); + + recursive_clear_registered_mime(privacy, child); + } + break; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_msg_mime) + recursive_clear_registered_mime(privacy, + mime->mm_data.mm_message.mm_msg_mime); + break; + } + unregister_mime(privacy, mime); +} + + +/* **************************************************** */ +/* fetch operations start here */ + + +static void recursive_clear_registered_mime(struct mailprivacy * privacy, + struct mailmime * mime); + +#if 0 +static void display_recursive_part(struct mailmime * mime) +{ + clistiter * cur; + + fprintf(stderr, "part %p\n", mime->mm_body); + switch (mime->mm_type) { + case MAILMIME_SINGLE: + fprintf(stderr, "single %p - %i\n", mime->mm_data.mm_single, + mime->mm_data.mm_single->dt_type); + if (mime->mm_data.mm_single->dt_type == MAILMIME_DATA_TEXT) { + fprintf(stderr, "data : %p %i\n", + mime->mm_data.mm_single->dt_data.dt_text.dt_data, + mime->mm_data.mm_single->dt_data.dt_text.dt_length); + } + break; + case MAILMIME_MESSAGE: + fprintf(stderr, "message %p\n", mime->mm_data.mm_message.mm_msg_mime); + display_recursive_part(mime->mm_data.mm_message.mm_msg_mime); + break; + case MAILMIME_MULTIPLE: + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; cur != NULL ; + cur = clist_next(cur)) { + + fprintf(stderr, "multipart\n"); + display_recursive_part(clist_content(cur)); + } + break; + } +} +#endif + +int mailprivacy_msg_get_bodystructure(struct mailprivacy * privacy, + mailmessage * msg_info, + struct mailmime ** result) +{ + int r; + struct mailmime * mime; + + if (msg_info->msg_mime != NULL) + return MAIL_NO_ERROR; + + if (msg_is_modified(privacy, msg_info)) + return MAIL_NO_ERROR; + + r = mailmessage_get_bodystructure(msg_info, &mime); + if (r != MAIL_NO_ERROR) + return r; + + /* modification on message if necessary */ + r = recursive_check_privacy(privacy, msg_info, msg_info->msg_mime); + if (r != MAIL_NO_ERROR) { + * result = msg_info->msg_mime; + return MAIL_NO_ERROR; + } + + r = register_msg(privacy, msg_info); + if (r != MAIL_NO_ERROR) { + recursive_clear_registered_mime(privacy, mime); + mailmessage_flush(msg_info); + return MAIL_ERROR_MEMORY; + } + + * result = msg_info->msg_mime; + + return MAIL_NO_ERROR; +} + +void mailprivacy_msg_flush(struct mailprivacy * privacy, + mailmessage * msg_info) +{ + if (msg_is_modified(privacy, msg_info)) { + /* remove all modified parts */ + if (msg_info->msg_mime != NULL) + recursive_clear_registered_mime(privacy, msg_info->msg_mime); + unregister_message(privacy, msg_info); + } + + mailmessage_flush(msg_info); +} + +static int fetch_registered_part(struct mailprivacy * privacy, + int (* fetch_section)(mailmessage *, struct mailmime *, + char **, size_t *), + struct mailmime * mime, + char ** result, size_t * result_len) +{ + mailmessage * dummy_msg; + int res; + char * content; + size_t content_len; + int r; + + dummy_msg = mime_message_init(NULL); + if (dummy_msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mime_message_set_tmpdir(dummy_msg, privacy->tmp_dir); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto free_msg; + } + + r = fetch_section(dummy_msg, mime, &content, &content_len); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_msg; + } + + r = register_result_mmapstr(privacy, content); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_fetch; + } + + mailmessage_free(dummy_msg); + + * result = content; + * result_len = content_len; + + return MAIL_NO_ERROR; + + free_fetch: + mailmessage_fetch_result_free(dummy_msg, content); + free_msg: + mailmessage_free(dummy_msg); + err: + return res; +} + +int mailprivacy_msg_fetch_section(struct mailprivacy * privacy, + mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + if (msg_is_modified(privacy, msg_info) && + mime_is_registered(privacy, mime)) { + return fetch_registered_part(privacy, mailmessage_fetch_section, + mime, result, result_len); + } + + return mailmessage_fetch_section(msg_info, mime, result, result_len); +} + +int mailprivacy_msg_fetch_section_header(struct mailprivacy * privacy, + mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + if (msg_is_modified(privacy, msg_info) && + mime_is_registered(privacy, mime)) { + return fetch_registered_part(privacy, mailmessage_fetch_section_header, + mime, result, result_len); + } + + return mailmessage_fetch_section_header(msg_info, mime, result, result_len); +} + +int mailprivacy_msg_fetch_section_mime(struct mailprivacy * privacy, + mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + if (msg_is_modified(privacy, msg_info) && + mime_is_registered(privacy, mime)) { + return fetch_registered_part(privacy, mailmessage_fetch_section_mime, + mime, result, result_len); + } + + return mailmessage_fetch_section_mime(msg_info, mime, result, result_len); +} + +int mailprivacy_msg_fetch_section_body(struct mailprivacy * privacy, + mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + if (msg_is_modified(privacy, msg_info) && + mime_is_registered(privacy, mime)) { + return fetch_registered_part(privacy, mailmessage_fetch_section_body, + mime, result, result_len); + } + + return mailmessage_fetch_section_body(msg_info, mime, result, result_len); +} + +void mailprivacy_msg_fetch_result_free(struct mailprivacy * privacy, + mailmessage * msg_info, + char * msg) +{ + if (msg == NULL) + return; + + if (msg_is_modified(privacy, msg_info)) { + if (result_is_mmapstr(privacy, msg)) { + unregister_result_mmapstr(privacy, msg); + return; + } + } + + mailmessage_fetch_result_free(msg_info, msg); +} + +int mailprivacy_msg_fetch(struct mailprivacy * privacy, + mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + return mailmessage_fetch(msg_info, result, result_len); +} + +int mailprivacy_msg_fetch_header(struct mailprivacy * privacy, + mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + return mailmessage_fetch_header(msg_info, result, result_len); +} + +/* end of fetch operations */ +/* **************************************************** */ + +static int privacy_handler(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result); + + + +static struct mailmime * +mime_add_alternative(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, + struct mailmime * alternative) +{ + struct mailmime * multipart; + int r; + struct mailmime * mime_copy; + char original_filename[PATH_MAX]; + + if (mime->mm_parent == NULL) + goto err; + + r = mailmime_new_with_content("multipart/alternative", NULL, &multipart); + if (r != MAILIMF_NO_ERROR) + goto err; + + r = mailmime_smart_add_part(multipart, alternative); + if (r != MAILIMF_NO_ERROR) { + goto free_multipart; + } + + /* get copy of mime part "mime" and set parts */ + + r = mailprivacy_fetch_mime_body_to_file(privacy, + original_filename, sizeof(original_filename), + msg, mime); + if (r != MAIL_NO_ERROR) + goto detach_alternative; + + r = mailprivacy_get_part_from_file(privacy, 0, 0, + original_filename, &mime_copy); + unlink(original_filename); + if (r != MAIL_NO_ERROR) { + goto detach_alternative; + } + + r = mailmime_smart_add_part(multipart, mime_copy); + if (r != MAILIMF_NO_ERROR) { + goto free_mime_copy; + } + + r = recursive_register_mime(privacy, multipart); + if (r != MAIL_NO_ERROR) + goto detach_mime_copy; + + mailmime_substitute(mime, multipart); + + mailmime_free(mime); + + return multipart; + + detach_mime_copy: + mailprivacy_recursive_unregister_mime(privacy, multipart); + mailmime_remove_part(alternative); + free_mime_copy: + mailprivacy_mime_clear(mime_copy); + mailmime_free(mime_copy); + detach_alternative: + mailmime_remove_part(alternative); + free_multipart: + mailmime_free(multipart); + err: + return NULL; +} + +/* + recursive_check_privacy returns MAIL_NO_ERROR if at least one + part is using a privacy protocol. +*/ + +static int recursive_check_privacy(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime) +{ + int r; + clistiter * cur; + struct mailmime * alternative; + int res; + struct mailmime * multipart; + + if (privacy == NULL) + return MAIL_NO_ERROR; + + if (mime_is_registered(privacy, mime)) + return MAIL_ERROR_INVAL; + + r = privacy_handler(privacy, msg, mime, &alternative); + if (r == MAIL_NO_ERROR) { + if (privacy->make_alternative) { + multipart = mime_add_alternative(privacy, msg, mime, alternative); + if (multipart == NULL) { + mailprivacy_mime_clear(alternative); + mailmime_free(alternative); + return MAIL_ERROR_MEMORY; + } + } + else { + mailmime_substitute(mime, alternative); + mailmime_free(mime); + mime = NULL; + } + + return MAIL_NO_ERROR; + } + else { + switch (mime->mm_type) { + case MAILMIME_SINGLE: + return MAIL_ERROR_INVAL; + + case MAILMIME_MULTIPLE: + res = MAIL_ERROR_INVAL; + + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * child; + + child = clist_content(cur); + + r = recursive_check_privacy(privacy, msg, child); + if (r == MAIL_NO_ERROR) + res = MAIL_NO_ERROR; + } + + return res; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_msg_mime != NULL) + return recursive_check_privacy(privacy, msg, + mime->mm_data.mm_message.mm_msg_mime); + return MAIL_ERROR_INVAL; + + default: + return MAIL_ERROR_INVAL; + } + } +} + +static int privacy_handler(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + int r; + struct mailmime * alternative_mime; + unsigned int i; + + alternative_mime = NULL; + for(i = 0 ; i < carray_count(privacy->protocols) ; i ++) { + struct mailprivacy_protocol * protocol; + + protocol = carray_get(privacy->protocols, i); + + if (protocol->decrypt != NULL) { + r = protocol->decrypt(privacy, msg, mime, &alternative_mime); + if (r == MAIL_NO_ERROR) { + + * result = alternative_mime; + + return MAIL_NO_ERROR; + } + } + } + + return MAIL_ERROR_INVAL; +} + +int mailprivacy_register(struct mailprivacy * privacy, + struct mailprivacy_protocol * protocol) +{ + int r; + + r = carray_add(privacy->protocols, protocol, NULL); + if (r < 0) + return MAIL_ERROR_MEMORY; + + return MAIL_NO_ERROR; +} + +void mailprivacy_unregister(struct mailprivacy * privacy, + struct mailprivacy_protocol * protocol) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(privacy->protocols) ; i ++) { + if (carray_get(privacy->protocols, i) == protocol) { + carray_delete(privacy->protocols, i); + return; + } + } +} + +static struct mailprivacy_protocol * +get_protocol(struct mailprivacy * privacy, char * privacy_driver) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(privacy->protocols) ; i ++) { + struct mailprivacy_protocol * protocol; + + protocol = carray_get(privacy->protocols, i); + if (strcasecmp(protocol->name, privacy_driver) == 0) + return protocol; + } + + return NULL; +} + +static struct mailprivacy_encryption * +get_encryption(struct mailprivacy_protocol * protocol, + char * privacy_encryption) +{ + int i; + + for(i = 0 ; i < protocol->encryption_count ; i ++) { + struct mailprivacy_encryption * encryption; + + encryption = &protocol->encryption_tab[i]; + if (strcasecmp(encryption->name, privacy_encryption) == 0) + return encryption; + } + + return NULL; +} + +int mailprivacy_encrypt(struct mailprivacy * privacy, + char * privacy_driver, char * privacy_encryption, + struct mailmime * mime, + struct mailmime ** result) +{ + return mailprivacy_encrypt_msg(privacy, privacy_driver, privacy_encryption, + NULL, mime, result); +} + +int mailprivacy_encrypt_msg(struct mailprivacy * privacy, + char * privacy_driver, char * privacy_encryption, + mailmessage * msg, + struct mailmime * mime, + struct mailmime ** result) +{ + struct mailprivacy_protocol * protocol; + struct mailprivacy_encryption * encryption; + int r; + + protocol = get_protocol(privacy, privacy_driver); + if (protocol == NULL) + return MAIL_ERROR_INVAL; + + encryption = get_encryption(protocol, privacy_encryption); + if (encryption == NULL) + return MAIL_ERROR_INVAL; + + if (encryption->encrypt == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + r = encryption->encrypt(privacy, msg, mime, result); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; +} + +char * mailprivacy_get_encryption_name(struct mailprivacy * privacy, + char * privacy_driver, char * privacy_encryption) +{ + struct mailprivacy_protocol * protocol; + struct mailprivacy_encryption * encryption; + + protocol = get_protocol(privacy, privacy_driver); + if (protocol == NULL) + return NULL; + + encryption = get_encryption(protocol, privacy_encryption); + if (encryption == NULL) + return NULL; + + return encryption->description; +} + +int mailprivacy_is_encrypted(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime) +{ + unsigned int i; + + if (mime_is_registered(privacy, mime)) + return 0; + + for(i = 0 ; i < carray_count(privacy->protocols) ; i ++) { + struct mailprivacy_protocol * protocol; + + protocol = carray_get(privacy->protocols, i); + + if (protocol->is_encrypted != NULL) { + if (protocol->is_encrypted(privacy, msg, mime)) + return 1; + } + } + + return 0; +} + +void mailprivacy_debug(struct mailprivacy * privacy, FILE * f) +{ + fprintf(f, "privacy debug -- begin\n"); + fprintf(f, "registered message: %i\n", chash_count(privacy->msg_ref)); + fprintf(f, "registered MMAPStr: %i\n", chash_count(privacy->mmapstr)); + fprintf(f, "registered mailmime: %i\n", chash_count(privacy->mime_ref)); + fprintf(f, "privacy debug -- end\n"); +} diff --git a/Sources/libetpan/engine/mailprivacy.h b/Sources/libetpan/engine/mailprivacy.h new file mode 100644 index 00000000..61ec039c --- /dev/null +++ b/Sources/libetpan/engine/mailprivacy.h @@ -0,0 +1,145 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailprivacy.h,v 1.6 2007/12/10 21:32:59 hoa Exp $ + */ + +#ifndef MAILPRIVACY_H + +#define MAILPRIVACY_H + +#include +#include +#include + +LIBETPAN_EXPORT +struct mailprivacy * mailprivacy_new(char * tmp_dir, int make_alternative); + +LIBETPAN_EXPORT +void mailprivacy_free(struct mailprivacy * privacy); + +LIBETPAN_EXPORT +int mailprivacy_msg_get_bodystructure(struct mailprivacy * privacy, + mailmessage * msg_info, + struct mailmime ** result); + +LIBETPAN_EXPORT +void mailprivacy_msg_flush(struct mailprivacy * privacy, + mailmessage * msg_info); + +LIBETPAN_EXPORT +int mailprivacy_msg_fetch_section(struct mailprivacy * privacy, + mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + +LIBETPAN_EXPORT +int mailprivacy_msg_fetch_section_header(struct mailprivacy * privacy, + mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +LIBETPAN_EXPORT +int mailprivacy_msg_fetch_section_mime(struct mailprivacy * privacy, + mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +LIBETPAN_EXPORT +int mailprivacy_msg_fetch_section_body(struct mailprivacy * privacy, + mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +LIBETPAN_EXPORT +void mailprivacy_msg_fetch_result_free(struct mailprivacy * privacy, + mailmessage * msg_info, + char * msg); + +LIBETPAN_EXPORT +int mailprivacy_msg_fetch(struct mailprivacy * privacy, + mailmessage * msg_info, + char ** result, + size_t * result_len); + +LIBETPAN_EXPORT +int mailprivacy_msg_fetch_header(struct mailprivacy * privacy, + mailmessage * msg_info, + char ** result, + size_t * result_len); + +LIBETPAN_EXPORT +int mailprivacy_register(struct mailprivacy * privacy, + struct mailprivacy_protocol * protocol); + +LIBETPAN_EXPORT +void mailprivacy_unregister(struct mailprivacy * privacy, + struct mailprivacy_protocol * protocol); + +LIBETPAN_EXPORT +char * mailprivacy_get_encryption_name(struct mailprivacy * privacy, + char * privacy_driver, char * privacy_encryption); + +/* deprecated */ +LIBETPAN_EXPORT +int mailprivacy_encrypt(struct mailprivacy * privacy, + char * privacy_driver, char * privacy_encryption, + struct mailmime * mime, + struct mailmime ** result); + +/* introduced the use of passphrase */ +LIBETPAN_EXPORT +int mailprivacy_encrypt_msg(struct mailprivacy * privacy, + char * privacy_driver, char * privacy_encryption, + mailmessage * msg, + struct mailmime * mime, + struct mailmime ** result); + +LIBETPAN_EXPORT +void mailprivacy_debug(struct mailprivacy * privacy, FILE * f); + +LIBETPAN_EXPORT +carray * mailprivacy_get_protocols(struct mailprivacy * privacy); + +LIBETPAN_EXPORT +int mailprivacy_is_encrypted(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime); + +LIBETPAN_EXPORT +void mailprivacy_recursive_unregister_mime(struct mailprivacy * privacy, + struct mailmime * mime); + +#endif diff --git a/Sources/libetpan/engine/mailprivacy_gnupg.c b/Sources/libetpan/engine/mailprivacy_gnupg.c new file mode 100644 index 00000000..93ebf929 --- /dev/null +++ b/Sources/libetpan/engine/mailprivacy_gnupg.c @@ -0,0 +1,3045 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailprivacy_gnupg.c,v 1.14 2011/05/03 16:30:22 hoa Exp $ + */ + +/* passphrase is needed when private key is needed + private key is needed : + - to sign a message + - and to decrypt a message +*/ +#define HAVE_CONFIG_H 1 + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailprivacy_gnupg.h" + +#include "mailprivacy.h" +#include +#include +#include +#include +#ifdef WIN32 +# include "win_etpan.h" +#else +# include +# include +#endif +#include +#include +#include "mailprivacy_tools.h" +#include "mailprivacy_tools_private.h" +#include +#include +#ifdef LIBETPAN_REENTRANT +#if defined(HAVE_PTHREAD_H) && !defined(IGNORE_PTHREAD_H) +#include +#elif (defined WIN32) +#include +#endif +#endif +#include + +enum { + NO_ERROR_PGP = 0, + ERROR_PGP_CHECK, + ERROR_PGP_COMMAND, + ERROR_PGP_FILE, + ERROR_PGP_NOPASSPHRASE +}; + +static int mailprivacy_gnupg_add_encryption_id(struct mailprivacy * privacy, + mailmessage * msg, char * encryption_id); +static char * get_passphrase(struct mailprivacy * privacy, + char * user_id); +static int get_userid(char * filename, char * username, size_t length); + + +static int gpg_command_passphrase(struct mailprivacy * privacy, + struct mailmessage * msg, + char * command, char * userid, + char * stdoutfile, char * stderrfile) +{ + char * passphrase; + int bad_passphrase; + int res; + int r; + + bad_passphrase = 0; + + passphrase = NULL; + if (userid != NULL) + passphrase = get_passphrase(privacy, userid); + + res = mailprivacy_spawn_and_wait(command, passphrase, stdoutfile, stderrfile, + &bad_passphrase); + if (res != NO_ERROR_PASSPHRASE) { + switch (res) { + case ERROR_PASSPHRASE_COMMAND: + return ERROR_PGP_COMMAND; + case ERROR_PASSPHRASE_FILE: + return ERROR_PGP_FILE; + default: + return ERROR_PGP_COMMAND; + } + return res; + } + + if (bad_passphrase && (userid == NULL)) { + char encryption_id[4096]; + + encryption_id[0] = '\0'; + r = get_userid(stderrfile, encryption_id, sizeof(encryption_id)); + if (r == 0) { + passphrase = get_passphrase(privacy, encryption_id); + if (passphrase == NULL) { + mailprivacy_gnupg_add_encryption_id(privacy, msg, encryption_id); + return ERROR_PGP_NOPASSPHRASE; + } + else { + free(passphrase); + return gpg_command_passphrase(privacy, msg, command, encryption_id, + stdoutfile, stderrfile); + } + } + else { + return ERROR_PGP_CHECK; + } + } + + if (bad_passphrase && (passphrase != NULL)) { + return ERROR_PGP_CHECK; + } + + if (bad_passphrase) { + mailprivacy_gnupg_add_encryption_id(privacy, msg, userid); + return ERROR_PGP_NOPASSPHRASE; + } + + return NO_ERROR_PGP; +} + +static int pgp_is_encrypted(struct mailmime * mime) +{ + if (mime->mm_content_type != NULL) { + clistiter * cur; + + if (strcasecmp(mime->mm_content_type->ct_subtype, "encrypted") != 0) + return 0; + + for(cur = clist_begin(mime->mm_content_type->ct_parameters) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = clist_content(cur); + + if ((strcasecmp(param->pa_name, "protocol") == 0) && + (strcasecmp(param->pa_value, "application/pgp-encrypted") == 0)) + return 1; + } + } + + return 0; +} + +static int pgp_is_signed(struct mailmime * mime) +{ + if (mime->mm_content_type != NULL) { + clistiter * cur; + + if (strcasecmp(mime->mm_content_type->ct_subtype, "signed") != 0) + return 0; + + for(cur = clist_begin(mime->mm_content_type->ct_parameters) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = clist_content(cur); + + if ((strcasecmp(param->pa_name, "protocol") == 0) && + (strcasecmp(param->pa_value, "application/pgp-signature") == 0)) + return 1; + } + } + + return 0; +} + +#define PGP_SIGNED "-----BEGIN PGP SIGNED MESSAGE-----" + +int pgp_is_clearsigned(char * data, size_t len) +{ + if (len >= strlen(PGP_SIGNED)) + if (strncmp(data, PGP_SIGNED, sizeof(PGP_SIGNED) - 1) == 0) + return 1; + + return 0; +} + +#define PGP_CRYPTED "-----BEGIN PGP MESSAGE-----" + +int pgp_is_crypted_armor(char * data, size_t len) +{ + if (len >= strlen(PGP_CRYPTED)) + if (strncmp(data, PGP_CRYPTED, sizeof(PGP_CRYPTED) - 1) == 0) + return 1; + + return 0; +} + + +#if 0 +#define BUF_SIZE 1024 + +/* write output to a file */ + +static int get_pgp_output(FILE * dest_f, char * command) +{ + FILE * p; + char buf[BUF_SIZE]; + size_t size; + int res; + int status; + char command_redirected[PATH_MAX]; + + snprintf(command_redirected, sizeof(command_redirected), "%s 2>&1", command); + + /* + flush buffer so that it is not flushed more than once when forking + */ + fflush(dest_f); + + p = popen(command_redirected, "r"); + if (p == NULL) { + res = ERROR_PGP_COMMAND; + goto err; + } + + while ((size = fread(buf, 1, sizeof(buf), p)) != 0) { + size_t written; + + written = fwrite(buf, 1, size, dest_f); + if (written != size) { + res = ERROR_PGP_FILE; + goto close; + } + } + status = pclose(p); + + if (WEXITSTATUS(status) != 0) + return ERROR_PGP_CHECK; + else + return NO_ERROR_PGP; + + close: + pclose(p); + err: + return res; +} +#endif + +/* parse output */ + +enum { + STATE_USERID, + STATE_NORMAL +}; + +static int get_userid(char * filename, char * username, size_t length) +{ + FILE * f; + int state; + char buffer[4096]; + int exit_code; + + exit_code = -1; + + f = fopen(filename, "r"); + if (f == NULL) + goto exit; + + state = STATE_NORMAL; + while (fgets(buffer, sizeof(buffer), f) != NULL) { + + switch (state) { + case STATE_NORMAL: + if (strncmp(buffer, "gpg: encrypted", 14) == 0) + state = STATE_USERID; + break; + + case STATE_USERID: + { + struct mailimf_mailbox * mb; + size_t current_index; + int r; + size_t buflen; + size_t i; + char * beginning; + + /* find double-quotes and remove beginning and ending */ + + buflen = strlen(buffer); + for(i = buflen - 1 ; 1 ; i --) { + if (buffer[i] == '\"') { + buffer[i] = '\0'; + break; + } + + if (i == 0) + break; + } + + beginning = buffer; + for(i = 0 ; i < buflen ; i ++) { + if (buffer[i] == '\"') { + beginning = buffer + i + 1; + break; + } + } + + r = mailimf_mailbox_parse(beginning, strlen(beginning), + ¤t_index, &mb); + if (r == MAILIMF_NO_ERROR) { + strncpy(username, mb->mb_addr_spec, length); + username[length - 1] = '\0'; + mailimf_mailbox_free(mb); + exit_code = 0; + } + + state = STATE_NORMAL; + } + break; + } + } + + fclose(f); + + exit: + return exit_code; +} + +#define PGP_DECRYPT_DESCRIPTION "PGP encrypted part\r\n" +#define PGP_DECRYPT_FAILED "PGP decryption FAILED\r\n" +#define PGP_DECRYPT_SUCCESS "PGP decryption success\r\n" + +/* extracted from mailprivacy_smime.c -- begin */ + +static char * get_first_from_addr(struct mailmime * mime) +{ + clistiter * cur; + struct mailimf_single_fields single_fields; + struct mailimf_fields * fields; + struct mailimf_mailbox * mb; + + if (mime->mm_type != MAILMIME_MESSAGE) + return NULL; + + fields = mime->mm_data.mm_message.mm_fields; + if (fields == NULL) + return NULL; + + mailimf_single_fields_init(&single_fields, fields); + + if (single_fields.fld_from == NULL) + return NULL; + + cur = clist_begin(single_fields.fld_from->frm_mb_list->mb_list); + if (cur == NULL) + return NULL; + + mb = clist_content(cur); + + return mb->mb_addr_spec; +} + +/* extracted from mailprivacy_smime.c -- end */ + +static int pgp_decrypt(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + struct mailmime * encrypted_mime; + clistiter * cur; + char encrypted_filename[PATH_MAX]; + char description_filename[PATH_MAX]; + char decrypted_filename[PATH_MAX]; + char command[PATH_MAX]; + struct mailmime * description_mime; + struct mailmime * decrypted_mime; + int r; + int res; + int decrypt_ok; + char quoted_encrypted_filename[PATH_MAX]; + struct mailmime * multipart; + + /* get the two parts of the PGP message */ + + cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list); + if (cur == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + cur = clist_next(cur); + if (cur == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + encrypted_mime = clist_content(cur); + + /* fetch the second section, that's the useful one */ + + r = mailprivacy_fetch_decoded_to_file(privacy, + encrypted_filename, sizeof(encrypted_filename), + msg, encrypted_mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + /* we are in a safe directory */ + + r = mailprivacy_get_tmp_filename(privacy, + decrypted_filename, sizeof(decrypted_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_encrypted; + } + + /* description */ + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_decrypted; + } + + /* run the command */ + + r = mail_quote_filename(quoted_encrypted_filename, + sizeof(quoted_encrypted_filename), encrypted_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + snprintf(command, sizeof(command), + "gpg --passphrase-fd=0 --batch --yes --decrypt '%s'", + quoted_encrypted_filename); + + decrypt_ok = 0; + r = gpg_command_passphrase(privacy, msg, command, NULL, + decrypted_filename, description_filename); + switch (r) { + case NO_ERROR_PGP: + decrypt_ok = 1; + break; + case ERROR_PGP_NOPASSPHRASE: + case ERROR_PGP_CHECK: + decrypt_ok = 0; + break; + case ERROR_PGP_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + case ERROR_PGP_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + if (!decrypt_ok) { + char encryption_id[4096]; + + encryption_id[0] = '\0'; + r = get_userid(description_filename, encryption_id, sizeof(encryption_id)); + if (r == 0) { + mailprivacy_gnupg_add_encryption_id(privacy, msg, encryption_id); + } + } + + /* building multipart */ + + r = mailmime_new_with_content("multipart/x-decrypted", NULL, &multipart); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* building the description part */ + + description_mime = mailprivacy_new_file_part(privacy, + description_filename, + "text/plain", MAILMIME_MECHANISM_8BIT); + if (description_mime == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* adds the description part */ + + r = mailmime_smart_add_part(multipart, description_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(description_mime); + mailmime_free(description_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* building the decrypted part */ + + r = mailprivacy_get_part_from_file(privacy, 1, 0, + decrypted_filename, &decrypted_mime); + if (r == MAIL_NO_ERROR) { + /* adds the decrypted part */ + + r = mailmime_smart_add_part(multipart, decrypted_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(decrypted_mime); + mailmime_free(decrypted_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + } + + unlink(description_filename); + unlink(decrypted_filename); + unlink(encrypted_filename); + + * result = multipart; + + return MAIL_NO_ERROR; + + unlink_description: + unlink(description_filename); + unlink_decrypted: + unlink(decrypted_filename); + unlink_encrypted: + unlink(encrypted_filename); + err: + return res; +} + +#define PGP_VERIFY_DESCRIPTION "PGP verify signed message\r\n" +#define PGP_VERIFY_FAILED "PGP verification FAILED\r\n" +#define PGP_VERIFY_SUCCESS "PGP verification success\r\n" + +static int +pgp_verify(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + struct mailmime * signed_mime; + struct mailmime * signature_mime; + char signed_filename[PATH_MAX]; + char signature_filename[PATH_MAX]; + int res; + int r; + clistiter * cur; + char command[PATH_MAX]; + struct mailmime * description_mime; + char decrypted_filename[PATH_MAX]; + char description_filename[PATH_MAX]; + char quoted_signed_filename[PATH_MAX]; + char quoted_signature_filename[PATH_MAX]; + struct mailmime * multipart; + struct mailmime * signed_msg_mime; + + /* get the two parts of the PGP message */ + + cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list); + if (cur == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + signed_mime = clist_content(cur); + cur = clist_next(cur); + if (cur == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + signature_mime = clist_content(cur); + + /* fetch signed part and write it to a file */ + + r = mailprivacy_fetch_mime_body_to_file(privacy, + signed_filename, sizeof(signed_filename), + msg, signed_mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + /* fetch signed part and write it to a file */ + + r = mailprivacy_fetch_decoded_to_file(privacy, + signature_filename, sizeof(signature_filename), + msg, signature_mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_signed; + } + + /* description */ + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_signature; + } + + /* decrypted (dummy) */ + + r = mailprivacy_get_tmp_filename(privacy, decrypted_filename, + sizeof(decrypted_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_description; + } + + /* run the command */ + + r = mail_quote_filename(quoted_signature_filename, + sizeof(quoted_signature_filename), signature_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_decrypted; + } + + r = mail_quote_filename(quoted_signed_filename, + sizeof(quoted_signed_filename), signed_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_decrypted; + } + + snprintf(command, sizeof(command), "gpg --batch --yes --verify '%s' '%s'", + quoted_signature_filename, quoted_signed_filename); + + r = gpg_command_passphrase(privacy, msg, command, NULL, + decrypted_filename, description_filename); + switch (r) { + case NO_ERROR_PGP: + break; + case ERROR_PGP_NOPASSPHRASE: + case ERROR_PGP_CHECK: + break; + case ERROR_PGP_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_decrypted; + case ERROR_PGP_FILE: + res = MAIL_ERROR_FILE; + goto unlink_decrypted; + } + + /* building multipart */ + + r = mailmime_new_with_content("multipart/x-verified", NULL, &multipart); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto unlink_decrypted; + } + + /* building the description part */ + + description_mime = mailprivacy_new_file_part(privacy, + description_filename, + "text/plain", MAILMIME_MECHANISM_8BIT); + if (description_mime == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_decrypted; + } + + /* adds the description part */ + + r = mailmime_smart_add_part(multipart, description_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(description_mime); + mailmime_free(description_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_decrypted; + } + + r = mailprivacy_get_part_from_file(privacy, 1, 0, + signed_filename, &signed_msg_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_decrypted; + } + + r = mailmime_smart_add_part(multipart, signed_msg_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(signed_msg_mime); + mailmime_free(signed_msg_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_decrypted; + } + + unlink(decrypted_filename); + unlink(description_filename); + unlink(signature_filename); + unlink(signed_filename); + + * result = multipart; + + return MAIL_NO_ERROR; + + unlink_decrypted: + unlink(decrypted_filename); + unlink_description: + unlink(description_filename); + unlink_signature: + unlink(signature_filename); + unlink_signed: + unlink(signed_filename); + err: + return res; +} + + +#define PGP_CLEAR_VERIFY_DESCRIPTION "PGP verify clear signed message\r\n" +#define PGP_CLEAR_VERIFY_FAILED "PGP verification FAILED\r\n" +#define PGP_CLEAR_VERIFY_SUCCESS "PGP verification success\r\n" + +static int pgp_verify_clearsigned(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, + char * content, size_t content_len, struct mailmime ** result) +{ + int r; + char command[PATH_MAX]; + int res; + size_t written; + char signed_filename[PATH_MAX]; + FILE * signed_f; + char stripped_filename[PATH_MAX]; + char description_filename[PATH_MAX]; + char quoted_signed_filename[PATH_MAX]; + struct mailmime * stripped_mime; + struct mailmime * description_mime; + struct mailmime * multipart; + struct mailmime_content * content_type; + + if (mime->mm_parent == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + if (mime->mm_parent->mm_type == MAILMIME_SINGLE) { + res = MAIL_ERROR_INVAL; + goto err; + } + + signed_f = mailprivacy_get_tmp_file(privacy, + signed_filename, sizeof(signed_filename)); + if (signed_f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + written = fwrite(content, 1, content_len, signed_f); + if (written != content_len) { + fclose(signed_f); + unlink(signed_filename); + res = MAIL_ERROR_FILE; + goto err; + } + fclose(signed_f); + + /* XXX - prepare file for PGP, remove trailing WS */ + + r = mailprivacy_get_tmp_filename(privacy, stripped_filename, + sizeof(stripped_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_signed; + } + + /* description */ + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_stripped; + } + + r = mail_quote_filename(quoted_signed_filename, + sizeof(quoted_signed_filename), signed_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + snprintf(command, sizeof(command), + "gpg --batch --yes --decrypt '%s'", quoted_signed_filename); + + r = gpg_command_passphrase(privacy, msg, command, NULL, + stripped_filename, description_filename); + switch (r) { + case NO_ERROR_PGP: + break; + case ERROR_PGP_NOPASSPHRASE: + case ERROR_PGP_CHECK: + break; + case ERROR_PGP_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + case ERROR_PGP_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + /* building multipart */ + + r = mailmime_new_with_content("multipart/x-verified", NULL, &multipart); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* building the description part */ + + description_mime = mailprivacy_new_file_part(privacy, + description_filename, + "text/plain", MAILMIME_MECHANISM_8BIT); + if (description_mime == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* adds the description part */ + + r = mailmime_smart_add_part(multipart, description_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(description_mime); + mailmime_free(description_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* building the signature stripped part */ + + stripped_mime = mailprivacy_new_file_part(privacy, + stripped_filename, + "application/octet-stream", + MAILMIME_MECHANISM_8BIT); + if (stripped_mime == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* place original content type */ + + content_type = mailmime_content_dup(mime->mm_content_type); + if (content_type == NULL) { + mailprivacy_mime_clear(stripped_mime); + mailmime_free(stripped_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + mailmime_content_free(stripped_mime->mm_content_type); + stripped_mime->mm_content_type = content_type; + + /* place original MIME fields */ + + if (mime->mm_mime_fields != NULL) { + struct mailmime_fields * mime_fields; + clistiter * cur; + + mime_fields = mailprivacy_mime_fields_dup(privacy, mime->mm_mime_fields); + if (mime_fields == NULL) { + mailprivacy_mime_clear(stripped_mime); + mailmime_free(stripped_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + for(cur = clist_begin(mime_fields->fld_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + if (field->fld_type == MAILMIME_FIELD_TRANSFER_ENCODING) { + mailmime_field_free(field); + clist_delete(mime_fields->fld_list, cur); + break; + } + } + clist_concat(stripped_mime->mm_mime_fields->fld_list, + mime_fields->fld_list); + mailmime_fields_free(mime_fields); + } + + /* adds the stripped part */ + + r = mailmime_smart_add_part(multipart, stripped_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(stripped_mime); + mailmime_free(stripped_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + unlink(description_filename); + unlink(stripped_filename); + unlink(signed_filename); + + * result = multipart; + + return MAIL_NO_ERROR; + + unlink_description: + unlink(description_filename); + unlink_stripped: + unlink(stripped_filename); + unlink_signed: + unlink(signed_filename); + err: + return res; +} + + +#define PGP_DECRYPT_ARMOR_DESCRIPTION "PGP ASCII armor encrypted part\r\n" +#define PGP_DECRYPT_ARMOR_FAILED "PGP ASCII armor decryption FAILED\r\n" +#define PGP_DECRYPT_ARMOR_SUCCESS "PGP ASCII armor decryption success\r\n" + +static int pgp_decrypt_armor(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, + char * content, size_t content_len, struct mailmime ** result) +{ + FILE * encrypted_f; + char encrypted_filename[PATH_MAX]; + char description_filename[PATH_MAX]; + char decrypted_filename[PATH_MAX]; + size_t written; + char command[PATH_MAX]; + struct mailmime * description_mime; + struct mailmime * decrypted_mime; + struct mailmime * multipart; + int r; + int res; + char quoted_encrypted_filename[PATH_MAX]; + + if (mime->mm_parent == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + if (mime->mm_parent->mm_type == MAILMIME_SINGLE) { + res = MAIL_ERROR_INVAL; + goto err; + } + + encrypted_f = mailprivacy_get_tmp_file(privacy, + encrypted_filename, + sizeof(encrypted_filename)); + if (encrypted_f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + written = fwrite(content, 1, content_len, encrypted_f); + if (written != content_len) { + fclose(encrypted_f); + unlink(encrypted_filename); + res = MAIL_ERROR_FILE; + goto err; + } + + fclose(encrypted_f); + + /* we are in a safe directory */ + + r = mailprivacy_get_tmp_filename(privacy, decrypted_filename, + sizeof(decrypted_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_encrypted; + } + + /* description */ + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_decrypted; + } + + /* run the command */ + + r = mail_quote_filename(quoted_encrypted_filename, + sizeof(quoted_encrypted_filename), encrypted_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + snprintf(command, sizeof(command), + "gpg --passphrase-fd=0 --batch --yes --decrypt '%s'", + quoted_encrypted_filename); + + r = gpg_command_passphrase(privacy, msg, command, NULL, + decrypted_filename, description_filename); + switch (r) { + case NO_ERROR_PGP: + break; + case ERROR_PGP_NOPASSPHRASE: + case ERROR_PGP_CHECK: + break; + case ERROR_PGP_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + case ERROR_PGP_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + /* building multipart */ + + r = mailmime_new_with_content("multipart/x-decrypted", NULL, &multipart); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* building the description part */ + + description_mime = mailprivacy_new_file_part(privacy, + description_filename, + "text/plain", MAILMIME_MECHANISM_8BIT); + if (description_mime == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* adds the description part */ + + r = mailmime_smart_add_part(multipart, description_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(description_mime); + mailmime_free(description_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* building the decrypted part */ + + r = mailprivacy_get_part_from_file(privacy, 1, 0, + decrypted_filename, &decrypted_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = r; + goto unlink_description; + } + + /* adds the decrypted part */ + + r = mailmime_smart_add_part(multipart, decrypted_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(decrypted_mime); + mailmime_free(decrypted_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + unlink(description_filename); + unlink(decrypted_filename); + unlink(encrypted_filename); + + * result = multipart; + + return MAIL_NO_ERROR; + + unlink_description: + unlink(description_filename); + unlink_decrypted: + unlink(decrypted_filename); + unlink_encrypted: + unlink(encrypted_filename); + err: + return res; +} + + +static int mime_is_text(struct mailmime * build_info) +{ + if (build_info->mm_type == MAILMIME_SINGLE) { + if (build_info->mm_content_type != NULL) { + if (build_info->mm_content_type->ct_type->tp_type == + MAILMIME_TYPE_DISCRETE_TYPE) { + if (build_info->mm_content_type->ct_type->tp_data.tp_discrete_type->dt_type == + MAILMIME_DISCRETE_TYPE_TEXT) + return 1; + } + } + else + return 1; + } + + return 0; +} + + +static int pgp_test_encrypted(struct mailprivacy * privacy, + mailmessage * msg, struct mailmime * mime) +{ + int r; + int res; + + switch (mime->mm_type) { + case MAILMIME_MULTIPLE: + return (pgp_is_encrypted(mime) || pgp_is_signed(mime)); + + case MAILMIME_SINGLE: + /* clear sign or ASCII armor encryption */ + if (mime_is_text(mime)) { + char * content; + size_t content_len; + char * parsed_content; + size_t parsed_content_len; + size_t cur_token; + int encoding; + struct mailmime_single_fields single_fields; + + r = mailprivacy_msg_fetch_section(privacy, msg, mime, + &content, &content_len); + if (r != MAIL_NO_ERROR) + return 0; + + mailmime_single_fields_init(&single_fields, mime->mm_mime_fields, + mime->mm_content_type); + if (single_fields.fld_encoding != NULL) + encoding = single_fields.fld_encoding->enc_type; + else + encoding = MAILMIME_MECHANISM_8BIT; + + cur_token = 0; + r = mailmime_part_parse(content, content_len, &cur_token, + encoding, &parsed_content, &parsed_content_len); + mailprivacy_msg_fetch_result_free(privacy, msg, content); + + if (r != MAILIMF_NO_ERROR) + return 0; + + res = 0; + + if (pgp_is_clearsigned(parsed_content, parsed_content_len)) + res = 1; + else if (pgp_is_crypted_armor(parsed_content, parsed_content_len)) + res = 1; + + mmap_string_unref(parsed_content); + + return res; + } + break; + } + + return 0; +} + +static int pgp_handler(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + int r; + struct mailmime * alternative_mime; + + alternative_mime = NULL; + switch (mime->mm_type) { + case MAILMIME_MULTIPLE: + r = MAIL_ERROR_INVAL; + if (pgp_is_encrypted(mime)) { + r = pgp_decrypt(privacy, msg, mime, &alternative_mime); + } + else if (pgp_is_signed(mime)) { + r = pgp_verify(privacy, msg, mime, &alternative_mime); + } + + if (r != MAIL_NO_ERROR) + return r; + + * result = alternative_mime; + + return MAIL_NO_ERROR; + + case MAILMIME_SINGLE: + /* clear sign or ASCII armor encryption */ + if (mime_is_text(mime)) { + char * content; + size_t content_len; + char * parsed_content; + size_t parsed_content_len; + size_t cur_token; + int encoding; + struct mailmime_single_fields single_fields; + + r = mailprivacy_msg_fetch_section(privacy, msg, mime, + &content, &content_len); + if (r != MAIL_NO_ERROR) + return MAIL_ERROR_FETCH; + + mailmime_single_fields_init(&single_fields, mime->mm_mime_fields, + mime->mm_content_type); + if (single_fields.fld_encoding != NULL) + encoding = single_fields.fld_encoding->enc_type; + else + encoding = MAILMIME_MECHANISM_8BIT; + + cur_token = 0; + r = mailmime_part_parse(content, content_len, &cur_token, + encoding, &parsed_content, &parsed_content_len); + mailprivacy_msg_fetch_result_free(privacy, msg, content); + + if (r != MAILIMF_NO_ERROR) + return MAIL_ERROR_PARSE; + + r = MAIL_ERROR_INVAL; + if (pgp_is_clearsigned(parsed_content, + parsed_content_len)) { + r = pgp_verify_clearsigned(privacy, + msg, mime, parsed_content, parsed_content_len, &alternative_mime); + } + else if (pgp_is_crypted_armor(parsed_content, + parsed_content_len)) { + r = pgp_decrypt_armor(privacy, + msg, mime, parsed_content, parsed_content_len, &alternative_mime); + } + + mmap_string_unref(parsed_content); + + if (r != MAIL_NO_ERROR) + return r; + + * result = alternative_mime; + + return MAIL_NO_ERROR; + } + break; + } + + return MAIL_ERROR_INVAL; +} + + +#if 0 +static void prepare_mime_single(struct mailmime * mime) +{ + struct mailmime_single_fields single_fields; + int encoding; + int r; + + if (mime->mime_fields != NULL) { + mailmime_single_fields_init(&single_fields, mime->mime_fields, + mime->content_type); + if (single_fields.encoding != NULL) { + encoding = single_fields.encoding->type; + switch (encoding) { + case MAILMIME_MECHANISM_8BIT: + case MAILMIME_MECHANISM_7BIT: + case MAILMIME_MECHANISM_BINARY: + single_fields.encoding->type = MAILMIME_MECHANISM_QUOTED_PRINTABLE; + break; + } + } + else { + struct mailmime_mechanism * mechanism; + struct mailmime_field * field; + + mechanism = + mailmime_mechanism_new(MAILMIME_MECHANISM_QUOTED_PRINTABLE, NULL); + if (mechanism == NULL) + return; + + field = mailmime_field_new(MAILMIME_FIELD_TRANSFER_ENCODING, + NULL, mechanism, NULL, NULL, 0, NULL, NULL); + if (field == NULL) { + mailmime_mechanism_free(mechanism); + return; + } + + r = clist_append(mime->mime_fields->list, field); + if (r < 0) { + mailmime_field_free(field); + return; + } + } + } + + switch (mime->body->encoding) { + case MAILMIME_MECHANISM_8BIT: + case MAILMIME_MECHANISM_7BIT: + case MAILMIME_MECHANISM_BINARY: + mime->body->encoding = MAILMIME_MECHANISM_QUOTED_PRINTABLE; + mime->body->encoded = 0; + break; + } +} + +/* + prepare_mime() + + we assume we built ourself the message. +*/ + +static void prepare_mime(struct mailmime * mime) +{ + clistiter * cur; + + switch (mime->type) { + case MAILMIME_SINGLE: + if (mime->body != NULL) { + prepare_mime_single(mime); + } + break; + + case MAILMIME_MULTIPLE: + for(cur = clist_begin(mime->list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailmime * child; + + child = cur->data; + + prepare_mime(child); + } + break; + + case MAILMIME_MESSAGE: + if (mime->msg_mime) { + prepare_mime(mime->msg_mime); + } + break; + } +} +#endif + +static int pgp_sign_mime(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + char to_sign_filename[PATH_MAX]; + char quoted_to_sign_filename[PATH_MAX]; + FILE * to_sign_f; + int res; + int r; + int col; + char description_filename[PATH_MAX]; + char signature_filename[PATH_MAX]; + char command[PATH_MAX]; + char default_key[PATH_MAX]; + struct mailmime * signature_mime; + struct mailmime * multipart; + struct mailmime_content * content; + struct mailmime_parameter * param; + struct mailmime * to_sign_msg_mime; + char * dup_signature_filename; + char * email; + int sign_ok; + + /* get signing key */ + + * default_key = '\0'; + email = get_first_from_addr(mime); + if (email != NULL) + snprintf(default_key, sizeof(default_key), + "--default-key %s", email); + + /* part to sign */ + + /* encode quoted printable all text parts */ + + mailprivacy_prepare_mime(mime); + + to_sign_f = mailprivacy_get_tmp_file(privacy, + to_sign_filename, sizeof(to_sign_filename)); + if (to_sign_f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + col = 0; + r = mailmime_write(to_sign_f, &col, mime); + if (r != MAILIMF_NO_ERROR) { + fclose(to_sign_f); + res = MAIL_ERROR_FILE; + goto unlink_to_sign; + } + + fclose(to_sign_f); + + /* prepare destination file for signature */ + + r = mailprivacy_get_tmp_filename(privacy, signature_filename, + sizeof(signature_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_to_sign; + } + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_signature; + } + + r = mail_quote_filename(quoted_to_sign_filename, + sizeof(quoted_to_sign_filename), to_sign_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + snprintf(command, sizeof(command), + "gpg --passphrase-fd=0 -a --batch --yes --digest-algo sha1 %s -b '%s'", + default_key, quoted_to_sign_filename); + + sign_ok = 0; + r = gpg_command_passphrase(privacy, msg, command, NULL, + signature_filename, description_filename); + switch (r) { + case NO_ERROR_PGP: + sign_ok = 1; + break; + case ERROR_PGP_NOPASSPHRASE: + case ERROR_PGP_CHECK: + sign_ok = 0; + break; + case ERROR_PGP_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + case ERROR_PGP_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + if (!sign_ok) { + res = MAIL_ERROR_COMMAND; + goto unlink_description; + } + + /* multipart */ + + multipart = mailprivacy_new_file_part(privacy, NULL, + "multipart/signed", -1); + if (multipart == NULL) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + content = multipart->mm_content_type; + + param = mailmime_param_new_with_data("micalg", "pgp-sha1"); + if (param == NULL) { + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + r = clist_append(content->ct_parameters, param); + if (r < 0) { + mailmime_parameter_free(param); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + param = mailmime_param_new_with_data("protocol", + "application/pgp-signature"); + if (param == NULL) { + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + r = clist_append(content->ct_parameters, param); + if (r < 0) { + mailmime_parameter_free(param); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* signed part */ + + r = mailprivacy_get_part_from_file(privacy, 1, 0, + to_sign_filename, &to_sign_msg_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = r; + goto unlink_description; + } + + mailprivacy_prepare_mime(to_sign_msg_mime); + + r = mailmime_smart_add_part(multipart, to_sign_msg_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(to_sign_msg_mime); + mailmime_free(to_sign_msg_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* signature part */ + + /* reencode the signature file with CRLF */ + dup_signature_filename = mailprivacy_dup_imf_file(privacy, + signature_filename); + if (dup_signature_filename == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + /* replace the signature file */ + unlink(signature_filename); + strncpy(signature_filename, + dup_signature_filename, sizeof(signature_filename)); + signature_filename[sizeof(signature_filename) - 1] = '\0'; + + signature_mime = mailprivacy_new_file_part(privacy, + signature_filename, + "application/pgp-signature", + MAILMIME_MECHANISM_8BIT); + if (signature_mime == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + r = mailmime_smart_add_part(multipart, signature_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(signature_mime); + mailmime_free(signature_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + unlink(description_filename); + unlink(signature_filename); + unlink(to_sign_filename); + + * result = multipart; + + return MAIL_NO_ERROR; + + unlink_description: + unlink(description_filename); + unlink_signature: + unlink(signature_filename); + unlink_to_sign: + unlink(to_sign_filename); + err: + return res; +} + + +/* ********************************************************************* */ +/* find GPG recipient */ + +static int recipient_add_mb(char * recipient, size_t * len, + struct mailimf_mailbox * mb) +{ + char buffer[PATH_MAX]; + size_t buflen; + + if (mb->mb_addr_spec != NULL) { + snprintf(buffer, sizeof(buffer), "-r %s ", mb->mb_addr_spec); + buflen = strlen(buffer); + if (buflen >= * len) + return MAIL_ERROR_MEMORY; + + strncat(recipient, buffer, * len); + (* len) -= buflen; + } + + return MAIL_NO_ERROR; +} + +static int recipient_add_mb_list(char * recipient, size_t * len, + struct mailimf_mailbox_list * mb_list) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = clist_content(cur); + + r = recipient_add_mb(recipient, len, mb); + if (r != MAIL_NO_ERROR) + return r; + } + + return MAIL_NO_ERROR; +} + +static int recipient_add_group(char * recipient, size_t * len, + struct mailimf_group * group) +{ + return recipient_add_mb_list(recipient, len, group->grp_mb_list); +} + +static int recipient_add_addr(char * recipient, size_t * len, + struct mailimf_address * addr) +{ + int r; + + switch (addr->ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + r = recipient_add_mb(recipient, len, addr->ad_data.ad_mailbox); + break; + case MAILIMF_ADDRESS_GROUP: + r = recipient_add_group(recipient, len, addr->ad_data.ad_group); + break; + default: + r = MAIL_ERROR_INVAL; + } + + return r; +} + +static int recipient_add_addr_list(char * recipient, size_t * len, + struct mailimf_address_list * addr_list) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_address * addr; + + addr = clist_content(cur); + + r = recipient_add_addr(recipient, len, addr); + if (r != MAIL_NO_ERROR) + return r; + } + + return MAIL_NO_ERROR; +} + + +static int collect_recipient(char * recipient, size_t size, + struct mailimf_fields * fields) +{ + struct mailimf_single_fields single_fields; + int r; + size_t remaining; + int res; + + * recipient = '\0'; + remaining = size - 1; + + mailimf_single_fields_init(&single_fields, fields); + + if (single_fields.fld_to != NULL) { + r = recipient_add_addr_list(recipient, &remaining, + single_fields.fld_to->to_addr_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + + if (single_fields.fld_cc != NULL) { + r = recipient_add_addr_list(recipient, &remaining, + single_fields.fld_cc->cc_addr_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + + if (single_fields.fld_bcc != NULL) { + if (single_fields.fld_bcc->bcc_addr_list != NULL) { + r = recipient_add_addr_list(recipient, &remaining, + single_fields.fld_bcc->bcc_addr_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + +#define PGP_VERSION "Version: 1\r\n" + +static int pgp_sign_encrypt_mime(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + char original_filename[PATH_MAX]; + FILE * original_f; + int res; + int r; + int col; + char encrypted_filename[PATH_MAX]; + char description_filename[PATH_MAX]; + char version_filename[PATH_MAX]; + FILE * version_f; + char command[PATH_MAX]; + char quoted_original_filename[PATH_MAX]; + struct mailmime * version_mime; + struct mailmime * multipart; + struct mailmime_content * content; + struct mailmime_parameter * param; + struct mailmime * encrypted_mime; + char recipient[PATH_MAX]; + struct mailimf_fields * fields; + struct mailmime * root; + size_t written; + char * email; + int encrypt_ok; + char default_key[PATH_MAX]; + + /* get signing key */ + + * default_key = '\0'; + email = get_first_from_addr(mime); + if (email != NULL) + snprintf(default_key, sizeof(default_key), + "--default-key %s", email); + + root = mime; + while (root->mm_parent != NULL) + root = root->mm_parent; + + fields = NULL; + if (root->mm_type == MAILMIME_MESSAGE) + fields = root->mm_data.mm_message.mm_fields; + + /* recipient */ + + collect_recipient(recipient, sizeof(recipient), fields); + + /* part to encrypt */ + + /* encode quoted printable all text parts */ + + mailprivacy_prepare_mime(mime); + + original_f = mailprivacy_get_tmp_file(privacy, original_filename, + sizeof(original_filename)); + if (original_f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + col = 0; + r = mailmime_write(original_f, &col, mime); + if (r != MAILIMF_NO_ERROR) { + fclose(original_f); + res = MAIL_ERROR_FILE; + goto unlink_original; + } + + fclose(original_f); + + /* prepare destination file for encryption */ + + r = mailprivacy_get_tmp_filename(privacy, encrypted_filename, + sizeof(encrypted_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_original; + } + + r = mail_quote_filename(quoted_original_filename, + sizeof(quoted_original_filename), original_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_encrypted; + } + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_encrypted; + } + + snprintf(command, sizeof(command), + "gpg --passphrase-fd=0 %s -a --batch --yes --digest-algo sha1 -s %s -e '%s'", + recipient, default_key, quoted_original_filename); + + encrypt_ok = 0; + r = gpg_command_passphrase(privacy, msg, command, NULL, + encrypted_filename, description_filename); + switch (r) { + case NO_ERROR_PGP: + encrypt_ok = 1; + break; + case ERROR_PGP_NOPASSPHRASE: + case ERROR_PGP_CHECK: + encrypt_ok = 0; + break; + case ERROR_PGP_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + case ERROR_PGP_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + if (!encrypt_ok) { + res = MAIL_ERROR_COMMAND; + goto unlink_description; + } + + /* multipart */ + + multipart = mailprivacy_new_file_part(privacy, NULL, + "multipart/encrypted", -1); + if (multipart == NULL) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + content = multipart->mm_content_type; + + param = mailmime_param_new_with_data("protocol", + "application/pgp-encrypted"); + if (param == NULL) { + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + r = clist_append(content->ct_parameters, param); + if (r < 0) { + mailmime_parameter_free(param); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* version part */ + + version_f = mailprivacy_get_tmp_file(privacy, + version_filename, + sizeof(version_filename)); + if (version_f == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_FILE; + goto unlink_description; + } + written = fwrite(PGP_VERSION, 1, sizeof(PGP_VERSION) - 1, version_f); + if (written != sizeof(PGP_VERSION) - 1) { + fclose(version_f); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_FILE; + goto unlink_description; + } + fclose(version_f); + + version_mime = mailprivacy_new_file_part(privacy, + version_filename, + "application/pgp-encrypted", + MAILMIME_MECHANISM_8BIT); + if (version_mime == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_version; + } + + r = mailmime_smart_add_part(multipart, version_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(version_mime); + mailmime_free(version_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_version; + } + + /* encrypted part */ + + encrypted_mime = mailprivacy_new_file_part(privacy, + encrypted_filename, + "application/octet-stream", + MAILMIME_MECHANISM_8BIT); + if (encrypted_mime == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_version; + } + + r = mailmime_smart_add_part(multipart, encrypted_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(encrypted_mime); + mailmime_free(encrypted_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_version; + } + + unlink(version_filename); + unlink(description_filename); + unlink(encrypted_filename); + unlink(original_filename); + + * result = multipart; + + return MAIL_NO_ERROR; + + unlink_version: + unlink(version_filename); + unlink_description: + unlink(description_filename); + unlink_encrypted: + unlink(encrypted_filename); + unlink_original: + unlink(original_filename); + err: + return res; +} + + +static int pgp_encrypt_mime(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + char original_filename[PATH_MAX]; + FILE * original_f; + int res; + int r; + int col; + char description_filename[PATH_MAX]; + char encrypted_filename[PATH_MAX]; + char version_filename[PATH_MAX]; + FILE * version_f; + char command[PATH_MAX]; + char quoted_original_filename[PATH_MAX]; + struct mailmime * version_mime; + struct mailmime * multipart; + struct mailmime_content * content; + struct mailmime_parameter * param; + struct mailmime * encrypted_mime; + char recipient[PATH_MAX]; + struct mailimf_fields * fields; + struct mailmime * root; + size_t written; + int encrypt_ok; + + root = mime; + while (root->mm_parent != NULL) + root = root->mm_parent; + + fields = NULL; + if (root->mm_type == MAILMIME_MESSAGE) + fields = root->mm_data.mm_message.mm_fields; + + /* recipient */ + + collect_recipient(recipient, sizeof(recipient), fields); + + /* part to encrypt */ + + /* encode quoted printable all text parts */ + + mailprivacy_prepare_mime(mime); + + original_f = mailprivacy_get_tmp_file(privacy, + original_filename, sizeof(original_filename)); + if (original_f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + col = 0; + r = mailmime_write(original_f, &col, mime); + if (r != MAILIMF_NO_ERROR) { + fclose(original_f); + res = MAIL_ERROR_FILE; + goto unlink_original; + } + + fclose(original_f); + + /* prepare destination file for encryption */ + + r = mailprivacy_get_tmp_filename(privacy, encrypted_filename, + sizeof(encrypted_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_original; + } + + r = mail_quote_filename(quoted_original_filename, + sizeof(quoted_original_filename), original_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_encrypted; + } + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_encrypted; + } + + snprintf(command, sizeof(command), "gpg %s -a --batch --yes -e '%s'", + recipient, quoted_original_filename); + + encrypt_ok = 0; + r = gpg_command_passphrase(privacy, msg, command, NULL, + encrypted_filename, description_filename); + switch (r) { + case NO_ERROR_PGP: + encrypt_ok = 1; + break; + case ERROR_PGP_NOPASSPHRASE: + case ERROR_PGP_CHECK: + encrypt_ok = 0; + break; + case ERROR_PGP_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + case ERROR_PGP_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + if (!encrypt_ok) { + res = MAIL_ERROR_COMMAND; + goto unlink_description; + } + + /* multipart */ + + multipart = mailprivacy_new_file_part(privacy, NULL, + "multipart/encrypted", -1); + if (multipart == NULL) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + content = multipart->mm_content_type; + + param = mailmime_param_new_with_data("protocol", + "application/pgp-encrypted"); + if (param == NULL) { + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + r = clist_append(content->ct_parameters, param); + if (r < 0) { + mailmime_parameter_free(param); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* version part */ + + version_f = mailprivacy_get_tmp_file(privacy, + version_filename, sizeof(version_filename)); + if (version_f == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_FILE; + goto unlink_description; + } + written = fwrite(PGP_VERSION, 1, sizeof(PGP_VERSION) - 1, version_f); + if (written != sizeof(PGP_VERSION) - 1) { + fclose(version_f); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_FILE; + goto unlink_description; + } + fclose(version_f); + + version_mime = mailprivacy_new_file_part(privacy, + version_filename, + "application/pgp-encrypted", + MAILMIME_MECHANISM_8BIT); + if (version_mime == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_version; + } + + r = mailmime_smart_add_part(multipart, version_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(version_mime); + mailmime_free(version_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_version; + } + + /* encrypted part */ + + encrypted_mime = mailprivacy_new_file_part(privacy, + encrypted_filename, + "application/octet-stream", + MAILMIME_MECHANISM_8BIT); + if (encrypted_mime == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_version; + } + + r = mailmime_smart_add_part(multipart, encrypted_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(encrypted_mime); + mailmime_free(encrypted_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_version; + } + + unlink(version_filename); + unlink(description_filename); + unlink(encrypted_filename); + unlink(original_filename); + + * result = multipart; + + return MAIL_NO_ERROR; + + unlink_version: + unlink(version_filename); + unlink_description: + unlink(description_filename); + unlink_encrypted: + unlink(encrypted_filename); + unlink_original: + unlink(original_filename); + err: + return res; +} + +static int pgp_clear_sign(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + char default_key[PATH_MAX]; + char original_filename[PATH_MAX]; + FILE * original_f; + char signed_filename[PATH_MAX]; + char description_filename[PATH_MAX]; + char quoted_original_filename[PATH_MAX]; + int col; + struct mailmime * signed_mime; + int res; + int r; + char command[PATH_MAX]; + struct mailmime_content * content_type; + char * email; + int sign_ok; + + if (mime->mm_type != MAILMIME_SINGLE) { + res = MAIL_ERROR_INVAL; + goto err; + } + + if (mime->mm_data.mm_single == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + /* get signing key */ + + * default_key = '\0'; + email = get_first_from_addr(mime); + if (email != NULL) + snprintf(default_key, sizeof(default_key), + "--default-key %s", email); + + /* get part to sign */ + + original_f = mailprivacy_get_tmp_file(privacy, + original_filename, + sizeof(original_filename)); + if (original_f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + col = 0; + r = mailmime_data_write(original_f, &col, mime->mm_data.mm_single, 1); + if (r != MAILIMF_NO_ERROR) { + fclose(original_f); + res = MAIL_ERROR_FILE; + goto unlink_original; + } + fclose(original_f); + + r = mailprivacy_get_tmp_filename(privacy, signed_filename, + sizeof(signed_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_original; + } + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_signed; + } + + r = mail_quote_filename(quoted_original_filename, + sizeof(quoted_original_filename), original_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + snprintf(command, sizeof(command), + "gpg --passphrase-fd=0 --batch --yes --digest-algo sha1 %s --clearsign '%s'", + default_key, quoted_original_filename); + + sign_ok = 0; + r = gpg_command_passphrase(privacy, msg, command, NULL, + signed_filename, description_filename); + switch (r) { + case NO_ERROR_PGP: + sign_ok = 1; + break; + case ERROR_PGP_NOPASSPHRASE: + case ERROR_PGP_CHECK: + sign_ok = 0; + break; + case ERROR_PGP_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + case ERROR_PGP_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + if (!sign_ok) { + res = MAIL_ERROR_COMMAND; + goto unlink_description; + } + + /* building the signed part */ + + signed_mime = mailprivacy_new_file_part(privacy, signed_filename, + NULL, MAILMIME_MECHANISM_8BIT); + if (signed_mime == NULL) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* place original content type */ + + content_type = mailmime_content_dup(mime->mm_content_type); + if (content_type == NULL) { + mailprivacy_mime_clear(signed_mime); + mailmime_free(signed_mime); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + mailmime_content_free(signed_mime->mm_content_type); + signed_mime->mm_content_type = content_type; + + /* place original MIME fields */ + + if (mime->mm_mime_fields != NULL) { + struct mailmime_fields * mime_fields; + clistiter * cur; + + mime_fields = mailprivacy_mime_fields_dup(privacy, + mime->mm_mime_fields); + if (mime_fields == NULL) { + mailprivacy_mime_clear(signed_mime); + mailmime_free(signed_mime); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + for(cur = clist_begin(mime_fields->fld_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + if (field->fld_type == MAILMIME_FIELD_TRANSFER_ENCODING) { + mailmime_field_free(field); + clist_delete(mime_fields->fld_list, cur); + break; + } + } + clist_concat(signed_mime->mm_mime_fields->fld_list, + mime_fields->fld_list); + mailmime_fields_free(mime_fields); + } + + unlink(description_filename); + unlink(signed_filename); + unlink(original_filename); + + * result = signed_mime; + + return MAIL_NO_ERROR; + + unlink_description: + unlink(description_filename); + unlink_signed: + unlink(signed_filename); + unlink_original: + unlink(original_filename); + err: + return res; +} + + +static int pgp_armor_encrypt(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + char original_filename[PATH_MAX]; + FILE * original_f; + char encrypted_filename[PATH_MAX]; + char quoted_original_filename[PATH_MAX]; + int col; + struct mailmime * encrypted_mime; + int res; + int r; + char command[PATH_MAX]; + struct mailmime_content * content_type; + struct mailmime * root; + struct mailimf_fields * fields; + char recipient[PATH_MAX]; + int encrypt_ok; + char description_filename[PATH_MAX]; + + if (mime->mm_type != MAILMIME_SINGLE) { + res = MAIL_ERROR_INVAL; + goto err; + } + + if (mime->mm_data.mm_single == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + root = mime; + while (root->mm_parent != NULL) + root = root->mm_parent; + + fields = NULL; + if (root->mm_type == MAILMIME_MESSAGE) + fields = root->mm_data.mm_message.mm_fields; + + /* recipient */ + + collect_recipient(recipient, sizeof(recipient), fields); + + /* get part to encrypt */ + + original_f = mailprivacy_get_tmp_file(privacy, original_filename, + sizeof(original_filename)); + if (original_f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + col = 0; + r = mailmime_data_write(original_f, &col, mime->mm_data.mm_single, 1); + if (r != MAILIMF_NO_ERROR) { + fclose(original_f); + res = MAIL_ERROR_FILE; + goto unlink_original; + } + fclose(original_f); + + r = mailprivacy_get_tmp_filename(privacy, encrypted_filename, + sizeof(encrypted_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_original; + } + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_encrypted; + } + + r = mail_quote_filename(quoted_original_filename, + sizeof(quoted_original_filename), original_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + snprintf(command, sizeof(command), "gpg %s --batch --yes -e --armor '%s'", + recipient, quoted_original_filename); + + encrypt_ok = 0; + r = gpg_command_passphrase(privacy, msg, command, NULL, + encrypted_filename, description_filename); + switch (r) { + case NO_ERROR_PGP: + encrypt_ok = 1; + break; + case ERROR_PGP_NOPASSPHRASE: + case ERROR_PGP_CHECK: + encrypt_ok = 0; + break; + case ERROR_PGP_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + case ERROR_PGP_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + if (!encrypt_ok) { + res = MAIL_ERROR_COMMAND; + goto unlink_description; + } + + /* building the encrypted part */ + + encrypted_mime = mailprivacy_new_file_part(privacy, + encrypted_filename, + "application/octet-stream", + MAILMIME_MECHANISM_8BIT); + if (encrypted_mime == NULL) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* place original content type */ + + content_type = mailmime_content_dup(mime->mm_content_type); + if (content_type == NULL) { + mailprivacy_mime_clear(encrypted_mime); + mailmime_free(encrypted_mime); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + mailmime_content_free(encrypted_mime->mm_content_type); + encrypted_mime->mm_content_type = content_type; + + /* place original MIME fields */ + + if (mime->mm_mime_fields != NULL) { + struct mailmime_fields * mime_fields; + clistiter * cur; + + mime_fields = mailprivacy_mime_fields_dup(privacy, mime->mm_mime_fields); + if (mime_fields == NULL) { + mailprivacy_mime_clear(encrypted_mime); + mailmime_free(encrypted_mime); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + for(cur = clist_begin(mime_fields->fld_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + if (field->fld_type == MAILMIME_FIELD_TRANSFER_ENCODING) { + mailmime_field_free(field); + clist_delete(mime_fields->fld_list, cur); + break; + } + } + clist_concat(encrypted_mime->mm_mime_fields->fld_list, + mime_fields->fld_list); + mailmime_fields_free(mime_fields); + } + + unlink(description_filename); + unlink(encrypted_filename); + unlink(original_filename); + + * result = encrypted_mime; + + return MAIL_NO_ERROR; + + unlink_description: + unlink(description_filename); + unlink_encrypted: + unlink(encrypted_filename); + unlink_original: + unlink(original_filename); + err: + return res; +} + + +static int pgp_armor_sign_encrypt(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + char default_key[PATH_MAX]; + char original_filename[PATH_MAX]; + FILE * original_f; + char encrypted_filename[PATH_MAX]; + char description_filename[PATH_MAX]; + char quoted_original_filename[PATH_MAX]; + int col; + struct mailmime * encrypted_mime; + int res; + int r; + char command[PATH_MAX]; + struct mailmime_content * content_type; + struct mailmime * root; + struct mailimf_fields * fields; + char recipient[PATH_MAX]; + char * email; + int encrypt_ok; + + if (mime->mm_type != MAILMIME_SINGLE) { + res = MAIL_ERROR_INVAL; + goto err; + } + + if (mime->mm_data.mm_single == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + /* get signing key */ + + * default_key = '\0'; + email = get_first_from_addr(mime); + if (email != NULL) + snprintf(default_key, sizeof(default_key), + "--default-key %s", email); + + root = mime; + while (root->mm_parent != NULL) + root = root->mm_parent; + + fields = NULL; + if (root->mm_type == MAILMIME_MESSAGE) + fields = root->mm_data.mm_message.mm_fields; + + /* recipient */ + + collect_recipient(recipient, sizeof(recipient), fields); + + /* get part to encrypt */ + + original_f = mailprivacy_get_tmp_file(privacy, + original_filename, + sizeof(original_filename)); + if (original_f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + col = 0; + r = mailmime_data_write(original_f, &col, mime->mm_data.mm_single, 1); + if (r != MAILIMF_NO_ERROR) { + fclose(original_f); + res = MAIL_ERROR_FILE; + goto unlink_original; + } + fclose(original_f); + + r = mailprivacy_get_tmp_filename(privacy, encrypted_filename, + sizeof(encrypted_filename)); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_FILE; + goto unlink_original; + } + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_encrypted; + } + + r = mail_quote_filename(quoted_original_filename, + sizeof(quoted_original_filename), original_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + snprintf(command, sizeof(command), + "gpg --passphrase-fd=0 %s --batch --yes --digest-algo sha1 " + "%s -e -s -a '%s'", + recipient, default_key, quoted_original_filename); + + encrypt_ok = 0; + r = gpg_command_passphrase(privacy, msg, command, NULL, + encrypted_filename, description_filename); + switch (r) { + case NO_ERROR_PGP: + encrypt_ok = 1; + break; + case ERROR_PGP_NOPASSPHRASE: + case ERROR_PGP_CHECK: + encrypt_ok = 0; + break; + case ERROR_PGP_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + case ERROR_PGP_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + if (!encrypt_ok) { + res = MAIL_ERROR_COMMAND; + goto unlink_description; + } + + /* building the encrypted part */ + + encrypted_mime = mailprivacy_new_file_part(privacy, + encrypted_filename, + "application/octet-stream", + MAILMIME_MECHANISM_8BIT); + if (encrypted_mime == NULL) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* place original content type */ + + content_type = mailmime_content_dup(mime->mm_content_type); + if (content_type == NULL) { + mailprivacy_mime_clear(encrypted_mime); + mailmime_free(encrypted_mime); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + mailmime_content_free(encrypted_mime->mm_content_type); + encrypted_mime->mm_content_type = content_type; + + /* place original MIME fields */ + + if (mime->mm_mime_fields != NULL) { + struct mailmime_fields * mime_fields; + clistiter * cur; + + mime_fields = mailprivacy_mime_fields_dup(privacy, mime->mm_mime_fields); + if (mime_fields == NULL) { + mailprivacy_mime_clear(encrypted_mime); + mailmime_free(encrypted_mime); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + for(cur = clist_begin(mime_fields->fld_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + if (field->fld_type == MAILMIME_FIELD_TRANSFER_ENCODING) { + mailmime_field_free(field); + clist_delete(mime_fields->fld_list, cur); + break; + } + } + clist_concat(encrypted_mime->mm_mime_fields->fld_list, + mime_fields->fld_list); + mailmime_fields_free(mime_fields); + } + + unlink(description_filename); + unlink(encrypted_filename); + unlink(original_filename); + + * result = encrypted_mime; + + return MAIL_NO_ERROR; + + unlink_description: + unlink(description_filename); + unlink_encrypted: + unlink(encrypted_filename); + unlink_original: + unlink(original_filename); + err: + return res; +} + +static struct mailprivacy_encryption pgp_encryption_tab[] = { + /* PGP signed part */ + { + /* name */ "signed", + /* description */ "PGP signed part", + /* encrypt */ pgp_sign_mime + }, + + /* pgp encrypted part */ + + { + /* name */ "encrypted", + /* description */ "PGP encrypted part", + /* encrypt */ pgp_encrypt_mime + }, + + /* PGP signed & encrypted part */ + + { + /* name */ "signed-encrypted", + /* description */ "PGP signed & encrypted part", + /* encrypt */ pgp_sign_encrypt_mime + }, + + /* PGP clear signed part */ + + { + /* name */ "clear-signed", + /* description */ "PGP clear signed part", + /* encrypt */ pgp_clear_sign + }, + + /* PGP armor encrypted part */ + + { + /* name */ "encrypted-armor", + /* description */ "PGP ASCII armor encrypted part", + /* encrypt */ pgp_armor_encrypt + }, + + /* PGP armor signed & encrypted part */ + + { + /* name */ "signed-encrypted-armor", + /* description */ "PGP ASCII armor signed & encrypted part", + /* encrypt */ pgp_armor_sign_encrypt + } +}; + +static struct mailprivacy_protocol pgp_protocol = { + /* name */ "pgp", + /* description */ "OpenPGP", + + /* is_encrypted */ pgp_test_encrypted, + /* decrypt */ pgp_handler, + + /* encryption_count */ + (sizeof(pgp_encryption_tab) / sizeof(pgp_encryption_tab[0])), + + /* encryption_tab */ pgp_encryption_tab +}; + +#ifdef LIBETPAN_REENTRANT +#if defined(HAVE_PTHREAD_H) && !defined(IGNORE_PTHREAD_H) +static pthread_mutex_t encryption_id_hash_lock = PTHREAD_MUTEX_INITIALIZER; +#define LOCK() pthread_mutex_lock(&encryption_id_hash_lock) +#define UNLOCK() pthread_mutex_unlock(&encryption_id_hash_lock) +#elif (defined WIN32) +static CRITICAL_SECTION encryption_id_hash_lock = {0}; +static int mailprivacy_gnupg_init_lock_done = 0; +#define LOCK() EnterCriticalSection(&encryption_id_hash_lock) +#define UNLOCK() LeaveCriticalSection(&encryption_id_hash_lock) +#endif +#else +#define LOCK() do while (0) +#define UNLOCK() do while (0) +#endif +static chash * encryption_id_hash = NULL; + +#ifdef LIBETPAN_REENTRANT +#if defined(HAVE_PTHREAD_H) && !defined(IGNORE_PTHREAD_H) +#elif (defined WIN32) +static void mailprivacy_gnupg_init_lock(void) +{ + if (InterlockedExchange(&mailprivacy_gnupg_init_lock_done, 1) == 0){ + InitializeCriticalSection(&encryption_id_hash_lock); + } +} +#endif +#endif + +int mailprivacy_gnupg_init(struct mailprivacy * privacy) +{ + return mailprivacy_register(privacy, &pgp_protocol); +} + +void mailprivacy_gnupg_done(struct mailprivacy * privacy) +{ + mailprivacy_unregister(privacy, &pgp_protocol); +} + +static clist * get_list(struct mailprivacy * privacy, mailmessage * msg) +{ + clist * encryption_id_list; + + encryption_id_list = NULL; + if (encryption_id_hash != NULL) { + chashdatum key; + chashdatum value; + int r; + + key.data = &msg; + key.len = sizeof(msg); + r = chash_get(encryption_id_hash, &key, &value); + if (r == 0) { + encryption_id_list = value.data; + } + } + + return encryption_id_list; +} + +void mailprivacy_gnupg_encryption_id_list_clear(struct mailprivacy * privacy, + mailmessage * msg) +{ + clist * encryption_id_list; + clistiter * iter; + + LOCK(); + encryption_id_list = get_list(privacy, msg); + if (encryption_id_list != NULL) { + chashdatum key; + + for(iter = clist_begin(encryption_id_list) ; + iter != NULL ; iter = clist_next(iter)) { + char * str; + + str = clist_content(iter); + free(str); + } + clist_free(encryption_id_list); + + key.data = &msg; + key.len = sizeof(msg); + chash_delete(encryption_id_hash, &key, NULL); + + if (chash_count(encryption_id_hash) == 0) { + chash_free(encryption_id_hash); + encryption_id_hash = NULL; + } + } + UNLOCK(); +} + +clist * mailprivacy_gnupg_encryption_id_list(struct mailprivacy * privacy, + mailmessage * msg) +{ + clist * encryption_id_list; + + LOCK(); + encryption_id_list = get_list(privacy, msg); + UNLOCK(); + + return encryption_id_list; +} + +static int mailprivacy_gnupg_add_encryption_id(struct mailprivacy * privacy, + mailmessage * msg, char * encryption_id) +{ + clist * encryption_id_list; + int r; + int res; + + LOCK(); + + res = -1; + + encryption_id_list = get_list(privacy, msg); + if (encryption_id_list == NULL) { + if (encryption_id_hash == NULL) + encryption_id_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + + if (encryption_id_hash != NULL) { + encryption_id_list = clist_new(); + if (encryption_id_list != NULL) { + chashdatum key; + chashdatum value; + + key.data = &msg; + key.len = sizeof(msg); + value.data = encryption_id_list; + value.len = 0; + r = chash_set(encryption_id_hash, &key, &value, NULL); + if (r < 0) + clist_free(encryption_id_list); + } + } + } + + encryption_id_list = get_list(privacy, msg); + if (encryption_id_list != NULL) { + char * str; + + str = strdup(encryption_id); + if (str != NULL) { + r = clist_append(encryption_id_list, str); + if (r < 0) { + free(str); + } + else { + res = 0; + } + } + } + + UNLOCK(); + + return res; +} + +#define MAX_EMAIL_SIZE 1024 + +static chash * passphrase_hash = NULL; + +int mailprivacy_gnupg_set_encryption_id(struct mailprivacy * privacy, + char * user_id, char * passphrase) +{ + chashdatum key; + chashdatum value; + int r; + char buf[MAX_EMAIL_SIZE]; + char * n; + + strncpy(buf, user_id, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + for(n = buf ; * n != '\0' ; n ++) + * n = toupper((unsigned char) * n); + + if (passphrase_hash == NULL) { + passphrase_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL); + if (passphrase_hash == NULL) + return MAIL_ERROR_MEMORY; + } + + key.data = buf; + key.len = (unsigned int) strlen(buf) + 1; + value.data = passphrase; + value.len = (unsigned int) strlen(passphrase) + 1; + + r = chash_set(passphrase_hash, &key, &value, NULL); + if (r < 0) { + return MAIL_ERROR_MEMORY; + } + + return MAIL_NO_ERROR; +} + +static char * get_passphrase(struct mailprivacy * privacy, + char * user_id) +{ + chashdatum key; + chashdatum value; + int r; + char * passphrase; + char buf[MAX_EMAIL_SIZE]; + char * n; + + strncpy(buf, user_id, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + for(n = buf ; * n != '\0' ; n ++) + * n = toupper((unsigned char) * n); + + if (passphrase_hash == NULL) + return NULL; + + key.data = buf; + key.len = (unsigned int) strlen(buf) + 1; + + r = chash_get(passphrase_hash, &key, &value); + if (r < 0) + return NULL; + + passphrase = strdup(value.data); + + return passphrase; +} diff --git a/Sources/libetpan/engine/mailprivacy_gnupg.h b/Sources/libetpan/engine/mailprivacy_gnupg.h new file mode 100644 index 00000000..454b158b --- /dev/null +++ b/Sources/libetpan/engine/mailprivacy_gnupg.h @@ -0,0 +1,60 @@ +/* + * etPan! -- a mail user agent + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailprivacy_gnupg.h,v 1.5 2007/10/30 00:40:39 hoa Exp $ + */ + +#ifndef MAIL_PRIVACY_GNUPG_H + +#define MAIL_PRIVACY_GNUPG_H + +#include + +LIBETPAN_EXPORT +int mailprivacy_gnupg_init(struct mailprivacy * privacy); + +LIBETPAN_EXPORT +void mailprivacy_gnupg_done(struct mailprivacy * privacy); + +LIBETPAN_EXPORT +clist * mailprivacy_gnupg_encryption_id_list(struct mailprivacy * privacy, + mailmessage * msg); + +LIBETPAN_EXPORT +void mailprivacy_gnupg_encryption_id_list_clear(struct mailprivacy * privacy, + mailmessage * msg); + +LIBETPAN_EXPORT +int mailprivacy_gnupg_set_encryption_id(struct mailprivacy * privacy, + char * user_id, char * passphrase); + +#endif diff --git a/Sources/libetpan/engine/mailprivacy_smime.c b/Sources/libetpan/engine/mailprivacy_smime.c new file mode 100644 index 00000000..2dcd1e65 --- /dev/null +++ b/Sources/libetpan/engine/mailprivacy_smime.c @@ -0,0 +1,1928 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailprivacy_smime.c,v 1.19 2011/05/03 16:30:22 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#if __APPLE__ +#include +#endif +#include "mailprivacy_smime.h" +#include +#ifdef WIN32 +# include "win_etpan.h" +# define WEXITSTATUS(r) (r) +#else +# include +# include +# include +#endif +#ifdef LIBETPAN_REENTRANT +#if defined(HAVE_PTHREAD_H) && !defined(IGNORE_PTHREAD_H) +#include +#elif (defined WIN32) +#include +#endif +#endif +#include +#include +#include +#include +#include "mailprivacy_tools.h" +#include "mailprivacy_tools_private.h" +#include "mailprivacy.h" +#include +#include +#include +#include + +/* + global variable + + TODO : instance of privacy drivers +*/ + +static int smime_command_passphrase(struct mailprivacy * privacy, + struct mailmessage * msg, + char * command, + char * passphrase, + char * stdoutfile, char * stderrfile); +static int mailprivacy_smime_add_encryption_id(struct mailprivacy * privacy, + mailmessage * msg, char * encryption_id); + +static char cert_dir[PATH_MAX] = ""; +static chash * certificates = NULL; +static chash * private_keys = NULL; +static char CAcert_dir[PATH_MAX] = ""; +static char * CAfile = NULL; +static int CA_check = 1; +static int store_cert = 0; +static char private_keys_dir[PATH_MAX] = ""; + +static char * get_cert_file(char * email); + +static char * get_private_key_file(char * email); + + +static int smime_is_signed(struct mailmime * mime) +{ + if (mime->mm_content_type != NULL) { + if ((strcasecmp(mime->mm_content_type->ct_subtype, "x-pkcs7-mime") == 0) || + (strcasecmp(mime->mm_content_type->ct_subtype, "pkcs7-mime") == 0)) { + clistiter * cur; + + for(cur = clist_begin(mime->mm_content_type->ct_parameters) ; + cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = cur->data; + + if ((strcasecmp(param->pa_name, "smime-type") == 0) && + (strcasecmp(param->pa_value, "signed-data") == 0)) + return 1; + } + + return 0; + } + else { + clistiter * cur; + + for(cur = clist_begin(mime->mm_content_type->ct_parameters) ; + cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = cur->data; + + if ((strcasecmp(param->pa_name, "protocol") == 0) && + ((strcasecmp(param->pa_value, + "application/x-pkcs7-signature") == 0) || + (strcasecmp(param->pa_value, + "application/pkcs7-signature") == 0))) + return 1; + } + } + } + + return 0; +} + +static int smime_is_encrypted(struct mailmime * mime) +{ + if (mime->mm_content_type != NULL) { + if ((strcasecmp(mime->mm_content_type->ct_subtype, "x-pkcs7-mime") == 0) || + (strcasecmp(mime->mm_content_type->ct_subtype, "pkcs7-mime") == 0)) { + clistiter * cur; + + for(cur = clist_begin(mime->mm_content_type->ct_parameters) ; + cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = cur->data; + + if ((strcasecmp(param->pa_name, "smime-type") == 0) && + (strcasecmp(param->pa_value, "signed-data") == 0)) + return 0; + } + + return 1; + } + } + + return 0; +} + + +enum { + NO_ERROR_SMIME = 0, + ERROR_SMIME_CHECK, + ERROR_SMIME_COMMAND, + ERROR_SMIME_FILE, + ERROR_SMIME_NOPASSPHRASE +}; + +#define BUF_SIZE 1024 + +static char * get_first_from_addr(struct mailmime * mime) +{ + clistiter * cur; + struct mailimf_single_fields single_fields; + struct mailimf_fields * fields; + struct mailimf_mailbox * mb; + + while (mime->mm_parent != NULL) + mime = mime->mm_parent; + + if (mime->mm_type != MAILMIME_MESSAGE) + return NULL; + + fields = mime->mm_data.mm_message.mm_fields; + if (fields == NULL) + return NULL; + + mailimf_single_fields_init(&single_fields, fields); + + if (single_fields.fld_from == NULL) + return NULL; + + cur = clist_begin(single_fields.fld_from->frm_mb_list->mb_list); + if (cur == NULL) + return NULL; + + mb = clist_content(cur); + + return mb->mb_addr_spec; +} + +#define SMIME_DECRYPT_DESCRIPTION "S/MIME encrypted part\r\n" +#define SMIME_DECRYPT_FAILED "S/MIME decryption FAILED\r\n" +#define SMIME_DECRYPT_SUCCESS "S/MIME decryption success\r\n" + +/* passphrase will be needed */ + +static int smime_decrypt(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + char smime_filename[PATH_MAX]; + char quoted_smime_filename[PATH_MAX]; + char description_filename[PATH_MAX]; + char decrypted_filename[PATH_MAX]; + char command[PATH_MAX]; + struct mailmime * description_mime; + struct mailmime * decrypted_mime; + int r; + int res; + int sign_ok; + struct mailmime * multipart; + char * smime_cert; + char * smime_key; + char quoted_smime_cert[PATH_MAX]; + char quoted_smime_key[PATH_MAX]; + char * email; + chashiter * iter; + + /* fetch the whole multipart and write it to a file */ + + r = mailprivacy_fetch_mime_body_to_file(privacy, + smime_filename, sizeof(smime_filename), + msg, mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + /* we are in a safe directory */ + + r = mailprivacy_get_tmp_filename(privacy, decrypted_filename, + sizeof(decrypted_filename)); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_FILE; + goto unlink_smime; + } + + /* description */ + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_FILE; + goto unlink_decrypted; + } + + sign_ok = 0; + for(iter = chash_begin(private_keys) ; iter != NULL ; + iter = chash_next(private_keys, iter)) { + chashdatum key; + char email_buf[BUF_SIZE]; + + chash_key(iter, &key); + + if (key.len >= sizeof(email_buf)) + continue; + + strncpy(email_buf, key.data, key.len); + email_buf[key.len] = '\0'; + email = email_buf; + + /* get encryption key */ + + smime_key = get_private_key_file(email); + smime_cert = get_cert_file(email); + if ((smime_cert == NULL) || (smime_key == NULL)) { + res = MAIL_ERROR_INVAL; + goto unlink_description; + } + + r = mail_quote_filename(quoted_smime_cert, sizeof(quoted_smime_cert), + smime_cert); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + r = mail_quote_filename(quoted_smime_key, sizeof(quoted_smime_key), + smime_key); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* run the command */ + + r = mail_quote_filename(quoted_smime_filename, + sizeof(quoted_smime_filename), smime_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + sign_ok = 0; + snprintf(command, sizeof(command), + "openssl smime -decrypt -passin fd:0 -in '%s' -inkey '%s' -recip '%s'", + quoted_smime_filename, quoted_smime_key, quoted_smime_cert); + + unlink(description_filename); + r = smime_command_passphrase(privacy, msg, command, + email, decrypted_filename, description_filename); + switch (r) { + case NO_ERROR_SMIME: + sign_ok = 1; + break; + case ERROR_SMIME_CHECK: + case ERROR_SMIME_NOPASSPHRASE: + sign_ok = 0; + break; + case ERROR_SMIME_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + case ERROR_SMIME_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + if (sign_ok) { + break; + } + } + + if (!sign_ok) { + if (chash_count(private_keys) == 0) { + FILE * description_f; + + description_f = mailprivacy_get_tmp_file(privacy, description_filename, + sizeof(description_filename)); + if (description_f == NULL) { + res = MAIL_ERROR_FILE; + goto unlink_decrypted; + } + fprintf(description_f, SMIME_DECRYPT_FAILED); + fclose(description_f); + } + } + else { + mailprivacy_smime_encryption_id_list_clear(privacy, msg); + } + + /* building multipart */ + + r = mailmime_new_with_content("multipart/x-decrypted", NULL, &multipart); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* building the description part */ + + description_mime = mailprivacy_new_file_part(privacy, + description_filename, + "text/plain", MAILMIME_MECHANISM_8BIT); + if (description_mime == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* adds the description part */ + + r = mailmime_smart_add_part(multipart, description_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(description_mime); + mailmime_free(description_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* building the decrypted part */ + + r = mailprivacy_get_part_from_file(privacy, 1, 0, + decrypted_filename, &decrypted_mime); + if (r == MAIL_NO_ERROR) { + /* adds the decrypted part */ + + r = mailmime_smart_add_part(multipart, decrypted_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(decrypted_mime); + mailmime_free(decrypted_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + } + + unlink(description_filename); + unlink(decrypted_filename); + unlink(smime_filename); + + * result = multipart; + + return MAIL_NO_ERROR; + + unlink_description: + unlink(description_filename); + unlink_decrypted: + unlink(decrypted_filename); + unlink_smime: + unlink(smime_filename); + err: + return res; +} + + +static int get_cert_from_sig(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime); + +#define SMIME_VERIFY_DESCRIPTION "S/MIME verify signed message\r\n" +#define SMIME_VERIFY_FAILED "S/MIME verification FAILED\r\n" +#define SMIME_VERIFY_SUCCESS "S/MIME verification success\r\n" + +static int +smime_verify(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + char smime_filename[PATH_MAX]; + char quoted_smime_filename[PATH_MAX]; + int res; + int r; + char command[PATH_MAX]; + int sign_ok; + struct mailmime * description_mime; + char description_filename[PATH_MAX]; + struct mailmime * multipart; + char stripped_filename[PATH_MAX]; + struct mailmime * stripped_mime; + char check_CA[PATH_MAX]; + char quoted_CAfile[PATH_MAX]; + char noverify[PATH_MAX]; + + if (store_cert) + get_cert_from_sig(privacy, msg, mime); + + * check_CA = '\0'; + if (CAfile != NULL) { + r = mail_quote_filename(quoted_CAfile, sizeof(quoted_CAfile), CAfile); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(check_CA, sizeof(check_CA), "-CAfile '%s'", quoted_CAfile); + } + + * noverify = '\0'; + if (!CA_check) { + snprintf(noverify, sizeof(noverify), "-noverify"); + } + + /* fetch the whole multipart and write it to a file */ + + r = mailprivacy_fetch_mime_body_to_file(privacy, + smime_filename, sizeof(smime_filename), + msg, mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = mailprivacy_get_tmp_filename(privacy,stripped_filename, + sizeof(stripped_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_smime; + } + + /* description */ + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_stripped; + } + + /* run the command */ + + r = mail_quote_filename(quoted_smime_filename, + sizeof(quoted_smime_filename), smime_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + sign_ok = 0; + snprintf(command, sizeof(command), "openssl smime -verify -in '%s' %s %s", + quoted_smime_filename, check_CA, noverify); + + r = smime_command_passphrase(privacy, msg, command, + NULL, stripped_filename, description_filename); + switch (r) { + case NO_ERROR_SMIME: + sign_ok = 1; + break; + case ERROR_SMIME_NOPASSPHRASE: + case ERROR_SMIME_CHECK: + sign_ok = 0; + break; + case ERROR_SMIME_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + case ERROR_SMIME_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + /* building multipart */ + + r = mailmime_new_with_content("multipart/x-verified", NULL, &multipart); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* building the description part */ + + description_mime = mailprivacy_new_file_part(privacy, + description_filename, + "text/plain", MAILMIME_MECHANISM_8BIT); + if (description_mime == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* adds the description part */ + + r = mailmime_smart_add_part(multipart, description_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(description_mime); + mailmime_free(description_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* insert the signed part */ + if (!sign_ok) { + if (mime->mm_type == MAILMIME_MULTIPLE) { + clistiter * child_iter; + struct mailmime * child; + + child_iter = clist_begin(mime->mm_data.mm_multipart.mm_mp_list); + child = clist_content(child_iter); + + r = mailprivacy_fetch_mime_body_to_file(privacy, + stripped_filename, sizeof(stripped_filename), + msg, child); + } + } + + r = mailprivacy_get_part_from_file(privacy, 1, 0, + stripped_filename, &stripped_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = r; + goto unlink_description; + } + + r = mailmime_smart_add_part(multipart, stripped_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(stripped_mime); + mailmime_free(stripped_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + unlink(description_filename); + unlink(stripped_filename); + /* unlink(smime_filename); */ + + * result = multipart; + + return MAIL_NO_ERROR; + + unlink_description: + unlink(description_filename); + unlink_stripped: + unlink(stripped_filename); + unlink_smime: + unlink(smime_filename); + err: + return res; +} + +static int smime_test_encrypted(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime) +{ + switch (mime->mm_type) { + case MAILMIME_MULTIPLE: + return smime_is_signed(mime); + + case MAILMIME_SINGLE: + return smime_is_encrypted(mime) || smime_is_signed(mime); + } + + return 0; +} + +static int smime_handler(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + int r; + struct mailmime * alternative_mime; + + alternative_mime = NULL; + switch (mime->mm_type) { + case MAILMIME_MULTIPLE: + r = MAIL_ERROR_INVAL; + if (smime_is_signed(mime)) + r = smime_verify(privacy, msg, mime, &alternative_mime); + + if (r != MAIL_NO_ERROR) + return r; + + * result = alternative_mime; + + return MAIL_NO_ERROR; + + case MAILMIME_SINGLE: + r = MAIL_ERROR_INVAL; + if (smime_is_encrypted(mime)) + r = smime_decrypt(privacy, msg, mime, &alternative_mime); + else if (smime_is_signed(mime)) + r = smime_verify(privacy, msg, mime, &alternative_mime); + + if (r != MAIL_NO_ERROR) + return r; + + * result = alternative_mime; + + return MAIL_NO_ERROR; + } + + return MAIL_ERROR_INVAL; +} + + + + +static void strip_mime_headers(struct mailmime * mime) +{ + struct mailmime_fields * fields; + clistiter * cur; + + fields = mime->mm_mime_fields; + + if (fields == NULL) + return; + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILMIME_FIELD_VERSION) { + mailmime_field_free(field); + clist_delete(fields->fld_list, cur); + break; + } + } +} + +/* passphrase is needed */ + +static int smime_sign(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + char signed_filename[PATH_MAX]; + FILE * signed_f; + int res; + int r; + int col; + char description_filename[PATH_MAX]; + char signature_filename[PATH_MAX]; + char command[PATH_MAX]; + char quoted_signed_filename[PATH_MAX]; + struct mailmime * signed_mime; + char * smime_cert; + char * smime_key; + char quoted_smime_cert[PATH_MAX]; + char quoted_smime_key[PATH_MAX]; + char * email; + + /* get signing key */ + + email = get_first_from_addr(mime); + if (email == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + smime_key = get_private_key_file(email); + smime_cert = get_cert_file(email); + if ((smime_cert == NULL) || (smime_key == NULL)) { + res = MAIL_ERROR_INVAL; + goto err; + } + + /* part to sign */ + + /* encode quoted printable all text parts */ + + mailprivacy_prepare_mime(mime); + + signed_f = mailprivacy_get_tmp_file(privacy, + signed_filename, sizeof(signed_filename)); + if (signed_f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + col = 0; + r = mailmime_write(signed_f, &col, mime); + if (r != MAILIMF_NO_ERROR) { + fclose(signed_f); + res = MAIL_ERROR_FILE; + goto unlink_signed; + } + + fclose(signed_f); + + /* prepare destination file for signature */ + + r = mailprivacy_get_tmp_filename(privacy, signature_filename, + sizeof(signature_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_signed; + } + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_signature; + } + + r = mail_quote_filename(quoted_signed_filename, + sizeof(quoted_signed_filename), signed_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + r = mail_quote_filename(quoted_smime_key, + sizeof(quoted_smime_key), smime_key); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + r = mail_quote_filename(quoted_smime_cert, + sizeof(quoted_smime_cert), smime_cert); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + snprintf(command, sizeof(command), + "openssl smime -sign -passin fd:0 -in '%s' -signer '%s' -inkey '%s'", + quoted_signed_filename, + quoted_smime_cert, quoted_smime_key); + + r = smime_command_passphrase(privacy, msg, command, + email, signature_filename, description_filename); + switch (r) { + case NO_ERROR_SMIME: + break; + case ERROR_SMIME_NOPASSPHRASE: + case ERROR_SMIME_CHECK: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + break; + case ERROR_SMIME_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + case ERROR_SMIME_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + /* signature part */ + + r = mailprivacy_get_part_from_file(privacy, 0, 0, + signature_filename, &signed_mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_description; + } + strip_mime_headers(signed_mime); + + unlink(description_filename); + /* unlink(signature_filename); */ + /* unlink(signed_filename); */ + + * result = signed_mime; + + return MAIL_NO_ERROR; + + unlink_description: + unlink(description_filename); + unlink_signature: + unlink(signature_filename); + unlink_signed: + unlink(signed_filename); + err: + return res; +} + + +/* ********************************************************************* */ +/* find S/MIME recipient */ + +static int recipient_add_mb(char * recipient, size_t * len, + struct mailimf_mailbox * mb) +{ + char * filename; + char quoted_filename[PATH_MAX]; + size_t buflen; + int r; + + if (mb->mb_addr_spec == NULL) + return MAIL_NO_ERROR; + + filename = get_cert_file(mb->mb_addr_spec); + if (filename == NULL) + return MAIL_ERROR_INVAL; + + r = mail_quote_filename(quoted_filename, sizeof(quoted_filename), + filename); + if (r < 0) + return MAIL_ERROR_MEMORY; + + buflen = strlen(quoted_filename + 1); + if (buflen >= * len) + return MAIL_ERROR_MEMORY; + + strncat(recipient, "\'", * len); + (* len) --; + strncat(recipient, quoted_filename, * len); + (* len) -= buflen; + strncat(recipient, "\'", * len); + (* len) --; + strncat(recipient, " ", * len); + (* len) --; + + return MAIL_NO_ERROR; +} + +static int recipient_add_mb_list(char * recipient, size_t * len, + struct mailimf_mailbox_list * mb_list) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = clist_content(cur); + + r = recipient_add_mb(recipient, len, mb); + if (r != MAIL_NO_ERROR) + return r; + } + + return MAIL_NO_ERROR; +} + +static int recipient_add_group(char * recipient, size_t * len, + struct mailimf_group * group) +{ + return recipient_add_mb_list(recipient, len, group->grp_mb_list); +} + +static int recipient_add_addr(char * recipient, size_t * len, + struct mailimf_address * addr) +{ + int r; + + switch (addr->ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + r = recipient_add_mb(recipient, len, addr->ad_data.ad_mailbox); + break; + case MAILIMF_ADDRESS_GROUP: + r = recipient_add_group(recipient, len, addr->ad_data.ad_group); + break; + default: + r = MAIL_ERROR_INVAL; + } + + return r; +} + +static int recipient_add_addr_list(char * recipient, size_t * len, + struct mailimf_address_list * addr_list) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_address * addr; + + addr = clist_content(cur); + + r = recipient_add_addr(recipient, len, addr); + if (r != MAIL_NO_ERROR) + return r; + } + + return MAIL_NO_ERROR; +} + +static int collect_smime_cert(char * recipient, size_t size, + struct mailimf_fields * fields) +{ + struct mailimf_single_fields single_fields; + int r; + size_t remaining; + int res; + + * recipient = '\0'; + remaining = size; + + mailimf_single_fields_init(&single_fields, fields); + + if (single_fields.fld_to != NULL) { + r = recipient_add_addr_list(recipient, &remaining, + single_fields.fld_to->to_addr_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + + if (single_fields.fld_cc != NULL) { + r = recipient_add_addr_list(recipient, &remaining, + single_fields.fld_cc->cc_addr_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + + if (single_fields.fld_bcc != NULL) { + if (single_fields.fld_bcc->bcc_addr_list != NULL) { + r = recipient_add_addr_list(recipient, &remaining, + single_fields.fld_bcc->bcc_addr_list); + if (r < 0) { + res = r; + goto err; + } + } + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + + +static int smime_encrypt(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + char encrypted_filename[PATH_MAX]; + int res; + int r; + int col; + char description_filename[PATH_MAX]; + char decrypted_filename[PATH_MAX]; + FILE * decrypted_f; + char command[PATH_MAX]; + char quoted_decrypted_filename[PATH_MAX]; + struct mailmime * encrypted_mime; + struct mailmime * root; + struct mailimf_fields * fields; + char recipient[PATH_MAX]; + + root = mime; + while (root->mm_parent != NULL) + root = root->mm_parent; + + fields = NULL; + if (root->mm_type == MAILMIME_MESSAGE) + fields = root->mm_data.mm_message.mm_fields; + + /* recipient */ + r = collect_smime_cert(recipient, sizeof(recipient), fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + /* part to encrypt */ + + /* encode quoted printable all text parts */ + + mailprivacy_prepare_mime(mime); + + decrypted_f = mailprivacy_get_tmp_file(privacy, + decrypted_filename, + sizeof(decrypted_filename)); + if (decrypted_f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + col = 0; + r = mailmime_write(decrypted_f, &col, mime); + if (r != MAILIMF_NO_ERROR) { + fclose(decrypted_f); + res = MAIL_ERROR_FILE; + goto unlink_decrypted; + } + + fclose(decrypted_f); + + /* prepare destination file for encryption */ + + r = mailprivacy_get_tmp_filename(privacy, encrypted_filename, + sizeof(encrypted_filename)); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_FILE; + goto unlink_decrypted; + } + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_FILE; + goto unlink_encrypted; + } + + r = mail_quote_filename(quoted_decrypted_filename, + sizeof(quoted_decrypted_filename), decrypted_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + snprintf(command, sizeof(command), "openssl smime -encrypt -in '%s' %s", + quoted_decrypted_filename, recipient); + + r = smime_command_passphrase(privacy, msg, command, + NULL, encrypted_filename, description_filename); + switch (r) { + case NO_ERROR_SMIME: + break; + case ERROR_SMIME_NOPASSPHRASE: + case ERROR_SMIME_CHECK: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + break; + case ERROR_SMIME_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_encrypted; + case ERROR_SMIME_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + /* encrypted part */ + + r = mailprivacy_get_part_from_file(privacy, 0, 0, + encrypted_filename, &encrypted_mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_description; + } + strip_mime_headers(encrypted_mime); + + unlink(description_filename); + unlink(encrypted_filename); + unlink(decrypted_filename); + + * result = encrypted_mime; + + return MAIL_NO_ERROR; + + unlink_description: + unlink(description_filename); + unlink_encrypted: + unlink(encrypted_filename); + unlink_decrypted: + unlink(decrypted_filename); + err: + return res; +} + + +/* passphrase will be needed */ + +static int smime_sign_encrypt(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + struct mailmime * signed_part; + struct mailmime * encrypted; + int r; + int res; + + r = smime_sign(privacy, msg, mime, &signed_part); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = smime_encrypt(privacy, msg, signed_part, &encrypted); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_signed; + } + + * result = encrypted; + + return MAIL_NO_ERROR; + + free_signed: + mailprivacy_mime_clear(signed_part); + mailmime_free(signed_part); + err: + return res; +} + + +static struct mailprivacy_encryption smime_encryption_tab[] = { + /* S/MIME signed part */ + { + /* name */ "signed", + /* description */ "S/MIME signed part", + /* encrypt */ smime_sign + }, + + /* S/MIME encrypted part */ + + { + /* name */ "encrypted", + /* description */ "S/MIME encrypted part", + /* encrypt */ smime_encrypt + }, + + /* S/MIME signed & encrypted part */ + + { + /* name */ "signed-encrypted", + /* description */ "S/MIME signed & encrypted part", + /* encrypt */ smime_sign_encrypt + } +}; + +static struct mailprivacy_protocol smime_protocol = { + /* name */ "smime", + /* description */ "S/MIME", + + /* is_encrypted */ smime_test_encrypted, + /* decrypt */ smime_handler, + + /* encryption_count */ + (sizeof(smime_encryption_tab) / sizeof(smime_encryption_tab[0])), + + /* encryption_tab */ smime_encryption_tab +}; + +#ifdef LIBETPAN_REENTRANT +#if defined(HAVE_PTHREAD_H) && !defined(IGNORE_PTHREAD_H) + static pthread_mutex_t encryption_id_hash_lock = PTHREAD_MUTEX_INITIALIZER; +#define LOCK() pthread_mutex_lock(&encryption_id_hash_lock) +#define UNLOCK() pthread_mutex_unlock(&encryption_id_hash_lock) +#elif (defined WIN32) + static CRITICAL_SECTION encryption_id_hash_lock = {0}; +#define LOCK() EnterCriticalSection(&encryption_id_hash_lock); +#define UNLOCK() LeaveCriticalSection(&encryption_id_hash_lock); +#endif +#else +#define LOCK() do {} while (0) +#define UNLOCK() do {} while (0) +#endif + +static void mailprivacy_smime_init_lock(void) +{ +#ifdef LIBETPAN_REENTRANT +#if defined(HAVE_PTHREAD_H) && !defined(IGNORE_PTHREAD_H) +#elif (defined WIN32) + static int mailprivacy_smime_init_lock_done = 0; + if (InterlockedExchange(&mailprivacy_smime_init_lock_done, 1) == 0) { + InitializeCriticalSection(&encryption_id_hash_lock); + } +#endif +#endif +} + +int mailprivacy_smime_init(struct mailprivacy * privacy) +{ + mailprivacy_smime_init_lock(); + certificates = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL); + if (certificates == NULL) + goto err; + + private_keys = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL); + if (private_keys == NULL) + goto free_cert; + + CAcert_dir[0] = '\0'; + + return mailprivacy_register(privacy, &smime_protocol); + + free_cert: + chash_free(certificates); + err: + return MAIL_ERROR_MEMORY; +} + +void mailprivacy_smime_done(struct mailprivacy * privacy) +{ + mailprivacy_unregister(privacy, &smime_protocol); + chash_free(private_keys); + private_keys = NULL; + chash_free(certificates); + certificates = NULL; + if (CAfile != NULL) { + unlink(CAfile); + free(CAfile); + } + CAfile = NULL; + CAcert_dir[0] = '\0'; +} + + +static void strip_string(char * str) +{ + char * p; + size_t len; + + p = strchr(str, '\r'); + if (p != NULL) + * p = 0; + + p = strchr(str, '\n'); + if (p != NULL) + * p = 0; + + p = str; + while ((* p == ' ') || (* p == '\t')) { + p ++; + } + + len = strlen(p); + memmove(str, p, len); + str[len] = 0; + + if (len == 0) + return; + + p = str; + len = len - 1; + while ((p[len] == ' ') || (p[len] == '\t')) { + p[len] = '\0'; + + if (len == 0) + break; + + len --; + } +} + + + +#define MAX_EMAIL_SIZE 1024 + +static void set_file(chash * hash, char * email, char * filename) +{ + char * n; + char buf[MAX_EMAIL_SIZE]; + chashdatum key; + chashdatum data; + + strncpy(buf, email, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + for(n = buf ; * n != '\0' ; n ++) + * n = toupper((unsigned char) * n); + strip_string(buf); + + key.data = buf; + key.len = (unsigned int) strlen(buf); + data.data = filename; + data.len = (unsigned int) strlen(filename) + 1; + + chash_set(hash, &key, &data, NULL); +} + +static char * get_file(chash * hash, char * email) +{ + chashdatum key; + chashdatum data; + char buf[MAX_EMAIL_SIZE]; + char * n; + int r; + + strncpy(buf, email, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + for(n = buf ; * n != '\0' ; n ++) + * n = toupper((unsigned char) * n); + + strip_string(buf); + key.data = buf; + key.len = (unsigned int) strlen(buf); + r = chash_get(hash, &key, &data); + if (r < 0) + return NULL; + + return data.data; +} + +#define CERTIFICATE_SUFFIX "-cert.pem" + +void mailprivacy_smime_set_cert_dir(struct mailprivacy * privacy, + char * directory) +{ + DIR * dir; + struct dirent * ent; + + chash_clear(certificates); + + if (directory == NULL) + return; + + if (* directory == '\0') + return; + + strncpy(cert_dir, directory, sizeof(cert_dir)); + cert_dir[sizeof(cert_dir) - 1] = '\0'; + + dir = opendir(directory); + if (dir == NULL) + return; + + while ((ent = readdir(dir)) != NULL) { +#if 0 + char quoted_filename[PATH_MAX]; + char filename[PATH_MAX]; + char command[PATH_MAX]; + char buf[MAX_EMAIL_SIZE]; + FILE * p; + int r; + + snprintf(filename, sizeof(filename), + "%s/%s", directory, ent->d_name); + + r = mail_quote_filename(quoted_filename, sizeof(quoted_filename), filename); + + snprintf(command, sizeof(command), + "openssl x509 -email -noout -in '%s' 2>/dev/null", quoted_filename); + + p = popen(command, "r"); + if (p == NULL) + continue; + + while (fgets(buf, sizeof(buf), p) != NULL) + set_file(certificates, buf, filename); + + pclose(p); +#endif + char filename[PATH_MAX]; + char email[PATH_MAX]; + char * p; + + snprintf(filename, sizeof(filename), + "%s/%s", directory, ent->d_name); + + strncpy(email, ent->d_name, sizeof(email)); + email[sizeof(email) - 1] = '\0'; + + p = strstr(email, CERTIFICATE_SUFFIX); + if (p == NULL) + continue; + + if (strlen(p) != sizeof(CERTIFICATE_SUFFIX) - 1) + continue; + + * p = 0; + + if (* email == '\0') + continue; + + set_file(certificates, email, filename); + } + closedir(dir); +} + +static char * get_cert_file(char * email) +{ + return get_file(certificates, email); +} + +static char * get_private_key_file(char * email) +{ + return get_file(private_keys, email); +} + +void mail_private_smime_clear_private_keys(struct mailprivacy * privacy) +{ + chash_clear(private_keys); +} + +#define MAX_BUF 1024 + +void mailprivacy_smime_set_CA_dir(struct mailprivacy * privacy, + char * directory) +{ + DIR * dir; + struct dirent * ent; + FILE * f_CA; + char CA_filename[PATH_MAX]; + + if (directory == NULL) + return; + + if (* directory == '\0') + return; + + /* make a temporary file that contains all the CAs */ + + if (CAfile != NULL) { + unlink(CAfile); + free(CAfile); + CAfile = NULL; + } + + f_CA = mailprivacy_get_tmp_file(privacy, CA_filename, sizeof(CA_filename)); + if (f_CA == NULL) + return; + + strncpy(CAcert_dir, directory, sizeof(CAcert_dir)); + CAcert_dir[sizeof(CAcert_dir) - 1] = '\0'; + + dir = opendir(directory); + if (dir == NULL) { + fclose(f_CA); + goto unlink_CA; + } + + while ((ent = readdir(dir)) != NULL) { + char filename[PATH_MAX]; + char buf[MAX_BUF]; + FILE * f; + + snprintf(filename, sizeof(filename), + "%s/%s", directory, ent->d_name); + + f = fopen(filename, "r"); + if (f == NULL) + continue; + + while (fgets(buf, sizeof(buf), f) != NULL) + fputs(buf, f_CA); + + fclose(f); + } + + closedir(dir); + + fclose(f_CA); + + CAfile = strdup(CA_filename); + if (CAfile == NULL) + goto unlink_CA; + + return; + + unlink_CA: + unlink(CA_filename); +} + +void mailprivacy_smime_set_CA_check(struct mailprivacy * privacy, + int enabled) +{ + CA_check = enabled; +} + +void mailprivacy_smime_set_store_cert(struct mailprivacy * privacy, + int enabled) +{ + store_cert = enabled; +} + +static int get_cert_from_sig(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime) +{ + clistiter * cur; + struct mailmime * signature_mime; + int res; + char signature_filename[PATH_MAX]; + char quoted_signature_filename[PATH_MAX]; + char * email; + char * cert_file; + char store_cert_filename[PATH_MAX]; + char quoted_store_cert_filename[PATH_MAX]; + int r; + char command[PATH_MAX]; + +#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR + //https://github.com/dinhviethoa/libetpan/issues/275 + //get_cert_from_sig is not needed on iOS + return MAIL_ERROR_COMMAND; +#endif + + if (* cert_dir == '\0') + return MAIL_ERROR_INVAL; + + if (mime->mm_type != MAILMIME_MULTIPLE) + return MAIL_ERROR_INVAL; + + email = get_first_from_addr(mime); + if (email == NULL) + return MAIL_ERROR_INVAL; + + cert_file = get_cert_file(email); + if (cert_file != NULL) + return MAIL_NO_ERROR; + + /* get the two parts of the S/MIME message */ + + cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list); + if (cur == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + cur = clist_next(cur); + if (cur == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + signature_mime = cur->data; + + r = mailprivacy_fetch_decoded_to_file(privacy, + signature_filename, sizeof(signature_filename), + msg, signature_mime); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mail_quote_filename(quoted_signature_filename, + sizeof(quoted_signature_filename), signature_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_signature; + } + + snprintf(store_cert_filename, sizeof(store_cert_filename), + "%s/%s" CERTIFICATE_SUFFIX, cert_dir, email); + + r = mail_quote_filename(quoted_store_cert_filename, + sizeof(quoted_store_cert_filename), store_cert_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_signature; + } + + snprintf(command, sizeof(command), + "openssl pkcs7 -inform DER -in '%s' -out '%s' -print_certs 2>/dev/null", + quoted_signature_filename, quoted_store_cert_filename); + +#if !TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR + //https://github.com/dinhviethoa/libetpan/issues/275 + //system() is not supported on iOS 11. + r = system(command); +#endif + + if (WEXITSTATUS(r) != 0) { + res = MAIL_ERROR_COMMAND; + goto unlink_signature; + } + + unlink(signature_filename); + + set_file(certificates, email, store_cert_filename); + + return MAIL_NO_ERROR; + + unlink_signature: + unlink(signature_filename); + err: + return res; +} + + +static void set_private_key(struct mailprivacy * privacy, + char * email, char * file) +{ + set_file(private_keys, email, file); +} + +#define PRIVATE_KEY_SUFFIX "-private-key.pem" + +void mailprivacy_smime_set_private_keys_dir(struct mailprivacy * privacy, + char * directory) +{ + DIR * dir; + struct dirent * ent; + + chash_clear(private_keys); + + if (directory == NULL) + return; + + if (* directory == '\0') + return; + + strncpy(private_keys_dir, directory, sizeof(private_keys_dir)); + private_keys_dir[sizeof(private_keys_dir) - 1] = '\0'; + + dir = opendir(directory); + if (dir == NULL) + return; + + while ((ent = readdir(dir)) != NULL) { + char filename[PATH_MAX]; + char email[PATH_MAX]; + char * p; + + snprintf(filename, sizeof(filename), + "%s/%s", directory, ent->d_name); + + strncpy(email, ent->d_name, sizeof(email)); + email[sizeof(email) - 1] = '\0'; + + p = strstr(email, PRIVATE_KEY_SUFFIX); + if (p == NULL) + continue; + + if (strlen(p) != sizeof(PRIVATE_KEY_SUFFIX) - 1) + continue; + + * p = 0; + + if (* email == '\0') + continue; + + set_private_key(privacy, email, filename); + } + closedir(dir); +} + +/* + - try private keys without passphrase and try those + for which we already have a passphrase, + - try recipient list and ask passphrase, + - then, ask passphrase for all private keys +*/ + +static char * get_passphrase(struct mailprivacy * privacy, + char * user_id); + +static int smime_command_passphrase(struct mailprivacy * privacy, + struct mailmessage * msg, + char * command, + char * userid, + char * stdoutfile, char * stderrfile) +{ + char * passphrase; + int res; + int bad_passphrase; + + bad_passphrase = 0; + + passphrase = NULL; + if (userid != NULL) + passphrase = get_passphrase(privacy, userid); + + res = mailprivacy_spawn_and_wait(command, passphrase, stdoutfile, stderrfile, + &bad_passphrase); + if (res != NO_ERROR_PASSPHRASE) { + switch (res) { + case ERROR_PASSPHRASE_COMMAND: + return ERROR_SMIME_COMMAND; + case ERROR_PASSPHRASE_FILE: + return ERROR_SMIME_FILE; + default: + return ERROR_SMIME_COMMAND; + } + return res; + } + + if (bad_passphrase) { + if (userid != NULL) { + mailprivacy_smime_add_encryption_id(privacy, msg, userid); + return ERROR_SMIME_NOPASSPHRASE; + } + + return ERROR_SMIME_CHECK; + } + + return NO_ERROR_SMIME; +} + + + +static chash * encryption_id_hash = NULL; + +static clist * get_list(struct mailprivacy * privacy, mailmessage * msg) +{ + clist * encryption_id_list; + + encryption_id_list = NULL; + if (encryption_id_hash != NULL) { + chashdatum key; + chashdatum value; + int r; + + key.data = &msg; + key.len = sizeof(msg); + r = chash_get(encryption_id_hash, &key, &value); + if (r == 0) { + encryption_id_list = value.data; + } + } + + return encryption_id_list; +} + +void mailprivacy_smime_encryption_id_list_clear(struct mailprivacy * privacy, + mailmessage * msg) +{ + clist * encryption_id_list; + clistiter * iter; + + LOCK(); + encryption_id_list = get_list(privacy, msg); + if (encryption_id_list != NULL) { + chashdatum key; + + for(iter = clist_begin(encryption_id_list) ; + iter != NULL ; iter = clist_next(iter)) { + char * str; + + str = clist_content(iter); + free(str); + } + clist_free(encryption_id_list); + + key.data = &msg; + key.len = sizeof(msg); + chash_delete(encryption_id_hash, &key, NULL); + + if (chash_count(encryption_id_hash) == 0) { + chash_free(encryption_id_hash); + encryption_id_hash = NULL; + } + } + UNLOCK(); +} + +clist * mailprivacy_smime_encryption_id_list(struct mailprivacy * privacy, + mailmessage * msg) +{ + clist * encryption_id_list; + + LOCK(); + encryption_id_list = get_list(privacy, msg); + UNLOCK(); + + return encryption_id_list; +} + +static int mailprivacy_smime_add_encryption_id(struct mailprivacy * privacy, + mailmessage * msg, char * encryption_id) +{ + clist * encryption_id_list; + int r; + int res; + + LOCK(); + + res = -1; + + encryption_id_list = get_list(privacy, msg); + if (encryption_id_list == NULL) { + if (encryption_id_hash == NULL) + encryption_id_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + + if (encryption_id_hash != NULL) { + encryption_id_list = clist_new(); + if (encryption_id_list != NULL) { + chashdatum key; + chashdatum value; + + key.data = &msg; + key.len = sizeof(msg); + value.data = encryption_id_list; + value.len = 0; + r = chash_set(encryption_id_hash, &key, &value, NULL); + if (r < 0) + clist_free(encryption_id_list); + } + } + } + + encryption_id_list = get_list(privacy, msg); + if (encryption_id_list != NULL) { + char * str; + + str = strdup(encryption_id); + if (str != NULL) { + r = clist_append(encryption_id_list, str); + if (r < 0) { + free(str); + } + else { + res = 0; + } + } + } + + UNLOCK(); + + return res; +} + +static chash * passphrase_hash = NULL; + +int mailprivacy_smime_set_encryption_id(struct mailprivacy * privacy, + char * user_id, char * passphrase) +{ + chashdatum key; + chashdatum value; + int r; + char buf[MAX_EMAIL_SIZE]; + char * n; + + strncpy(buf, user_id, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + for(n = buf ; * n != '\0' ; n ++) + * n = toupper((unsigned char) * n); + + if (passphrase_hash == NULL) { + passphrase_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL); + if (passphrase_hash == NULL) + return MAIL_ERROR_MEMORY; + } + + key.data = buf; + key.len = (unsigned int) strlen(buf) + 1; + value.data = passphrase; + value.len = (unsigned int) strlen(passphrase) + 1; + + r = chash_set(passphrase_hash, &key, &value, NULL); + if (r < 0) { + return MAIL_ERROR_MEMORY; + } + + return MAIL_NO_ERROR; +} + +static char * get_passphrase(struct mailprivacy * privacy, + char * user_id) +{ + chashdatum key; + chashdatum value; + int r; + char * passphrase; + char buf[MAX_EMAIL_SIZE]; + char * n; + + strncpy(buf, user_id, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + for(n = buf ; * n != '\0' ; n ++) + * n = toupper((unsigned char) * n); + + if (passphrase_hash == NULL) + return NULL; + + key.data = buf; + key.len = (unsigned int) strlen(buf) + 1; + + r = chash_get(passphrase_hash, &key, &value); + if (r < 0) + return NULL; + + passphrase = strdup(value.data); + + return passphrase; +} diff --git a/Sources/libetpan/engine/mailprivacy_smime.h b/Sources/libetpan/engine/mailprivacy_smime.h new file mode 100644 index 00000000..bb2d57a8 --- /dev/null +++ b/Sources/libetpan/engine/mailprivacy_smime.h @@ -0,0 +1,104 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailprivacy_smime.h,v 1.5 2007/10/30 00:40:39 hoa Exp $ + */ + +#ifndef MAILPRIVACY_SMIME_H + +#define MAILPRIVACY_SMIME_H + +#include + +LIBETPAN_EXPORT +int mailprivacy_smime_init(struct mailprivacy * privacy); + +LIBETPAN_EXPORT +void mailprivacy_smime_done(struct mailprivacy * privacy); + +LIBETPAN_EXPORT +void mailprivacy_smime_set_cert_dir(struct mailprivacy * privacy, + char * directory); + + +/* + set directory where certificates of authority certifications are + stored. +*/ + +LIBETPAN_EXPORT +void mailprivacy_smime_set_CA_dir(struct mailprivacy * privacy, + char * directory); + + +/* + to disable the verification of signers certificates of a + signed message. +*/ + +LIBETPAN_EXPORT +void mailprivacy_smime_set_CA_check(struct mailprivacy * privacy, + int enabled); + + +/* + to store certificates of signed messages +*/ + +LIBETPAN_EXPORT +void mailprivacy_smime_set_store_cert(struct mailprivacy * privacy, + int enabled); + +/* + set directory where private keys are stored. + name of the files in that directory must be in form : + [email-address]-private-key.pem +*/ + +LIBETPAN_EXPORT +void mailprivacy_smime_set_private_keys_dir(struct mailprivacy * privacy, + char * directory); + + +LIBETPAN_EXPORT +clist * mailprivacy_smime_encryption_id_list(struct mailprivacy * privacy, + mailmessage * msg); + +LIBETPAN_EXPORT +void mailprivacy_smime_encryption_id_list_clear(struct mailprivacy * privacy, + mailmessage * msg); + +LIBETPAN_EXPORT +int mailprivacy_smime_set_encryption_id(struct mailprivacy * privacy, + char * user_id, char * passphrase); + +#endif diff --git a/Sources/libetpan/engine/mailprivacy_tools.c b/Sources/libetpan/engine/mailprivacy_tools.c new file mode 100644 index 00000000..69c6a5b3 --- /dev/null +++ b/Sources/libetpan/engine/mailprivacy_tools.c @@ -0,0 +1,1578 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailprivacy_tools.c,v 1.18 2011/01/06 00:09:52 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#if __APPLE__ +#include +#endif + +#include "mailprivacy_tools.h" +#include "mailprivacy_tools_private.h" + +#include +#include +#include +#ifdef WIN32 +# include "win_etpan.h" +#else +# include +# include +# include +#endif +#include +#include +#include +#include +#include +#include "mailprivacy.h" +#include +#include + +void mailprivacy_mime_clear(struct mailmime * mime) +{ + struct mailmime_data * data; + clistiter * cur; + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + data = mime->mm_data.mm_single; + if (data != NULL) { + if (data->dt_type == MAILMIME_DATA_FILE) + unlink(data->dt_data.dt_filename); + } + break; + + case MAILMIME_MULTIPLE: + data = mime->mm_data.mm_multipart.mm_preamble; + if (data != NULL) { + if (data->dt_type == MAILMIME_DATA_FILE) + unlink(data->dt_data.dt_filename); + } + data = mime->mm_data.mm_multipart.mm_epilogue; + if (data != NULL) { + if (data->dt_type == MAILMIME_DATA_FILE) + unlink(data->dt_data.dt_filename); + } + + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * submime; + + submime = clist_content(cur); + + mailprivacy_mime_clear(submime); + } + break; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + mailprivacy_mime_clear(mime->mm_data.mm_message.mm_msg_mime); + } + break; + } +} + + +static FILE * get_tmp_file(char * filename) +{ + int fd; + mode_t old_mask; + FILE * f; + + old_mask = umask(0077); + fd = mkstemp(filename); + umask(old_mask); + if (fd == -1) + return NULL; + + f = fdopen(fd, "r+"); + if (f == NULL) { + close(fd); + unlink(filename); + } + + return f; +} + +FILE * mailprivacy_get_tmp_file(struct mailprivacy * privacy, + char * filename, size_t size) +{ + snprintf(filename, size, "%s/libetpan-privacy-XXXXXX", privacy->tmp_dir); + return get_tmp_file(filename); +} + +int mailprivacy_get_tmp_filename(struct mailprivacy * privacy, + char * filename, size_t size) +{ + FILE * f; + + f = mailprivacy_get_tmp_file(privacy, filename, size); + if (f == NULL) + return MAIL_ERROR_FILE; + + fclose(f); + + return MAIL_NO_ERROR; +} + +static char * dup_file(struct mailprivacy * privacy, + char * source_filename) +{ + char filename[PATH_MAX]; + FILE * dest_f; + int r; + struct stat stat_info; + char * dest_filename; + char * mapping; + size_t written; + int fd; + + dest_f = mailprivacy_get_tmp_file(privacy, filename, sizeof(filename)); + if (dest_f == NULL) + goto err; + + dest_filename = strdup(filename); + if (dest_filename == NULL) + goto close_dest; + + fd = open(source_filename, O_RDONLY); + if (fd < 0) + goto free_dest; + + r = fstat(fd, &stat_info); + if (r < 0) + goto close_src; + + mapping = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapping == (char *)MAP_FAILED) + goto close_src; + + written = fwrite(mapping, 1, stat_info.st_size, dest_f); + if (written != (size_t) stat_info.st_size) + goto unmap; + + munmap(mapping, stat_info.st_size); + close(fd); + fclose(dest_f); + + return dest_filename; + + unmap: + munmap(mapping, stat_info.st_size); + close_src: + close(fd); + free_dest: + free(dest_filename); + close_dest: + fclose(dest_f); + err: + return NULL; +} + + +/* + mime_data_replace() + + write a mime part to a file and change the reference of mailmime_data + to the file. +*/ + +static int mime_data_replace(struct mailprivacy * privacy, + int encoding_type, + struct mailmime_data * data, + int reencode) +{ + char filename[PATH_MAX]; + FILE * f; + size_t written; + char * dup_filename; + int res; + int r; + int decoded; + + if (data->dt_type != MAILMIME_DATA_TEXT) { + res = MAIL_NO_ERROR; + goto err; + } + + f = mailprivacy_get_tmp_file(privacy, filename, sizeof(filename)); + if (f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + decoded = 0; + if (reencode) { + if (encoding_type != -1) { + char * content; + size_t content_len; + size_t cur_token; + + cur_token = 0; + r = mailmime_part_parse(data->dt_data.dt_text.dt_data, + data->dt_data.dt_text.dt_length, + &cur_token, encoding_type, &content, &content_len); + + if (r == MAILIMF_NO_ERROR) { + /* write decoded */ + written = fwrite(content, 1, content_len, f); + if (written != content_len) { + fclose(f); + unlink(filename); + res = MAIL_ERROR_FILE; + goto err; + } + mmap_string_unref(content); + + decoded = 1; + data->dt_encoded = 0; + } + } + } + + if (!decoded) { + written = fwrite(data->dt_data.dt_text.dt_data, 1, + data->dt_data.dt_text.dt_length, f); + if (written != data->dt_data.dt_text.dt_length) { + fclose(f); + unlink(filename); + res = MAIL_ERROR_FILE; + goto err; + } + } + + fclose(f); + + dup_filename = strdup(filename); + if (dup_filename == NULL) { + unlink(filename); + res = MAIL_ERROR_MEMORY; + goto err; + } + + data->dt_type = MAILMIME_DATA_FILE; + data->dt_data.dt_filename = dup_filename; + + return MAIL_NO_ERROR; + + err: + return res; +} + + +/* + recursive_replace_single_parts() + + write all parts of the given mime part to file. +*/ + +static int recursive_replace_single_parts(struct mailprivacy * privacy, + struct mailmime * mime, int reencode) +{ + int r; + int res; + clistiter * cur; + + mime->mm_mime_start = NULL; + + switch(mime->mm_type) { + case MAILMIME_SINGLE: + if (mime->mm_data.mm_single != NULL) { + int encoding_type; + struct mailmime_single_fields single_fields; + + mailmime_single_fields_init(&single_fields, mime->mm_mime_fields, + mime->mm_content_type); + + if (single_fields.fld_encoding != NULL) + encoding_type = single_fields.fld_encoding->enc_type; + else + encoding_type = -1; + + r = mime_data_replace(privacy, encoding_type, + mime->mm_data.mm_single, reencode); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + break; + + case MAILMIME_MULTIPLE: + if (mime->mm_data.mm_multipart.mm_preamble != NULL) { + r = mime_data_replace(privacy, -1, + mime->mm_data.mm_multipart.mm_preamble, reencode); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + + if (mime->mm_data.mm_multipart.mm_epilogue != NULL) { + r = mime_data_replace(privacy, -1, + mime->mm_data.mm_multipart.mm_epilogue, reencode); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * child; + + child = clist_content(cur); + + r = recursive_replace_single_parts(privacy, child, reencode); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + + break; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + r = recursive_replace_single_parts(privacy, + mime->mm_data.mm_message.mm_msg_mime, reencode); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + break; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +/* + mailprivacy_get_mime() + + parse the message in MIME structure, + all single MIME parts are stored in files. + + privacy can be set to NULL to disable privacy check. +*/ + +int mailprivacy_get_mime(struct mailprivacy * privacy, + int check_privacy, int reencode, + char * content, size_t content_len, + struct mailmime ** result_mime) +{ + struct mailmime * mime; + mailmessage * msg; + int r; + int res; + +#if 0 + int check_privacy; + + check_privacy = (privacy != NULL); +#endif + + /* + use message data driver, get bodystructure and + convert all the data part in MAILMIME_SINGLE to files. + */ + + msg = data_message_init(content, content_len); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + +#if 0 + if (msg->mime == NULL) { + if (check_privacy) { + r = mailprivacy_msg_get_bodystructure(privacy, msg, &mime); + } + else { + /* + don't use etpan_msg_get_bodystructure because it is not useful + and to avoid loops due to security part + */ + r = mailmessage_get_bodystructure(msg, &mime); + } + } + else { + mime = msg->mime; + } +#endif + + if (check_privacy) + r = mailprivacy_msg_get_bodystructure(privacy, msg, &mime); + else + r = mailmessage_get_bodystructure(msg, &mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_msg; + } + + /* + should be done so that the MIME structure need not to be unregistered. + */ + mailprivacy_recursive_unregister_mime(privacy, mime); + + r = recursive_replace_single_parts(privacy, mime, reencode); + if (r != MAIL_NO_ERROR) { + res = r; + goto clear_mime; + } + + data_message_detach_mime(msg); +#if 0 + if (check_privacy) + mailprivacy_msg_flush(privacy, msg); + else + mailmessage_flush(msg); +#endif + mailprivacy_msg_flush(privacy, msg); + mailmessage_free(msg); + + * result_mime = mime; + + return MAIL_NO_ERROR; + + clear_mime: + mailprivacy_mime_clear(mime); + mailprivacy_msg_flush(privacy, msg); + free_msg: + mailmessage_free(msg); + err: + return res; +} + +#ifndef LIBETPAN_SYSTEM_BASENAME +static char * libetpan_basename(char * filename) +{ + char * next; + char * p; + + p = filename; + next = strchr(p, '/'); + + while (next != NULL) { + p = next; + next = strchr(p + 1, '/'); + } + + if (p == filename) + return filename; + else + return p + 1; +} +#else +#define libetpan_basename(a) basename(a) +#endif + +struct mailmime * +mailprivacy_new_file_part(struct mailprivacy * privacy, + char * filename, + char * default_content_type, int default_encoding) +{ + char basename_buf[PATH_MAX]; + struct mailmime_mechanism * encoding; + struct mailmime_content * content; + struct mailmime * mime; + int r; + char * dup_filename; + struct mailmime_fields * mime_fields; + int encoding_type; + char * content_type_str; + int do_encoding; + + if (filename != NULL) { + strncpy(basename_buf, filename, PATH_MAX); + libetpan_basename(basename_buf); + } + + encoding = NULL; + + /* default content-type */ + if (default_content_type == NULL) + content_type_str = "application/octet-stream"; + else + content_type_str = default_content_type; + + content = mailmime_content_new_with_str(content_type_str); + if (content == NULL) { + goto free_content; + } + + do_encoding = 1; + if (content->ct_type->tp_type == MAILMIME_TYPE_COMPOSITE_TYPE) { + struct mailmime_composite_type * composite; + + composite = content->ct_type->tp_data.tp_composite_type; + + switch (composite->ct_type) { + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + if (strcasecmp(content->ct_subtype, "rfc822") == 0) + do_encoding = 0; + break; + + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + do_encoding = 0; + break; + } + } + + if (do_encoding) { + if (default_encoding == -1) + encoding_type = MAILMIME_MECHANISM_BASE64; + else + encoding_type = default_encoding; + + /* default Content-Transfer-Encoding */ + encoding = mailmime_mechanism_new(encoding_type, NULL); + if (encoding == NULL) { + goto free_content; + } + } + + mime_fields = mailmime_fields_new_with_data(encoding, + NULL, NULL, NULL, NULL); + if (mime_fields == NULL) { + goto free_content; + } + + mime = mailmime_new_empty(content, mime_fields); + if (mime == NULL) { + goto free_mime_fields; + } + + if ((filename != NULL) && (mime->mm_type == MAILMIME_SINGLE)) { + /* + duplicates the file so that the file can be deleted when + the MIME part is done + */ + dup_filename = dup_file(privacy, filename); + if (dup_filename == NULL) { + goto free_mime; + } + + r = mailmime_set_body_file(mime, dup_filename); + if (r != MAILIMF_NO_ERROR) { + free(dup_filename); + goto free_mime; + } + } + + return mime; + + free_mime: + mailmime_free(mime); + goto err; + free_mime_fields: + mailmime_fields_free(mime_fields); + mailmime_content_free(content); + goto err; + free_content: + if (encoding != NULL) + mailmime_mechanism_free(encoding); + if (content != NULL) + mailmime_content_free(content); + err: + return NULL; +} + + +int mailmime_substitute(struct mailmime * old_mime, + struct mailmime * new_mime) +{ + struct mailmime * parent; + + parent = old_mime->mm_parent; + if (parent == NULL) + return MAIL_ERROR_INVAL; + + if (old_mime->mm_parent_type == MAILMIME_MESSAGE) + parent->mm_data.mm_message.mm_msg_mime = new_mime; + else /* MAILMIME_MULTIPLE */ + old_mime->mm_multipart_pos->data = new_mime; + new_mime->mm_parent = parent; + new_mime->mm_parent_type = old_mime->mm_parent_type; + + /* detach old_mime */ + old_mime->mm_parent = NULL; + old_mime->mm_parent_type = MAILMIME_NONE; + + return MAIL_NO_ERROR; +} + + + +/* write mime headers and body to a file, CR LF fixed */ + +int mailprivacy_fetch_mime_body_to_file(struct mailprivacy * privacy, + char * filename, size_t size, + mailmessage * msg, struct mailmime * mime) +{ + int r; + int res; + FILE * f; + char * content; + size_t content_len; + int col; + + if (mime->mm_parent_type == MAILMIME_NONE) { + res = MAIL_ERROR_INVAL; + goto err; + } + + f = mailprivacy_get_tmp_file(privacy, filename, size); + if (f == NULL) { + res = MAIL_ERROR_FETCH; + goto err; + } + + r = mailprivacy_msg_fetch_section_mime(privacy, msg, mime, + &content, &content_len); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_FETCH; + goto close; + } + + col = 0; + r = mailimf_string_write(f, &col, content, content_len); + mailprivacy_msg_fetch_result_free(privacy, msg, content); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto close; + } + + r = mailprivacy_msg_fetch_section(privacy, msg, mime, + &content, &content_len); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_FETCH; + goto close; + } + + r = mailimf_string_write(f, &col, content, content_len); + mailprivacy_msg_fetch_result_free(privacy, msg, content); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto close; + } + + fclose(f); + + return MAIL_NO_ERROR; + + close: + fclose(f); + unlink(filename); + err: + return res; +} + + +int mailprivacy_get_part_from_file(struct mailprivacy * privacy, + int check_security, int reencode, char * filename, + struct mailmime ** result_mime) +{ + int fd; + struct mailmime * mime; + int r; + struct stat stat_info; + int res; + char * mapping; + + fd = open(filename, O_RDONLY); + if (fd < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + r = fstat(fd, &stat_info); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto close; + } + + mapping = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapping == (char *)MAP_FAILED) { + res = MAIL_ERROR_FILE; + goto close; + } + + mime = NULL; + /* check recursive parts if privacy is set */ + r = mailprivacy_get_mime(privacy, check_security, reencode, + mapping, stat_info.st_size, &mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto unmap; + } + + if (mime->mm_type == MAILMIME_MESSAGE) { + struct mailmime * submime; + + submime = mime->mm_data.mm_message.mm_msg_mime; + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + mailmime_remove_part(submime); + mailmime_free(mime); + + mime = submime; + } + } + + munmap(mapping, stat_info.st_size); + + close(fd); + + * result_mime = mime; + + return MAIL_NO_ERROR; + + unmap: + munmap(mapping, stat_info.st_size); + close: + close(fd); + err: + return res; +} + +int mail_quote_filename(char * result, size_t size, char * path) +{ + char * p; + char * result_p; + size_t remaining; + + result_p = result; + remaining = size; + + for(p = path ; * p != '\0' ; p ++) { + int quote_not_needed; + +#if 0 + quote_not_needed = (isalpha(* p) || isdigit(* p) || (* p == '/')); +#else + quote_not_needed = (* p != '\\') && (* p != '\'') && (* p != '\"'); +#endif + if (quote_not_needed) { + if (remaining > 0) { + * result_p = * p; + result_p ++; + remaining --; + } + else { + result[size - 1] = '\0'; + return -1; + } + } + else { + if (remaining >= 2) { + * result_p = '\\'; + result_p ++; + * result_p = * p; + result_p ++; + remaining -= 2; + } + else { + result[size - 1] = '\0'; + return -1; + } + } + } + if (remaining > 0) { + * result_p = '\0'; + } + else { + result[size - 1] = '\0'; + return -1; + } + + return 0; +} + + +static void prepare_mime_single(struct mailmime * mime) +{ + struct mailmime_single_fields single_fields; + int encoding; + int r; + + if (mime->mm_mime_fields != NULL) { + mailmime_single_fields_init(&single_fields, mime->mm_mime_fields, + mime->mm_content_type); + if (single_fields.fld_encoding != NULL) { + encoding = single_fields.fld_encoding->enc_type; + switch (encoding) { + case MAILMIME_MECHANISM_8BIT: + case MAILMIME_MECHANISM_7BIT: + case MAILMIME_MECHANISM_BINARY: + single_fields.fld_encoding->enc_type = + MAILMIME_MECHANISM_QUOTED_PRINTABLE; + break; + } + } + else { + struct mailmime_mechanism * mechanism; + struct mailmime_field * field; + + mechanism = + mailmime_mechanism_new(MAILMIME_MECHANISM_QUOTED_PRINTABLE, NULL); + if (mechanism == NULL) + return; + + field = mailmime_field_new(MAILMIME_FIELD_TRANSFER_ENCODING, + NULL, mechanism, NULL, NULL, 0, NULL, NULL, NULL); + if (field == NULL) { + mailmime_mechanism_free(mechanism); + return; + } + + r = clist_append(mime->mm_mime_fields->fld_list, field); + if (r < 0) { + mailmime_field_free(field); + return; + } + } + } + + if (mime->mm_type == MAILMIME_SINGLE) { + switch (mime->mm_data.mm_single->dt_encoding) { + case MAILMIME_MECHANISM_8BIT: + case MAILMIME_MECHANISM_7BIT: + case MAILMIME_MECHANISM_BINARY: + mime->mm_data.mm_single->dt_encoding = + MAILMIME_MECHANISM_QUOTED_PRINTABLE; + mime->mm_data.mm_single->dt_encoded = 0; + break; + } + } +} + +/* + mailprivacy_prepare_mime() + + we assume we built ourself the message. +*/ + +void mailprivacy_prepare_mime(struct mailmime * mime) +{ + clistiter * cur; + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + if (mime->mm_data.mm_single != NULL) { + prepare_mime_single(mime); + } + break; + + case MAILMIME_MULTIPLE: + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * child; + + child = clist_content(cur); + + mailprivacy_prepare_mime(child); + } + break; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_msg_mime) { + mailprivacy_prepare_mime(mime->mm_data.mm_message.mm_msg_mime); + } + break; + } +} + + +char * mailprivacy_dup_imf_file(struct mailprivacy * privacy, + char * source_filename) +{ + char filename[PATH_MAX]; + FILE * dest_f; + int r; + struct stat stat_info; + char * dest_filename; + char * mapping; + int fd; + int col; + + dest_f = mailprivacy_get_tmp_file(privacy, + filename, sizeof(filename)); + if (dest_f == NULL) + goto err; + + dest_filename = strdup(filename); + if (dest_filename == NULL) + goto close_dest; + + fd = open(source_filename, O_RDONLY); + if (fd < 0) + goto free_dest; + + r = fstat(fd, &stat_info); + if (r < 0) + goto close_src; + + mapping = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapping == (char *)MAP_FAILED) + goto close_src; + + col = 0; + r = mailimf_string_write(dest_f, &col, mapping, stat_info.st_size); + if (r != MAILIMF_NO_ERROR) + goto unmap; + + munmap(mapping, stat_info.st_size); + close(fd); + fclose(dest_f); + + return dest_filename; + + unmap: + munmap(mapping, stat_info.st_size); + close_src: + close(fd); + free_dest: + free(dest_filename); + close_dest: + fclose(dest_f); + err: + return NULL; +} + +/* TODO : better function to duplicate mime fields, currenly such inelegant */ + +struct mailmime_fields * +mailprivacy_mime_fields_dup(struct mailprivacy * privacy, + struct mailmime_fields * mime_fields) +{ + FILE * f; + char tmp_file[PATH_MAX]; + int col; + int r; + struct mailmime_fields * dup_mime_fields; + int fd; + char * mapping; + struct stat stat_info; + struct mailimf_fields * fields; + size_t cur_token; + + f = mailprivacy_get_tmp_file(privacy, tmp_file, sizeof(tmp_file)); + if (f == NULL) + goto err; + + col = 0; + r = mailmime_fields_write(f, &col, mime_fields); + if (r != MAILIMF_NO_ERROR) + goto unlink; + + fflush(f); + + fd = fileno(f); + if (fd == -1) + goto unlink; + + r = fstat(fd, &stat_info); + if (r < 0) + goto unlink; + + mapping = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapping == (char *)MAP_FAILED) + goto unlink; + + cur_token = 0; + r = mailimf_optional_fields_parse(mapping, stat_info.st_size, + &cur_token, &fields); + if (r != MAILIMF_NO_ERROR) + goto unmap; + + r = mailmime_fields_parse(fields, &dup_mime_fields); + mailimf_fields_free(fields); + if (r != MAILIMF_NO_ERROR) + goto unmap; + + munmap(mapping, stat_info.st_size); + fclose(f); + unlink(tmp_file); + + return dup_mime_fields; + + unmap: + munmap(mapping, stat_info.st_size); + unlink: + fclose(f); + unlink(tmp_file); + err: + return NULL; +} + + + +struct mailmime_parameter * +mailmime_parameter_dup(struct mailmime_parameter * param) +{ + char * name; + char * value; + struct mailmime_parameter * dup_param; + + name = strdup(param->pa_name); + if (name == NULL) + goto err; + + value = strdup(param->pa_value); + if (value == NULL) + goto free_name; + + dup_param = mailmime_parameter_new(name, value); + if (dup_param == NULL) + goto free_value; + + return dup_param; + + free_value: + free(value); + free_name: + free(name); + err: + return NULL; +} + +struct mailmime_composite_type * +mailmime_composite_type_dup(struct mailmime_composite_type * composite_type) +{ + struct mailmime_composite_type * dup_composite; + char * token; + + token = NULL; + if (composite_type->ct_token != NULL) { + token = strdup(composite_type->ct_token); + if (token == NULL) + goto err; + } + + dup_composite = mailmime_composite_type_new(composite_type->ct_type, token); + if (dup_composite == NULL) + goto free_token; + + return dup_composite; + + free_token: + if (token != NULL) + free(token); + err: + return NULL; +} + +struct mailmime_discrete_type * +mailmime_discrete_type_dup(struct mailmime_discrete_type * discrete_type) +{ + struct mailmime_discrete_type * dup_discrete; + char * extension; + + extension = NULL; + if (discrete_type->dt_extension != NULL) { + extension = strdup(discrete_type->dt_extension); + if (extension == NULL) + goto err; + } + + dup_discrete = mailmime_discrete_type_new(discrete_type->dt_type, extension); + if (dup_discrete == NULL) + goto free_extension; + + return dup_discrete; + + free_extension: + if (extension != NULL) + free(extension); + err: + return NULL; +} + +struct mailmime_type * mailmime_type_dup(struct mailmime_type * type) +{ + struct mailmime_type * dup_type; + struct mailmime_discrete_type * discrete_type; + struct mailmime_composite_type * composite_type; + + discrete_type = NULL; + composite_type = NULL; + switch (type->tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + discrete_type = + mailmime_discrete_type_dup(type->tp_data.tp_discrete_type); + if (discrete_type == NULL) + goto err; + break; + + composite_type = + mailmime_composite_type_dup(type->tp_data.tp_composite_type); + if (composite_type == NULL) + goto free_discrete; + } + + dup_type = mailmime_type_new(type->tp_type, discrete_type, composite_type); + if (dup_type == NULL) + goto free_composite; + + return dup_type; + + free_composite: + if (composite_type != NULL) + mailmime_composite_type_free(composite_type); + free_discrete: + if (discrete_type != NULL) + mailmime_discrete_type_free(discrete_type); + err: + return NULL; +} + +struct mailmime_content * +mailmime_content_dup(struct mailmime_content * content) +{ + clist * list; + struct mailmime_type * type; + int r; + struct mailmime_content * dup_content; + char * subtype; + + type = mailmime_type_dup(content->ct_type); + if (type == NULL) + goto err; + + subtype = strdup(content->ct_subtype); + if (subtype == NULL) + goto free_type; + + list = clist_new(); + if (list == NULL) + goto free_subtype; + + if (content->ct_parameters != NULL) { + clistiter * cur; + + for(cur = clist_begin(content->ct_parameters) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = mailmime_parameter_dup(clist_content(cur)); + if (param == NULL) + goto free_list; + + r = clist_append(list, param); + if (r < 0) { + mailmime_parameter_free(param); + goto free_list; + } + } + } + + dup_content = mailmime_content_new(type, subtype, list); + if (dup_content == NULL) + goto free_list; + + return dup_content; + + free_list: + clist_foreach(list, (clist_func) mailmime_parameter_free, NULL); + free_subtype: + free(subtype); + free_type: + mailmime_type_free(type); + err: + return NULL; +} + + +int mailprivacy_fetch_decoded_to_file(struct mailprivacy * privacy, + char * filename, size_t size, + mailmessage * msg, struct mailmime * mime) +{ + int r; + int res; + FILE * f; + char * content; + size_t content_len; + size_t written; + struct mailmime_single_fields single_fields; + int encoding; + size_t cur_token; + char * parsed_content; + size_t parsed_content_len; + + mailmime_single_fields_init(&single_fields, mime->mm_mime_fields, + mime->mm_content_type); + if (single_fields.fld_encoding != NULL) + encoding = single_fields.fld_encoding->enc_type; + else + encoding = MAILMIME_MECHANISM_8BIT; + + r = mailprivacy_msg_fetch_section(privacy, msg, mime, + &content, &content_len); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_FETCH; + goto err; + } + + cur_token = 0; + r = mailmime_part_parse(content, content_len, &cur_token, + encoding, &parsed_content, &parsed_content_len); + mailprivacy_msg_fetch_result_free(privacy, msg, content); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_PARSE; + goto err; + } + + f = mailprivacy_get_tmp_file(privacy, filename, size); + if (f == NULL) { + res = MAIL_ERROR_FETCH; + goto free_fetch; + } + written = fwrite(parsed_content, 1, parsed_content_len, f); + if (written != parsed_content_len) { + res = MAIL_ERROR_FILE; + goto close; + } + fclose(f); + + mmap_string_unref(parsed_content); + + return MAIL_NO_ERROR; + + close: + fclose(f); + unlink(filename); + free_fetch: + mmap_string_unref(parsed_content); + err: + return res; +} + + + +#ifdef HAVE_MINGW32_SYSTEM +/* Define to 1 do enable debugging. */ +#define DEBUG_W32_SPAWN 0 + +/* Create pipe where the read end is inheritable. */ +static int +create_inheritable_pipe (HANDLE filedes[2]) +{ + HANDLE r, w, h; + SECURITY_ATTRIBUTES sec_attr; + + memset (&sec_attr, 0, sizeof sec_attr); + sec_attr.nLength = sizeof sec_attr; + sec_attr.bInheritHandle = FALSE; + + if (!CreatePipe (&r, &w, &sec_attr, 0)) + return -1; + + if (!DuplicateHandle (GetCurrentProcess(), r, + GetCurrentProcess(), &h, 0, + TRUE, DUPLICATE_SAME_ACCESS )) + { + CloseHandle (r); + CloseHandle (w); + return -1; + } + CloseHandle (w); + w = h; + + filedes[0] = r; + filedes[1] = w; + return 0; +} +#endif /*HAVE_MINGW32_SYSTEM*/ + + +int mailprivacy_spawn_and_wait(char * command, char * passphrase, + char * stdoutfile, char * stderrfile, + int * bad_passphrase) +{ +#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR + //https://github.com/dinhviethoa/libetpan/issues/275 + //mailprivacy_spawn_and_wait is not needed on iOS + return MAIL_ERROR_COMMAND; +#endif + +#ifdef WIN32 + int res; + SECURITY_ATTRIBUTES sec_attr; + PROCESS_INFORMATION pi = + { + NULL, /* Returns process handle. */ + 0, /* Returns primary thread handle. */ + 0, /* Returns pid. */ + 0 /* Returns tid. */ + }; + STARTUPINFO si; + int cr_flags; + HANDLE wp_passphrase[2]; + HANDLE fd_out; + HANDLE fd_err; + int code; + + /* Prepare security attributes. */ + memset (&sec_attr, 0, sizeof sec_attr); + sec_attr.nLength = sizeof sec_attr; + sec_attr.bInheritHandle = TRUE; + + fd_out = CreateFile (stdoutfile, + GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ|FILE_SHARE_WRITE, + &sec_attr, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (fd_out == INVALID_HANDLE_VALUE) + { + res = ERROR_PASSPHRASE_FILE; + goto err; + } + + fd_err = CreateFile (stderrfile, + GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ|FILE_SHARE_WRITE, + &sec_attr, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (fd_err == INVALID_HANDLE_VALUE) + { + res = ERROR_PASSPHRASE_FILE; + goto close_out; + } + + /* Create a pipe for the passphrase. */ + if (create_inheritable_pipe (wp_passphrase)) + { + res = ERROR_PASSPHRASE_FILE; + goto close_err; + } + + /* Prepare security attributes. */ + memset (&sec_attr, 0, sizeof sec_attr); + sec_attr.nLength = sizeof sec_attr; + sec_attr.bInheritHandle = FALSE; + + /* Start the process. */ + memset (&si, 0, sizeof si); + si.cb = sizeof (si); + si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; + si.wShowWindow = DEBUG_W32_SPAWN ? SW_SHOW : SW_MINIMIZE; + si.hStdInput = wp_passphrase[0]; + si.hStdOutput = fd_out; + si.hStdError = fd_err; + + cr_flags = (CREATE_DEFAULT_ERROR_MODE + | GetPriorityClass (GetCurrentProcess ()) + | CREATE_SUSPENDED); + if (!CreateProcess (NULL, /* Program to start. */ + command, /* Command line arguments. */ + &sec_attr, /* Process security attributes. */ + &sec_attr, /* Thread security attributes. */ + TRUE, /* Inherit handles. */ + cr_flags, /* Creation flags. */ + NULL, /* Environment. */ + NULL, /* Use current drive/directory. */ + &si, /* Startup information. */ + &pi /* Returns process information. */ + )) + { + CloseHandle (wp_passphrase[0]); + CloseHandle (wp_passphrase[1]); + + res = ERROR_PASSPHRASE_COMMAND; + goto close_err; + } + + /* Close the other end of the pipe. */ + CloseHandle (wp_passphrase[0]); + CloseHandle (fd_out); + CloseHandle (fd_err); + /* Process has been created suspended; resume it now. */ + ResumeThread (pi.hThread); + CloseHandle (pi.hThread); + + if ((passphrase != NULL) && (strlen(passphrase) > 0)) { + DWORD written; + WriteFile (wp_passphrase[1], passphrase, strlen(passphrase), + &written, NULL); + } + else { + DWORD written; + /* dummy password */ + WriteFile(wp_passphrase[1], "*dummy*", 7, &written, NULL); + } + CloseHandle(wp_passphrase[1]); + + code = WaitForSingleObject (pi.hProcess, INFINITE); + if (code == WAIT_OBJECT_0) + { + DWORD exc; + if (GetExitCodeProcess (pi.hProcess, &exc)) + { + if (exc) + *bad_passphrase = 1; + } + else + res = ERROR_PASSPHRASE_COMMAND; + } + else + res = ERROR_PASSPHRASE_COMMAND; + + CloseHandle (pi.hProcess); + return 0; + + close_err: + CloseHandle (fd_err); + close_out: + CloseHandle (fd_out); + err: + return res; +#else + int res; + int fd_out; + int fd_err; + pid_t pid; + int passphrase_input[2]; + int r; + + fd_out = open(stdoutfile, O_RDWR | O_CREAT | O_TRUNC, 0600); + if (fd_out < 0) { + res = ERROR_PASSPHRASE_FILE; + goto err; + } + + fd_err = open(stderrfile, O_RDWR | O_CREAT | O_TRUNC, 0600); + if (fd_err < 0) { + res = ERROR_PASSPHRASE_FILE; + goto close_out; + } + + r = pipe(passphrase_input); + if (r < 0) { + res = ERROR_PASSPHRASE_FILE; + goto close_err; + } + + pid = fork(); + switch (pid) { + case -1: + { + close (passphrase_input[0]); + close (passphrase_input[1]); + res = ERROR_PASSPHRASE_COMMAND; + goto close_err; + } + + case 0: + /* child */ + { + int status; + + /* close unneeded fd */ + close(passphrase_input[1]); + + dup2(passphrase_input[0], 0); + close(passphrase_input[0]); + dup2(fd_out, 1); + close(fd_out); + dup2(fd_err, 2); + close(fd_err); + +#if !TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR + //https://github.com/dinhviethoa/libetpan/issues/275 + //system() is not supported on iOS 11. + status = system(command); +#endif + + exit(WEXITSTATUS(status)); + } + break; + + default: + /* parent */ + { + int status; + + /* close unneeded fd */ + close(fd_err); + close(fd_out); + close(passphrase_input[0]); + + if ((passphrase != NULL) && (strlen(passphrase) > 0)) { + r = (int) write(passphrase_input[1], passphrase, strlen(passphrase)); + if (r != (int) strlen(passphrase)) { + close(passphrase_input[1]); + return ERROR_PASSPHRASE_FILE; + } + } + else { + /* dummy password */ + r = (int) write(passphrase_input[1], "*dummy*", 7); + if (r != 7) { + close(passphrase_input[1]); + return ERROR_PASSPHRASE_FILE; + } + } + close(passphrase_input[1]); + + waitpid(pid, &status, 0); + + if (WEXITSTATUS(status) != 0) + *bad_passphrase = 1; + + return MAIL_NO_ERROR; + } + break; + } + + close_err: + close(fd_err); + close_out: + close(fd_out); + err: + return res; +#endif +} + + diff --git a/Sources/libetpan/engine/mailprivacy_tools.h b/Sources/libetpan/engine/mailprivacy_tools.h new file mode 100644 index 00000000..cd6241f6 --- /dev/null +++ b/Sources/libetpan/engine/mailprivacy_tools.h @@ -0,0 +1,120 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailprivacy_tools.h,v 1.7 2007/12/10 21:32:59 hoa Exp $ + */ + +#ifndef MAIL_PRIVACY_TOOLS_H + +#define MAIL_PRIVACY_TOOLS_H + +#include +#include + +LIBETPAN_EXPORT +void mailprivacy_mime_clear(struct mailmime * mime); + +LIBETPAN_EXPORT +FILE * mailprivacy_get_tmp_file(struct mailprivacy * privacy, + char * filename, size_t size); + +LIBETPAN_EXPORT +int mailprivacy_get_tmp_filename(struct mailprivacy * privacy, + char * filename, size_t size); + +LIBETPAN_EXPORT +struct mailmime * +mailprivacy_new_file_part(struct mailprivacy * privacy, + char * filename, + char * default_content_type, int default_encoding); + +LIBETPAN_EXPORT +int mailmime_substitute(struct mailmime * old_mime, + struct mailmime * new_mime); + +LIBETPAN_EXPORT +int mailprivacy_fetch_mime_body_to_file(struct mailprivacy * privacy, + char * filename, size_t size, + mailmessage * msg, struct mailmime * mime); + +LIBETPAN_EXPORT +int mailprivacy_get_part_from_file(struct mailprivacy * privacy, + int check_privacy, int reencode, + char * filename, + struct mailmime ** result_mime); + +LIBETPAN_EXPORT +int mail_quote_filename(char * result, size_t size, char * path); + +LIBETPAN_EXPORT +void mailprivacy_prepare_mime(struct mailmime * mime); + +LIBETPAN_EXPORT +char * mailprivacy_dup_imf_file(struct mailprivacy * privacy, + char * source_filename); + +LIBETPAN_EXPORT +struct mailmime_fields * +mailprivacy_mime_fields_dup(struct mailprivacy * privacy, + struct mailmime_fields * mime_fields); + +LIBETPAN_EXPORT +struct mailmime_parameter * +mailmime_parameter_dup(struct mailmime_parameter * param); + +LIBETPAN_EXPORT +struct mailmime_composite_type * +mailmime_composite_type_dup(struct mailmime_composite_type * composite_type); + +LIBETPAN_EXPORT +struct mailmime_discrete_type * +mailmime_discrete_type_dup(struct mailmime_discrete_type * discrete_type); + +LIBETPAN_EXPORT +struct mailmime_type * mailmime_type_dup(struct mailmime_type * type); + +LIBETPAN_EXPORT +struct mailmime_content * +mailmime_content_dup(struct mailmime_content * content); + +LIBETPAN_EXPORT +int mailprivacy_fetch_decoded_to_file(struct mailprivacy * privacy, + char * filename, size_t size, + mailmessage * msg, struct mailmime * mime); + +LIBETPAN_EXPORT +int mailprivacy_get_mime(struct mailprivacy * privacy, + int check_privacy, int reencode, + char * content, size_t content_len, + struct mailmime ** result_mime); + +#endif diff --git a/Sources/libetpan/engine/mailprivacy_tools_private.h b/Sources/libetpan/engine/mailprivacy_tools_private.h new file mode 100644 index 00000000..8cbb4d4d --- /dev/null +++ b/Sources/libetpan/engine/mailprivacy_tools_private.h @@ -0,0 +1,48 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILPRIVACY_TOOLS_PRIVATE_H + +#define MAILPRIVACY_TOOLS_PRIVATE_H + +#include +#include + +enum { + NO_ERROR_PASSPHRASE = 0, + ERROR_PASSPHRASE_COMMAND, + ERROR_PASSPHRASE_FILE +}; + +int mailprivacy_spawn_and_wait(char * command, char * passphrase, + char * stdoutfile, char * stderrfile, + int * bad_passphrase); + +#endif diff --git a/Sources/libetpan/engine/mailprivacy_types.h b/Sources/libetpan/engine/mailprivacy_types.h new file mode 100644 index 00000000..e62fbfca --- /dev/null +++ b/Sources/libetpan/engine/mailprivacy_types.h @@ -0,0 +1,83 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailprivacy_types.h,v 1.4 2005/11/21 16:17:57 hoa Exp $ + */ + +#ifndef MAIL_PRIVACY_TYPES_H + +#define MAIL_PRIVACY_TYPES_H + +#include +#include +#include +#include + +struct mailprivacy { + char * tmp_dir; /* working tmp directory */ + chash * msg_ref; /* mailmessage => present or not */ + chash * mmapstr; /* mmapstring => present or not present */ + chash * mime_ref; /* mime => present or not */ + carray * protocols; + int make_alternative; + /* if make_alternative is 0, replaces the part with decrypted + part, if 1, adds a multipart/alternative and put the decrypted + and encrypted part as subparts. + */ +}; + +struct mailprivacy_encryption { + char * name; + char * description; + + int (* encrypt)(struct mailprivacy *, + mailmessage *, + struct mailmime *, struct mailmime **); +}; + +struct mailprivacy_protocol { + char * name; + char * description; + + /* introduced to easy the port to sylpheed */ + int (* is_encrypted)(struct mailprivacy *, + mailmessage *, struct mailmime *); + + int (* decrypt)(struct mailprivacy *, + mailmessage *, struct mailmime *, + struct mailmime **); + + int encryption_count; + struct mailprivacy_encryption * encryption_tab; +}; + +#endif diff --git a/Sources/libetpan/include/acl.h b/Sources/libetpan/include/acl.h new file mode 100644 index 00000000..8678927b --- /dev/null +++ b/Sources/libetpan/include/acl.h @@ -0,0 +1,165 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + TODO: parse extension to capability as defined in [rfc4314]. + capability =/ rights-capa + + This should actually be automatically parsed by parse_capability_data, + so maybe it's sufficient to code a higher-level (not mailimap) function + that returns a list of extra-rights as defined in rights-capa. +*/ + +#ifndef ACL_H + +#define ACL_H + +#include "libetpan-config.h" +#include "mailimap_extension.h" +#include "acl_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +LIBETPAN_EXPORT +extern struct mailimap_extension_api mailimap_extension_acl; + +/* + mailimap_acl_setacl() + + This will set access for an identifier on the mailbox specified. + + @param session the IMAP session + @param mailbox the mailbox to modify + @param identifier the identifier to set access-rights for + @param mod_rights the modification to make to the rights + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + +*/ + +LIBETPAN_EXPORT +int mailimap_acl_setacl(mailimap * session, + const char * mailbox, + const char * identifier, + const char * mod_rights); + +/* + mailimap_acl_deleteacl() + + This will remove the acl on the mailbox for the identifier specified. + + @param session the IMAP session + @param mailbox the mailbox to modify + @param identifier the identifier to remove acl for + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + +*/ + +LIBETPAN_EXPORT +int mailimap_acl_deleteacl(mailimap * session, + const char * mailbox, + const char * identifier); + +/* + mailimap_acl_getacl() + + This will get a list of acls for the mailbox + + @param session the IMAP session + @param mailbox the mailbox to get the acls for + @param result this will store a clist of (struct mailimap_acl_acl_data *) + in (* result) + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + +*/ + +LIBETPAN_EXPORT +int mailimap_acl_getacl(mailimap * session, + const char * mailbox, + clist ** result); + +/* + mailimap_acl_listrights() + + The LISTRIGHTS command takes a mailbox name and an identifier and + returns information about what rights can be granted to the + identifier in the ACL for the mailbox. + + @param session the IMAP session + @param mailbox the mailbox to get the acls for + @param identifier the identifier to query the acls for + @param result this will store a (struct mailimap_acl_listrights_data *) + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + +*/ + +LIBETPAN_EXPORT +int mailimap_acl_listrights(mailimap * session, + const char * mailbox, + const char * identifier, + struct mailimap_acl_listrights_data ** result); + +/* + mailimap_acl_myrights() + + This will list the rights for the querying user on the mailbox + + @param session the IMAP session + @param mailbox the mailbox to get the acls for + @param result this will store a (struct mailimap_acl_myrights_data *) + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + +*/ + +LIBETPAN_EXPORT +int mailimap_acl_myrights(mailimap * session, + const char * mailbox, + struct mailimap_acl_myrights_data ** result); + +LIBETPAN_EXPORT +int mailimap_has_acl(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/acl_parser.h b/Sources/libetpan/include/acl_parser.h new file mode 100644 index 00000000..061cc4a9 --- /dev/null +++ b/Sources/libetpan/include/acl_parser.h @@ -0,0 +1,92 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ACL_PARSER_H + +#define ACL_PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_parser.h" +#include "acl_types.h" + +int +mailimap_acl_acl_data_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_acl_acl_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_acl_listrights_data_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_acl_listrights_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_acl_myrights_data_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_acl_myrights_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_acl_identifier_rights_parse(mailstream * fd, + MMAPString *buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_acl_identifier_rights ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_acl_identifier_parse(mailstream * fd, + MMAPString *buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + char ** result, size_t progr_rate, + progress_function * progr_fun); + +int mailimap_acl_rights_parse(mailstream * fd, + MMAPString *buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + char ** result, size_t progr_rate, + progress_function * progr_fun); + +int mailimap_acl_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/acl_sender.h b/Sources/libetpan/include/acl_sender.h new file mode 100644 index 00000000..9796a7d4 --- /dev/null +++ b/Sources/libetpan/include/acl_sender.h @@ -0,0 +1,66 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ACL_SENDER_H + +#define ACL_SENDER_H + +#include "mailimap_sender.h" +#include "acl_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int mailimap_acl_setacl_send(mailstream * fd, + const char * mailbox, + const char * identifier, + const char * mod_rights); + +int mailimap_acl_deleteacl_send(mailstream * fd, + const char * mailbox, + const char * identifier); + +int mailimap_acl_getacl_send(mailstream * fd, + const char * mailbox); + +int mailimap_acl_listrights_send(mailstream * fd, + const char * mailbox, + const char * identifier); + +int mailimap_acl_myrights_send(mailstream * fd, + const char * mailbox); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/acl_types.h b/Sources/libetpan/include/acl_types.h new file mode 100644 index 00000000..b085bd5f --- /dev/null +++ b/Sources/libetpan/include/acl_types.h @@ -0,0 +1,169 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ACL_TYPES_H + +#define ACL_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "libetpan-config.h" +#include "mailstream.h" +#include "clist.h" + +/* + ACL grammar + see [rfc4314] for further information + + LOWER-ALPHA = %x61-7A ;; a-z + + acl-data = "ACL" SP mailbox *(SP identifier SP + rights) + + capability =/ rights-capa + ;;capability is defined in [IMAP4] + + command-auth =/ setacl / deleteacl / getacl / + listrights / myrights + ;;command-auth is defined in [IMAP4] + + deleteacl = "DELETEACL" SP mailbox SP identifier + + getacl = "GETACL" SP mailbox + + identifier = astring + + listrights = "LISTRIGHTS" SP mailbox SP identifier + + listrights-data = "LISTRIGHTS" SP mailbox SP identifier + SP rights *(SP rights) + + mailbox-data =/ acl-data / listrights-data / myrights-data + ;;mailbox-data is defined in [IMAP4] + + mod-rights = astring + ;; +rights to add, -rights to remove + ;; rights to replace + + myrights = "MYRIGHTS" SP mailbox + + myrights-data = "MYRIGHTS" SP mailbox SP rights + + new-rights = 1*LOWER-ALPHA + ;; MUST include "t", "e", "x", and "k". + ;; MUST NOT include standard rights listed + ;; in section 2.2 + + rights = astring + ;; only lowercase ASCII letters and digits + ;; are allowed. + + rights-capa = "RIGHTS=" new-rights + ;; RIGHTS=... capability + + setacl = "SETACL" SP mailbox SP identifier + SP mod-rights +*/ + +/* + only need to recognize types that can be "embedded" into main + IMAPrev1 types. +*/ +enum { + MAILIMAP_ACL_TYPE_ACL_DATA, /* child of mailbox-data */ + MAILIMAP_ACL_TYPE_LISTRIGHTS_DATA, /* child of mailbox-data */ + MAILIMAP_ACL_TYPE_MYRIGHTS_DATA /* child of mailbox-data */ +}; + +void mailimap_acl_identifier_free(char * identifier); + +void mailimap_acl_rights_free(char * rights); + +struct mailimap_acl_identifier_rights { + char * identifer; + char * rights; +}; + +struct mailimap_acl_identifier_rights * +mailimap_acl_identifier_rights_new(char * identifier, char * rights); + +void mailimap_acl_identifier_rights_free( + struct mailimap_acl_identifier_rights * id_rights); + +struct mailimap_acl_acl_data { + char * mailbox; + clist * idrights_list; + /* list of (struct mailimap_acl_identifier_rights *) */ +}; + +struct mailimap_acl_acl_data * +mailimap_acl_acl_data_new(char * mailbox, clist * idrights_list); + +LIBETPAN_EXPORT +void mailimap_acl_acl_data_free(struct + mailimap_acl_acl_data * acl_data); + +struct mailimap_acl_listrights_data { + char * mailbox; + char * identifier; + clist * rights_list; /* list of (char *) */ +}; + +struct mailimap_acl_listrights_data * +mailimap_acl_listrights_data_new(char * mailbox, + char * identifier, clist * rights_list); + +LIBETPAN_EXPORT +void mailimap_acl_listrights_data_free(struct + mailimap_acl_listrights_data * listrights_data); + +struct mailimap_acl_myrights_data { + char * mailbox; + char * rights; +}; + +struct mailimap_acl_myrights_data * +mailimap_acl_myrights_data_new(char * mailbox, char * rights); + +LIBETPAN_EXPORT +void mailimap_acl_myrights_data_free(struct + mailimap_acl_myrights_data * myrights_data); + +void +mailimap_acl_free(struct mailimap_extension_data * ext_data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/annotatemore.h b/Sources/libetpan/include/annotatemore.h new file mode 100644 index 00000000..7efaf03d --- /dev/null +++ b/Sources/libetpan/include/annotatemore.h @@ -0,0 +1,103 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ANNOTATEMORE_H + +#define ANNOTATEMORE_H + +#include "libetpan-config.h" +#include "mailimap_extension.h" +#include "annotatemore_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +LIBETPAN_EXPORT +extern struct mailimap_extension_api mailimap_extension_annotatemore; + +/* + mailimap_annotatemore_getannotation() + + This function will get annotations from given mailboxes or the server. + + @param session the IMAP session + @param list_mb mailbox name with possible wildcard, + empty string implies server annotation + @param entries entry specifier with possible wildcards + @param attribs attribute specifier with possible wildcards + @param result This will store a clist of (struct mailimap_annotate_data *) + in (* result) + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + +*/ + +LIBETPAN_EXPORT +int mailimap_annotatemore_getannotation(mailimap * session, + const char * list_mb, + struct mailimap_annotatemore_entry_match_list * entries, + struct mailimap_annotatemore_attrib_match_list * attribs, + clist ** result); + +/* + mailimap_annotatemore_setannotation() + + This function will set annotations on given mailboxes or the server. + + @param session the IMAP session + @param list_mb mailbox name with possible wildcard, + empty string implies server annotation + @param en_att a list of entries/attributes to set + @param result if return is MAILIMAP_ERROR_EXTENSION result + is MAILIMAP_ANNOTATEMORE_RESP_TEXT_CODE_TOOBIG or + MAILIMAP_ANNOTATEMORE_RESP_TEXT_CODE_TOOMANY for + extra information about the error. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_annotatemore_setannotation(mailimap * session, + const char * list_mb, + struct mailimap_annotatemore_entry_att_list * en_att, + int * result); + +LIBETPAN_EXPORT +int mailimap_has_annotatemore(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/annotatemore_parser.h b/Sources/libetpan/include/annotatemore_parser.h new file mode 100644 index 00000000..a8fdaf13 --- /dev/null +++ b/Sources/libetpan/include/annotatemore_parser.h @@ -0,0 +1,104 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ANNOTATEMORE_PARSER_H + +#define ANNOTATEMORE_PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_parser.h" +#include "annotatemore_types.h" + +int +mailimap_annotatemore_annotate_data_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_annotatemore_annotate_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_annotatemore_entry_list_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_annotatemore_entry_list ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_annotatemore_entry_att_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_annotatemore_entry_att ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_annotatemore_att_value_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_annotatemore_att_value ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_annotatemore_attrib_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_annotatemore_value_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_annotatemore_entry_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_annotatemore_text_code_annotatemore_parse(mailstream * fd, + MMAPString *buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, int * result, + size_t progr_rate, progress_function * progr_fun); + +int mailimap_annotatemore_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/annotatemore_sender.h b/Sources/libetpan/include/annotatemore_sender.h new file mode 100644 index 00000000..aa540784 --- /dev/null +++ b/Sources/libetpan/include/annotatemore_sender.h @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ANNOTATEMORE_SENDER_H + +#define ANNOTATEMORE_SENDER_H + +#include "mailimap_sender.h" +#include "annotatemore_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int mailimap_annotatemore_getannotation_send(mailstream * fd, + const char * list_mb, + struct mailimap_annotatemore_entry_match_list * entries, + struct mailimap_annotatemore_attrib_match_list * attribs); + +int mailimap_annotatemore_setannotation_send(mailstream * fd, + const char * list_mb, + struct mailimap_annotatemore_entry_att_list * en_att); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/annotatemore_types.h b/Sources/libetpan/include/annotatemore_types.h new file mode 100644 index 00000000..aab41c37 --- /dev/null +++ b/Sources/libetpan/include/annotatemore_types.h @@ -0,0 +1,268 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ANNOTATEMORE_TYPES_H + +#define ANNOTATEMORE_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "libetpan-config.h" +#include "mailstream.h" +#include "clist.h" + +/* + ANNOTATEMORE grammar + see [draft-daboo-imap-annotatemore-07] for further information + + annotate-data = "ANNOTATION" SP mailbox SP entry-list + ; empty string for mailbox implies + ; server annotation. + + att-value = attrib SP value + + attrib = string + ; dot-separated attribute name + ; MUST NOT contain "*" or "%" + attrib-match = string + ; dot-separated attribute name + ; MAY contain "*" or "%" for use as wildcards + + attribs = attrib-match / "(" attrib-match *(SP attrib-match) ")" + ; attribute specifiers that can include wildcards + + command-auth /= setannotation / getannotation + ; adds to original IMAP command + + entries = entry-match / "(" entry-match *(SP entry-match) ")" + ; entry specifiers that can include wildcards + + entry = string + ; slash-separated path to entry + ; MUST NOT contain "*" or "%" + + entry-att = entry SP "(" att-value *(SP att-value) ")" + + entry-list = entry-att *(SP entry-att) / + "(" entry *(SP entry) ")" + ; entry attribute-value pairs list for + ; GETANNOTATION response, or + ; parenthesised entry list for unsolicited + ; notification of annotation changes + + entry-match = string + ; slash-separated path to entry + ; MAY contain "*" or "%" for use as wildcards + + getannotation = "GETANNOTATION" SP list-mailbox SP entries SP attribs + ; empty string for list-mailbox implies + ; server annotation. + + response-data /= "*" SP annotate-data CRLF + ; adds to original IMAP data responses + + resp-text-code =/ "ANNOTATEMORE" SP "TOOBIG" / + "ANNOTATEMORE" SP "TOOMANY" + ; new response codes for SETANNOTATION failures + + setannotation = "SETANNOTATION" SP list-mailbox SP setentryatt + ; empty string for list-mailbox implies + ; server annotation. + + setentryatt = entry-att / "(" entry-att *(SP entry-att) ")" + + value = nstring +*/ + +/* + only need to recognize types that can be "embedded" into main + IMAPrev1 types. +*/ +enum { + MAILIMAP_ANNOTATEMORE_TYPE_ANNOTATE_DATA, /* child of response-data */ + MAILIMAP_ANNOTATEMORE_TYPE_RESP_TEXT_CODE /* child of resp-text-code */ +}; + +/* + error codes for annotatemore. +*/ +enum { + MAILIMAP_ANNOTATEMORE_RESP_TEXT_CODE_UNSPECIFIED, /* unspecified response */ + MAILIMAP_ANNOTATEMORE_RESP_TEXT_CODE_TOOBIG, /* annotation too big */ + MAILIMAP_ANNOTATEMORE_RESP_TEXT_CODE_TOOMANY /* too many annotations */ +}; + +void mailimap_annotatemore_attrib_free(char * attrib); + +void mailimap_annotatemore_value_free(char * value); + +void mailimap_annotatemore_entry_free(char * entry); + +struct mailimap_annotatemore_att_value { + char * attrib; + char * value; +}; + +LIBETPAN_EXPORT +struct mailimap_annotatemore_att_value * +mailimap_annotatemore_att_value_new(char * attrib, char * value); + +void mailimap_annotatemore_att_value_free(struct + mailimap_annotatemore_att_value * att_value); + +struct mailimap_annotatemore_entry_att { + char * entry; + clist * att_value_list; + /* list of (struct mailimap_annotatemore_att_value *) */ +}; + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_att * +mailimap_annotatemore_entry_att_new(char * entry, clist * list); + +LIBETPAN_EXPORT +void mailimap_annotatemore_entry_att_free(struct + mailimap_annotatemore_entry_att * en_att); + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_att * +mailimap_annotatemore_entry_att_new_empty(char * entry); + +LIBETPAN_EXPORT +int mailimap_annotatemore_entry_att_add(struct + mailimap_annotatemore_entry_att * en_att, + struct mailimap_annotatemore_att_value * at_value); + +enum { + MAILIMAP_ANNOTATEMORE_ENTRY_LIST_TYPE_ERROR, /* error condition */ + MAILIMAP_ANNOTATEMORE_ENTRY_LIST_TYPE_ENTRY_ATT_LIST, /* entry-att-list */ + MAILIMAP_ANNOTATEMORE_ENTRY_LIST_TYPE_ENTRY_LIST /* entry-list */ +}; + +struct mailimap_annotatemore_entry_list { + int en_list_type; + clist * en_list_data; + /* either a list of (struct annotatemore_entry_att *) + or a list of (char *) */ +}; + +struct mailimap_annotatemore_entry_list * +mailimap_annotatemore_entry_list_new(int type, clist * en_att_list, clist * en_list); + +void mailimap_annotatemore_entry_list_free(struct + mailimap_annotatemore_entry_list * en_list); + +struct mailimap_annotatemore_annotate_data { + char * mailbox; + struct mailimap_annotatemore_entry_list * entry_list; +}; + +struct mailimap_annotatemore_annotate_data * +mailimap_annotatemore_annotate_data_new(char * mb, struct + mailimap_annotatemore_entry_list * en_list); + +LIBETPAN_EXPORT +void mailimap_annotatemore_annotate_data_free(struct + mailimap_annotatemore_annotate_data * an_data); + +struct mailimap_annotatemore_entry_match_list { + clist * entry_match_list; /* list of (char *) */ +}; + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_match_list * +mailimap_annotatemore_entry_match_list_new(clist * en_list); + +LIBETPAN_EXPORT +void mailimap_annotatemore_entry_match_list_free( + struct mailimap_annotatemore_entry_match_list * en_list); + +struct mailimap_annotatemore_attrib_match_list { + clist * attrib_match_list; /* list of (char *) */ +}; + +LIBETPAN_EXPORT +struct mailimap_annotatemore_attrib_match_list * +mailimap_annotatemore_attrib_match_list_new(clist * at_list); + +LIBETPAN_EXPORT +void mailimap_annotatemore_attrib_match_list_free( + struct mailimap_annotatemore_attrib_match_list * at_list); + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_match_list * +mailimap_annotatemore_entry_match_list_new_empty(void); + +LIBETPAN_EXPORT +int mailimap_annotatemore_entry_match_list_add( + struct mailimap_annotatemore_entry_match_list * en_list, + char * entry); + +LIBETPAN_EXPORT +struct mailimap_annotatemore_attrib_match_list * +mailimap_annotatemore_attrib_match_list_new_empty(void); + +LIBETPAN_EXPORT +int mailimap_annotatemore_attrib_match_list_add( + struct mailimap_annotatemore_attrib_match_list * at_list, + char * attrib); + +struct mailimap_annotatemore_entry_att_list { + clist * entry_att_list; /* list of (mailimap_annotatemore_entry_att *) */ +}; + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_att_list * +mailimap_annotatemore_entry_att_list_new(clist * en_list); + +LIBETPAN_EXPORT +void mailimap_annotatemore_entry_att_list_free( + struct mailimap_annotatemore_entry_att_list * en_list); + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_att_list * +mailimap_annotatemore_entry_att_list_new_empty(void); + +LIBETPAN_EXPORT +int mailimap_annotatemore_entry_att_list_add( + struct mailimap_annotatemore_entry_att_list * en_list, + struct mailimap_annotatemore_entry_att * en_att); + +void +mailimap_annotatemore_free(struct mailimap_extension_data * ext_data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/base64.h b/Sources/libetpan/include/base64.h new file mode 100644 index 00000000..61461773 --- /dev/null +++ b/Sources/libetpan/include/base64.h @@ -0,0 +1,65 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - Juergen Graf + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: base64.h,v 1.3 2005/06/01 12:21:57 smarinier Exp $ + */ + +#ifndef BASE64_H +#define BASE64_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef LIBETPAN_CONFIG_H +# include "libetpan-config.h" +#endif + +/** + * creates (malloc) a new base64 encoded string from a standard 8bit string + * don't forget to free it when time comes ;) + */ +LIBETPAN_EXPORT +char * encode_base64(const char * in, int len); + +/** + * creates (malloc) a new standard 8bit string from an base64 encoded string + * don't forget to free it when time comes ;) + */ +LIBETPAN_EXPORT +char * decode_base64(const char * in, int len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/carray.h b/Sources/libetpan/include/carray.h new file mode 100644 index 00000000..9bf5125e --- /dev/null +++ b/Sources/libetpan/include/carray.h @@ -0,0 +1,149 @@ +/* + * libEtPan! -- a mail stuff library + * + * carray - Implements simple dynamic pointer arrays + * + * Copyright (c) 1999-2005, Gaël Roualland + * interface changes - 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: carray.h,v 1.18 2010/11/16 20:46:35 hoa Exp $ + */ + +#ifndef CARRAY_H +#define CARRAY_H + +#ifndef LIBETPAN_CONFIG_H +# include "libetpan-config.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +struct carray_s { + void ** array; + unsigned int len; + unsigned int max; +}; + +typedef struct carray_s carray; + +/* Creates a new array of pointers, with initsize preallocated cells */ +LIBETPAN_EXPORT +carray * carray_new(unsigned int initsize); + +/* Adds the pointer to data in the array. + Returns the index of the pointer in the array or -1 on error */ +LIBETPAN_EXPORT +int carray_add(carray * array, void * data, unsigned int * indx); + +LIBETPAN_EXPORT +int carray_set_size(carray * array, unsigned int new_size); + +/* Removes the cell at this index position. Returns TRUE on success. + Order of elements in the array IS changed. */ +LIBETPAN_EXPORT +int carray_delete(carray * array, unsigned int indx); + +/* Removes the cell at this index position. Returns TRUE on success. + Order of elements in the array IS not changed. */ +LIBETPAN_EXPORT +int carray_delete_slow(carray * array, unsigned int indx); + +/* remove without decreasing the size of the array */ +LIBETPAN_EXPORT +int carray_delete_fast(carray * array, unsigned int indx); + +/* Some of the following routines can be implemented as macros to + be faster. If you don't want it, define NO_MACROS */ +#ifdef NO_MACROS + +/* Returns the array itself */ +LIBETPAN_EXPORT +void ** carray_data(carray *); + +/* Returns the number of elements in the array */ +LIBETPAN_EXPORT +unsigned int carray_count(carray *); + +/* Returns the contents of one cell */ +LIBETPAN_EXPORT +void * carray_get(carray * array, unsigned int indx); + +/* Sets the contents of one cell */ +LIBETPAN_EXPORT +void carray_set(carray * array, unsigned int indx, void * value); + +#else + +#if 0 +#define carray_data(a) (a->array) +#define carray_count(a) (a->len) +#define carray_get(a, indx) (a->array[indx]) +#define carray_set(a, indx, v) do { a->array[indx]=v; } while(0) +#endif + +#ifndef INLINE +#ifdef _MSC_VER +#define INLINE __inline +#else +#define INLINE inline +#endif +#endif + +static INLINE void ** carray_data(carray * array) +{ + return array->array; +} + +static INLINE unsigned int carray_count(carray * array) +{ + return array->len; +} + +static INLINE void * carray_get(carray * array, unsigned int indx) +{ + return array->array[indx]; +} + +static INLINE void carray_set(carray * array, unsigned int indx, void * value) +{ + array->array[indx] = value; +} +#endif + +LIBETPAN_EXPORT +void carray_free(carray * array); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/charconv.h b/Sources/libetpan/include/charconv.h new file mode 100644 index 00000000..b5e5f6d6 --- /dev/null +++ b/Sources/libetpan/include/charconv.h @@ -0,0 +1,84 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: charconv.h,v 1.13 2006/06/16 09:25:23 smarinier Exp $ + */ + +#ifndef CHARCONV_H + +#define CHARCONV_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "sys/types.h" + +#ifndef LIBETPAN_CONFIG_H +# include "libetpan-config.h" +#endif + +enum { + MAIL_CHARCONV_NO_ERROR = 0, + MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET, + MAIL_CHARCONV_ERROR_MEMORY, + MAIL_CHARCONV_ERROR_CONV +}; + +/** +* define your own conversion. +* - result is big enough to contain your converted string +* - result_len contain the maximum size available (out value must contain the final converted size) +* - your conversion return an error code based on upper enum values +*/ +LIBETPAN_EXPORT +extern int (*extended_charconv)(const char * tocode, const char * fromcode, const char * str, size_t length, + char * result, size_t* result_len); + +LIBETPAN_EXPORT +int charconv(const char * tocode, const char * fromcode, + const char * str, size_t length, + char ** result); + +LIBETPAN_EXPORT +int charconv_buffer(const char * tocode, const char * fromcode, + const char * str, size_t length, + char ** result, size_t * result_len); + +LIBETPAN_EXPORT +void charconv_buffer_free(char * str); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/chash.h b/Sources/libetpan/include/chash.h new file mode 100644 index 00000000..8440077d --- /dev/null +++ b/Sources/libetpan/include/chash.h @@ -0,0 +1,191 @@ +/* + * libEtPan! -- a mail stuff library + * + * chash - Implements generic hash tables. + * + * Copyright (c) 1999-2005, Gaël Roualland + * interface changes - 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: chash.h,v 1.16 2010/11/16 20:46:35 hoa Exp $ + */ + +#ifndef CHASH_H +#define CHASH_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef LIBETPAN_CONFIG_H +# include "libetpan-config.h" +#endif + +typedef struct { + void * data; + unsigned int len; +} chashdatum; + +struct chash { + unsigned int size; + unsigned int count; + int copyvalue; + int copykey; + struct chashcell ** cells; +}; + +typedef struct chash chash; + +struct chashcell { + unsigned int func; + chashdatum key; + chashdatum value; + struct chashcell * next; +}; + +typedef struct chashcell chashiter; + +#define CHASH_COPYNONE 0 +#define CHASH_COPYKEY 1 +#define CHASH_COPYVALUE 2 +#define CHASH_COPYALL (CHASH_COPYKEY | CHASH_COPYVALUE) + +#define CHASH_DEFAULTSIZE 13 + +/* Allocates a new (empty) hash using this initial size and the given flags, + specifying which data should be copied in the hash. + CHASH_COPYNONE : Keys/Values are not copied. + CHASH_COPYKEY : Keys are dupped and freed as needed in the hash. + CHASH_COPYVALUE : Values are dupped and freed as needed in the hash. + CHASH_COPYALL : Both keys and values are dupped in the hash. + */ +LIBETPAN_EXPORT +chash * chash_new(unsigned int size, int flags); + +/* Frees a hash */ +LIBETPAN_EXPORT +void chash_free(chash * hash); + +/* Removes all elements from a hash */ +LIBETPAN_EXPORT +void chash_clear(chash * hash); + +/* Adds an entry in the hash table. + Length can be 0 if key/value are strings. + If an entry already exists for this key, it is replaced, and its value + is returned. Otherwise, the data pointer will be NULL and the length + field be set to TRUE or FALSe to indicate success or failure. */ +LIBETPAN_EXPORT +int chash_set(chash * hash, + chashdatum * key, + chashdatum * value, + chashdatum * oldvalue); + +/* Retrieves the data associated to the key if it is found in the hash table. + The data pointer and the length will be NULL if not found*/ +LIBETPAN_EXPORT +int chash_get(chash * hash, + chashdatum * key, chashdatum * result); + +/* Removes the entry associated to this key if it is found in the hash table, + and returns its contents if not dupped (otherwise, pointer will be NULL + and len TRUE). If entry is not found both pointer and len will be NULL. */ +LIBETPAN_EXPORT +int chash_delete(chash * hash, + chashdatum * key, + chashdatum * oldvalue); + +/* Resizes the hash table to the passed size. */ +LIBETPAN_EXPORT +int chash_resize(chash * hash, unsigned int size); + +/* Returns an iterator to the first non-empty entry of the hash table */ +LIBETPAN_EXPORT +chashiter * chash_begin(chash * hash); + +/* Returns the next non-empty entry of the hash table */ +LIBETPAN_EXPORT +chashiter * chash_next(chash * hash, chashiter * iter); + +/* Some of the following routines can be implemented as macros to + be faster. If you don't want it, define NO_MACROS */ +#ifdef NO_MACROS +/* Returns the size of the hash table */ +LIBETPAN_EXPORT +unsigned int chash_size(chash * hash); + +/* Returns the number of entries in the hash table */ +LIBETPAN_EXPORT +unsigned int chash_count(chash * hash); + +/* Returns the key part of the entry pointed by the iterator */ +LIBETPAN_EXPORT +void chash_key(chashiter * iter, chashdatum * result); + +/* Returns the value part of the entry pointed by the iterator */ +LIBETPAN_EXPORT +void chash_value(chashiter * iter, chashdatum * result); + +#else + +#ifndef INLINE +#ifdef _MSC_VER +#define INLINE __inline +#else +#define INLINE inline +#endif +#endif + +static INLINE unsigned int chash_size(chash * hash) +{ + return hash->size; +} + +static INLINE unsigned int chash_count(chash * hash) +{ + return hash->count; +} + +static INLINE void chash_key(chashiter * iter, chashdatum * result) +{ + * result = iter->key; +} + +static INLINE void chash_value(chashiter * iter, chashdatum * result) +{ + * result = iter->value; +} + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/clientid.h b/Sources/libetpan/include/clientid.h new file mode 100644 index 00000000..41e19a9d --- /dev/null +++ b/Sources/libetpan/include/clientid.h @@ -0,0 +1,66 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2018, 2019 - LinuxMagic + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef CLIENTID_H + +#define CLIENTID_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap.h" + +/* + mailimap_clientid() + + This function will perform the clientid command. + + @param session IMAP session + @param type the clientid type + @param clientid the client identifier + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_clientid(mailimap * session, + const char * type, const char * clientid); + +LIBETPAN_EXPORT +int mailimap_has_clientid(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/clientid_sender.h b/Sources/libetpan/include/clientid_sender.h new file mode 100644 index 00000000..d27ef010 --- /dev/null +++ b/Sources/libetpan/include/clientid_sender.h @@ -0,0 +1,49 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2018, 2019 - LinuxMagic + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef CLIENTID_SENDER_H + +#define CLIENTID_SENDER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailstream.h" + +int mailimap_clientid_send(mailstream * fd, + const char * type, const char * clientid); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/clist.h b/Sources/libetpan/include/clist.h new file mode 100644 index 00000000..f6fdf72d --- /dev/null +++ b/Sources/libetpan/include/clist.h @@ -0,0 +1,146 @@ +/* + * libEtPan! -- a mail stuff library + * + * clist - Implements simple generic double-linked pointer lists + * + * Copyright (c) 1999-2005, Gaël Roualland + * interface changes - 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: clist.h,v 1.13 2011/05/09 21:49:46 hoa Exp $ + */ + +#ifndef CLIST_H +#define CLIST_H + +#ifndef LIBETPAN_CONFIG_H +# include "libetpan-config.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clistcell_s { + void * data; + struct clistcell_s * previous; + struct clistcell_s * next; +} clistcell; + +struct clist_s { + clistcell * first; + clistcell * last; + int count; +}; + +typedef struct clist_s clist; +typedef clistcell clistiter; + +/* Allocate a new pointer list */ +LIBETPAN_EXPORT +clist * clist_new(void); + +/* Destroys a list. Data pointed by data pointers is NOT freed. */ +LIBETPAN_EXPORT +void clist_free(clist *); + +/* Some of the following routines can be implemented as macros to + be faster. If you don't want it, define NO_MACROS */ +#ifdef NO_MACROS + +/* Returns TRUE if list is empty */ +int clist_isempty(clist *); + +/* Returns the number of elements in the list */ +int clist_count(clist *); + +/* Returns an iterator to the first element of the list */ +clistiter * clist_begin(clist *); + +/* Returns an iterator to the last element of the list */ +clistiter * clist_end(clist *); + +/* Returns an iterator to the next element of the list */ +clistiter * clist_next(clistiter *); + +/* Returns an iterator to the previous element of the list */ +clistiter * clist_previous(clistiter *); + +/* Returns the data pointer of this element of the list */ +void* clist_content(clistiter *); + +/* Inserts this data pointer at the beginning of the list */ +int clist_prepend(clist *, void *); + +/* Inserts this data pointer at the end of the list */ +int clist_append(clist *, void *); +#else +#define clist_isempty(lst) (((lst)->first==(lst)->last) && ((lst)->last==NULL)) +#define clist_count(lst) ((lst)->count) +#define clist_begin(lst) ((lst)->first) +#define clist_end(lst) ((lst)->last) +#define clist_next(iter) (iter ? (iter)->next : NULL) +#define clist_previous(iter) (iter ? (iter)->previous : NULL) +#define clist_content(iter) (iter ? (iter)->data : NULL) +#define clist_prepend(lst, data) (clist_insert_before(lst, (lst)->first, data)) +#define clist_append(lst, data) (clist_insert_after(lst, (lst)->last, data)) +#endif + +/* Inserts this data pointer before the element pointed by the iterator */ +LIBETPAN_EXPORT +int clist_insert_before(clist *, clistiter *, void *); + +/* Inserts this data pointer after the element pointed by the iterator */ +LIBETPAN_EXPORT +int clist_insert_after(clist *, clistiter *, void *); + +/* Deletes the element pointed by the iterator. + Returns an iterator to the next element. */ +LIBETPAN_EXPORT +clistiter * clist_delete(clist *, clistiter *); + +typedef void (* clist_func)(void *, void *); + +LIBETPAN_EXPORT +void clist_foreach(clist * lst, clist_func func, void * data); + +LIBETPAN_EXPORT +void clist_concat(clist * dest, clist * src); + +LIBETPAN_EXPORT +void * clist_nth_data(clist * lst, int indx); + +LIBETPAN_EXPORT +clistiter * clist_nth(clist * lst, int indx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/condstore.h b/Sources/libetpan/include/condstore.h new file mode 100644 index 00000000..3740dea6 --- /dev/null +++ b/Sources/libetpan/include/condstore.h @@ -0,0 +1,101 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2013 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef CONDSTORE_H + +#define CONDSTORE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "libetpan-config.h" +#include "mailimap_extension.h" +#include "condstore_types.h" + +LIBETPAN_EXPORT +extern struct mailimap_extension_api mailimap_extension_condstore; + +LIBETPAN_EXPORT +int mailimap_store_unchangedsince(mailimap * session, + struct mailimap_set * set, uint64_t mod_sequence_valzer, + struct mailimap_store_att_flags * store_att_flags); + +LIBETPAN_EXPORT +int mailimap_uid_store_unchangedsince(mailimap * session, + struct mailimap_set * set, uint64_t mod_sequence_valzer, + struct mailimap_store_att_flags * store_att_flags); + +LIBETPAN_EXPORT +int mailimap_fetch_changedsince(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, uint64_t mod_sequence_value, + clist ** result); + +LIBETPAN_EXPORT +int mailimap_uid_fetch_changedsince(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, uint64_t mod_sequence_value, + clist ** result); + +LIBETPAN_EXPORT +struct mailimap_fetch_att * mailimap_fetch_att_new_modseq(void); + +LIBETPAN_EXPORT +int mailimap_search_modseq(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result, uint64_t * p_mod_sequence_value); + +LIBETPAN_EXPORT +int mailimap_uid_search_modseq(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result, uint64_t * p_mod_sequence_value); + +LIBETPAN_EXPORT +int mailimap_search_literalplus_modseq(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result, uint64_t * p_mod_sequence_value); + +LIBETPAN_EXPORT +int mailimap_uid_search_literalplus_modseq(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result, uint64_t * p_mod_sequence_value); + +LIBETPAN_EXPORT +int mailimap_select_condstore(mailimap * session, const char * mb, uint64_t * p_mod_sequence_value); + +LIBETPAN_EXPORT +int mailimap_examine_condstore(mailimap * session, const char * mb, uint64_t * p_mod_sequence_value); + +LIBETPAN_EXPORT +int mailimap_has_condstore(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/condstore_private.h b/Sources/libetpan/include/condstore_private.h new file mode 100644 index 00000000..f9240d9a --- /dev/null +++ b/Sources/libetpan/include/condstore_private.h @@ -0,0 +1,50 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2013 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef CONDSTORE_PRIVATE_H + +#define CONDSTORE_PRIVATE_H + +int mailimap_examine_condstore_optional(mailimap * session, const char * mb, + int condstore, uint64_t * p_mod_sequence_value); + +int mailimap_select_condstore_optional(mailimap * session, const char * mb, + int condstore, uint64_t * p_mod_sequence_value); + +int mailimap_store_unchangedsince_optional(mailimap * session, + struct mailimap_set * set, int use_unchangedsince, uint64_t mod_sequence_valzer, + struct mailimap_store_att_flags * store_att_flags); + +int mailimap_uid_store_unchangedsince_optional(mailimap * session, + struct mailimap_set * set, int use_unchangedsince, uint64_t mod_sequence_valzer, + struct mailimap_store_att_flags * store_att_flags); + +#endif diff --git a/Sources/libetpan/include/condstore_types.h b/Sources/libetpan/include/condstore_types.h new file mode 100644 index 00000000..88a5055c --- /dev/null +++ b/Sources/libetpan/include/condstore_types.h @@ -0,0 +1,97 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2013 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef CONDSTORE_TYPE_H + +#define CONDSTORE_TYPE_H + +#include "mailimap_types.h" + +enum { + MAILIMAP_CONDSTORE_TYPE_FETCH_DATA, + MAILIMAP_CONDSTORE_TYPE_RESP_TEXT_CODE, + MAILIMAP_CONDSTORE_TYPE_SEARCH_DATA, + MAILIMAP_CONDSTORE_TYPE_STATUS_INFO +}; + +struct mailimap_condstore_fetch_mod_resp { + uint64_t cs_modseq_value; +}; + +enum { + MAILIMAP_CONDSTORE_RESPTEXTCODE_HIGHESTMODSEQ, + MAILIMAP_CONDSTORE_RESPTEXTCODE_NOMODSEQ, + MAILIMAP_CONDSTORE_RESPTEXTCODE_MODIFIED +}; + +struct mailimap_condstore_resptextcode { + int cs_type; + union { + uint64_t cs_modseq_value; + struct mailimap_set * cs_modified_set; + } cs_data; +}; + +struct mailimap_condstore_search { + clist * cs_search_result; /* uint32_t */ + uint64_t cs_modseq_value; +}; + +struct mailimap_condstore_status_info { + uint64_t cs_highestmodseq_value; +}; + +LIBETPAN_EXPORT +struct mailimap_condstore_fetch_mod_resp * mailimap_condstore_fetch_mod_resp_new(uint64_t cs_modseq_value); + +LIBETPAN_EXPORT +void mailimap_condstore_fetch_mod_resp_free(struct mailimap_condstore_fetch_mod_resp * fetch_data); + +LIBETPAN_EXPORT +struct mailimap_condstore_resptextcode * mailimap_condstore_resptextcode_new(int cs_type, + uint64_t cs_modseq_value, struct mailimap_set * cs_modified_set); + +LIBETPAN_EXPORT +void mailimap_condstore_resptextcode_free(struct mailimap_condstore_resptextcode * resptextcode); + +LIBETPAN_EXPORT +struct mailimap_condstore_search * mailimap_condstore_search_new(clist * cs_search_result, uint64_t cs_modseq_value); + +LIBETPAN_EXPORT +void mailimap_condstore_search_free(struct mailimap_condstore_search * search_data); + +LIBETPAN_EXPORT +struct mailimap_condstore_status_info * mailimap_condstore_status_info_new(uint64_t cs_highestmodseq_value); + +LIBETPAN_EXPORT +void mailimap_condstore_status_info_free(struct mailimap_condstore_status_info * status_info); + +#endif diff --git a/Sources/libetpan/include/config.h b/Sources/libetpan/include/config.h new file mode 100644 index 00000000..1c9233a6 --- /dev/null +++ b/Sources/libetpan/include/config.h @@ -0,0 +1,191 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Check for Linux's /usr/include/features.h + */ +#ifdef _FEATURES_H +# error config.h must be first file included +#endif + +/* Define to detected Berkeley DB major version number */ +#define DBVERS 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_CTYPE_H 1 + +/* Define to use curl */ +//#define HAVE_CURL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to use expat */ +//#define HAVE_EXPAT 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to use getopt_long */ +#define HAVE_GETOPT_LONG 1 + +/* Define to 1 if you have the `getpagesize' function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define if you have the iconv() function. */ +#define HAVE_ICONV 1 + +/* prototype of iconv() has const parameters */ +/* #undef HAVE_ICONV_PROTO_CONST */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to enable IPv6 support. */ +#define HAVE_IPV6 1 + +/* Define to 1 if you have the `lockfile' library (-llockfile). */ +/* #undef HAVE_LIBLOCKFILE */ + +/* Define to 1 if you have the `nsl' library (-lnsl). */ +/* #undef HAVE_LIBNSL */ + +/* Define to 1 if you have the `socket' library (-lsocket). */ +/* #undef HAVE_LIBSOCKET */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Defined if we run on a W32 API based system */ +/* #undef HAVE_MINGW32_SYSTEM */ + +/* Define to 1 if you have a working `mmap' system call. */ +#define HAVE_MMAP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_PTHREAD_H 1 + +/* Define to use setenv */ +#define HAVE_SETENV 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_MMAN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_POLL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_WINSOCK2_H */ + +/* Enable classes using zlib compression. */ +#define HAVE_ZLIB 1 + +/* Define to include multithreading support */ +#define LIBETPAN_REENTRANT 1 + +/* Define this to the version of libEtPan */ +#define LIBETPAN_VERSION "1.9.3" + +/* Define this to the major version of libEtPan */ +#define LIBETPAN_VERSION_MAJOR 1 + +/* Define this to the micro version of libEtPan */ +#define LIBETPAN_VERSION_MICRO 3 + +/* Define this to the minor version of libEtPan */ +#define LIBETPAN_VERSION_MINOR 9 + +/* Enable support for lmdb cache */ +/* #undef LMDB */ + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#define LT_OBJDIR ".libs/" + +/* Name of package */ +#define PACKAGE "libetpan" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "libetpan-devel@lists.sourceforge.net" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "libetpan" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "libetpan 1.9.3" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "libetpan" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.9.3" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to be lazy on protocol syntax */ +#define UNSTRICT_SYNTAX 1 + +/* Define to use GnuTLS */ +/* #undef USE_GNUTLS */ + +/* use poll instead of select */ +/* #undef USE_POLL */ + +/* Define to use SASL */ +/* #define USE_SASL 1 */ + +/* Define to use OpenSSL */ +/* #undef USE_SSL */ + +/* Version number of package */ +#define VERSION "1.9.4" + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif diff --git a/Sources/libetpan/include/connect.h b/Sources/libetpan/include/connect.h new file mode 100644 index 00000000..43f8f923 --- /dev/null +++ b/Sources/libetpan/include/connect.h @@ -0,0 +1,62 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: connect.h,v 1.16 2007/06/30 12:58:21 hoa Exp $ + */ + +#ifndef CONNECT_H + +#define CONNECT_H + +#ifdef HAVE_INTTYPES_H +# include +#endif +#include + +#ifdef __cplusplus +extern "C" { +#endif + +uint16_t mail_get_service_port(const char * name, char * protocol); +int mail_tcp_connect(const char * server, uint16_t port); +int mail_tcp_connect_timeout(const char * server, uint16_t port, time_t timeout); +int mail_tcp_connect_with_local_address(const char * server, uint16_t port, + const char * local_address, uint16_t local_port); +int mail_tcp_connect_with_local_address_timeout(const char * server, uint16_t port, + const char * local_address, uint16_t local_port, time_t timeout); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Sources/libetpan/include/data_message_driver.h b/Sources/libetpan/include/data_message_driver.h new file mode 100644 index 00000000..1d8cd177 --- /dev/null +++ b/Sources/libetpan/include/data_message_driver.h @@ -0,0 +1,60 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: data_message_driver.h,v 1.5 2007/12/10 21:32:58 hoa Exp $ + */ + +#ifndef DATA_MESSAGE_DRIVER_H + +#define DATA_MESSAGE_DRIVER_H + +#include "mailmessage.h" + +#define LIBETPAN_DATA_MESSAGE + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * data_message_driver; + +LIBETPAN_EXPORT +mailmessage * data_message_init(char * data, size_t len); + +LIBETPAN_EXPORT +void data_message_detach_mime(mailmessage * msg); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/date.h b/Sources/libetpan/include/date.h new file mode 100644 index 00000000..a3244bfc --- /dev/null +++ b/Sources/libetpan/include/date.h @@ -0,0 +1,38 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef DATE_H +#define DATE_H + +#include + +time_t newsfeed_iso8601_date_parse(char *date); + +#endif /* __DATE_H */ diff --git a/Sources/libetpan/include/dbdriver.h b/Sources/libetpan/include/dbdriver.h new file mode 100644 index 00000000..6067f692 --- /dev/null +++ b/Sources/libetpan/include/dbdriver.h @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: dbdriver.h,v 1.2 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef DBDRIVER_H + +#define DBDRIVER_H + +#include "dbdriver_message.h" +#include "dbdriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * db_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/dbdriver_message.h b/Sources/libetpan/include/dbdriver_message.h new file mode 100644 index 00000000..2b668b32 --- /dev/null +++ b/Sources/libetpan/include/dbdriver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: dbdriver_message.h,v 1.2 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef DBDRIVER_MESSAGE_H + +#define DBDRIVER_MESSAGE_H + +#include "dbdriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * db_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/dbdriver_types.h b/Sources/libetpan/include/dbdriver_types.h new file mode 100644 index 00000000..d5eb28a6 --- /dev/null +++ b/Sources/libetpan/include/dbdriver_types.h @@ -0,0 +1,71 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: dbdriver_types.h,v 1.2 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef DBDRIVER_TYPES_H + +#define DBDRIVER_TYPES_H + +#include "libetpan-config.h" + +#include "maildriver_types.h" +#include "generic_cache_types.h" +#include "mailstorage_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct db_session_state_data { + char db_filename[PATH_MAX]; + struct mail_flags_store * db_flags_store; +}; + +/* db storage */ + +/* + db_mailstorage is the state data specific to the db storage. + + - pathname is the path of the db storage. +*/ + +struct db_mailstorage { + char * db_pathname; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/dbstorage.h b/Sources/libetpan/include/dbstorage.h new file mode 100644 index 00000000..af96c6cd --- /dev/null +++ b/Sources/libetpan/include/dbstorage.h @@ -0,0 +1,62 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: dbstorage.h,v 1.3 2005/06/01 12:21:57 smarinier Exp $ + */ + +#ifndef DBSTORAGE_H + +#define DBSTORAGE_H + +#include "dbdriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + db_mailstorage_init is the constructor for a DB storage. + + @param storage this is the storage to initialize. + + @param pathname is the directory that contains the mailbox. +*/ + +LIBETPAN_EXPORT +int db_mailstorage_init(struct mailstorage * storage, + char * db_pathname); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/enable.h b/Sources/libetpan/include/enable.h new file mode 100644 index 00000000..9c955e3d --- /dev/null +++ b/Sources/libetpan/include/enable.h @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2011 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ENABLE_H + +#define ENABLE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_extension.h" + +LIBETPAN_EXPORT +extern struct mailimap_extension_api mailimap_extension_enable; + +LIBETPAN_EXPORT +int mailimap_enable(mailimap * session, struct mailimap_capability_data * capabilities, + struct mailimap_capability_data ** result); + +LIBETPAN_EXPORT +int mailimap_has_enable(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/feeddriver.h b/Sources/libetpan/include/feeddriver.h new file mode 100644 index 00000000..216cc0b9 --- /dev/null +++ b/Sources/libetpan/include/feeddriver.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: feeddriver.h,v 1.1 2007/01/18 09:15:01 hoa Exp $ + */ + +#ifndef FEEDDRIVER_H + +#define FEEDDRIVER_H + +#include "feeddriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * feed_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/feeddriver_message.h b/Sources/libetpan/include/feeddriver_message.h new file mode 100644 index 00000000..f9caad03 --- /dev/null +++ b/Sources/libetpan/include/feeddriver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: feeddriver_message.h,v 1.1 2007/01/18 09:15:01 hoa Exp $ + */ + +#ifndef FEEDDRIVER_MESSAGE_H + +#define FEEDDRIVER_MESSAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "feeddriver_types.h" + +extern mailmessage_driver * feed_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/feeddriver_types.h b/Sources/libetpan/include/feeddriver_types.h new file mode 100644 index 00000000..b5684b5a --- /dev/null +++ b/Sources/libetpan/include/feeddriver_types.h @@ -0,0 +1,68 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: feeddriver_types.h,v 1.1 2007/01/18 09:15:01 hoa Exp $ + */ + +#ifndef FEEDDRIVER_TYPES_H + +#define FEEDDRIVER_TYPES_H + +#include "libetpan-config.h" + +#include "maildriver_types.h" +#include "mailstorage_types.h" +#include "newsfeed.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct feed_session_state_data { + time_t feed_last_update; + struct newsfeed * feed_session; + int feed_error; +}; + +struct feed_mailstorage { + char * feed_url; + + int feed_cached; + char * feed_cache_directory; + char * feed_flags_directory; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/feedstorage.h b/Sources/libetpan/include/feedstorage.h new file mode 100644 index 00000000..d447b337 --- /dev/null +++ b/Sources/libetpan/include/feedstorage.h @@ -0,0 +1,72 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: feedstorage.h,v 1.1 2007/01/18 09:15:01 hoa Exp $ + */ + +#ifndef FEEDSTORAGE_H + +#define FEEDSTORAGE_H + +#include "feeddriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + feed_mailstorage_init is the constructor for a FEED storage + + @param storage this is the storage to initialize. + + @param feed_url this is the URL of the feed. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache + + @param flags_directory is the location of the flags +*/ + +LIBETPAN_EXPORT +int feed_mailstorage_init(struct mailstorage * storage, + const char * feed_url, + int feed_cached, const char * feed_cache_directory, + const char * feed_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/generic_cache.h b/Sources/libetpan/include/generic_cache.h new file mode 100644 index 00000000..b5858aa2 --- /dev/null +++ b/Sources/libetpan/include/generic_cache.h @@ -0,0 +1,109 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: generic_cache.h,v 1.18 2008/02/20 22:15:51 hoa Exp $ + */ + +#ifndef GENERIC_CACHE_H + +#define GENERIC_CACHE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "generic_cache_types.h" +#include "mailmessage_types.h" +#include "chash.h" +#include "carray.h" +#include "mail_cache_db_types.h" + +int generic_cache_create_dir(char * dirname); + +int generic_cache_store(char * filename, char * content, size_t length); +int generic_cache_read(char * filename, char ** result, size_t * result_len); + +int generic_cache_fields_read(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mailimf_fields ** result); + +int generic_cache_fields_write(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mailimf_fields * fields); + +int generic_cache_flags_read(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mail_flags ** result); + +int generic_cache_flags_write(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mail_flags * flags); + +int generic_cache_delete(struct mail_cache_db * cache_db, char * keyname); + +#if 0 +int generic_cache_fields_read(DB * dbp, MMAPString * mmapstr, + char * keyname, struct mailimf_fields ** result); + +int generic_cache_fields_write(DB * dbp, MMAPString * mmapstr, + char * keyname, struct mailimf_fields * fields); + +int generic_cache_flags_read(DB * dbp, MMAPString * mmapstr, + char * keyname, struct mail_flags ** result); + +int generic_cache_flags_write(DB * dbp, MMAPString * mmapstr, + char * keyname, struct mail_flags * flags); + +int generic_cache_delete(DB * dbp, char * keyname); +#endif + +struct mail_flags_store * mail_flags_store_new(void); + +void mail_flags_store_clear(struct mail_flags_store * flags_store); + +void mail_flags_store_free(struct mail_flags_store * flags_store); + +int mail_flags_store_set(struct mail_flags_store * flags_store, + mailmessage * msg); + +void mail_flags_store_sort(struct mail_flags_store * flags_store); + +struct mail_flags * +mail_flags_store_get(struct mail_flags_store * flags_store, uint32_t indx); + +int mail_flags_compare(struct mail_flags * flags1, struct mail_flags * flags2); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/generic_cache_types.h b/Sources/libetpan/include/generic_cache_types.h new file mode 100644 index 00000000..e32f9fec --- /dev/null +++ b/Sources/libetpan/include/generic_cache_types.h @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: generic_cache_types.h,v 1.6 2004/11/21 21:53:35 hoa Exp $ + */ + +#ifndef GENERIC_CACHE_TYPE_H + +#define GENERIC_CACHE_TYPE_H + +#include "carray.h" +#include "chash.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct mail_flags_store { + carray * fls_tab; + chash * fls_hash; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/hotmailstorage.h b/Sources/libetpan/include/hotmailstorage.h new file mode 100644 index 00000000..d61614fb --- /dev/null +++ b/Sources/libetpan/include/hotmailstorage.h @@ -0,0 +1,57 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: hotmailstorage.h,v 1.3 2005/06/01 12:21:58 smarinier Exp $ + */ + +#ifndef HOTMAILSTORAGE_H + +#define HOTMAILSTORAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailstorage_types.h" + +LIBETPAN_EXPORT +int hotmail_mailstorage_init(struct mailstorage * storage, + char * hotmail_login, char * hotmail_password, + int hotmail_cached, char * hotmail_cache_directory, + char * hotmail_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Sources/libetpan/include/idle.h b/Sources/libetpan/include/idle.h new file mode 100644 index 00000000..93d6d704 --- /dev/null +++ b/Sources/libetpan/include/idle.h @@ -0,0 +1,64 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILIMAP_IDLE_H + +#define MAILIMAP_IDLE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_types.h" + +LIBETPAN_EXPORT +int mailimap_idle(mailimap * session); + +LIBETPAN_EXPORT +int mailimap_idle_done(mailimap * session); + +LIBETPAN_EXPORT +int mailimap_idle_get_fd(mailimap * session); + +/* delay in seconds */ +LIBETPAN_EXPORT +void mailimap_idle_set_delay(mailimap * session, long delay); + +LIBETPAN_EXPORT +long mailimap_idle_get_done_delay(mailimap * session); + +LIBETPAN_EXPORT +int mailimap_has_idle(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/imapdriver.h b/Sources/libetpan/include/imapdriver.h new file mode 100644 index 00000000..5350b032 --- /dev/null +++ b/Sources/libetpan/include/imapdriver.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver.h,v 1.12 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef IMAPDRIVER_H + +#define IMAPDRIVER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "imapdriver_types.h" + +extern mailsession_driver * imap_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/imapdriver_cached.h b/Sources/libetpan/include/imapdriver_cached.h new file mode 100644 index 00000000..5a75b1f4 --- /dev/null +++ b/Sources/libetpan/include/imapdriver_cached.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver_cached.h,v 1.11 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef IMAPDRIVER_CACHED_H + +#define IMAPDRIVER_CACHED_H + +#include "imapdriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * imap_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/imapdriver_cached_message.h b/Sources/libetpan/include/imapdriver_cached_message.h new file mode 100644 index 00000000..2d8eaee4 --- /dev/null +++ b/Sources/libetpan/include/imapdriver_cached_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver_cached_message.h,v 1.6 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef IMAPDRIVER_CACHED_MESSAGE_H + +#define IMAPDRIVER_CACHED_MESSAGE_H + +#include "imapdriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * imap_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/imapdriver_message.h b/Sources/libetpan/include/imapdriver_message.h new file mode 100644 index 00000000..e2fd4f44 --- /dev/null +++ b/Sources/libetpan/include/imapdriver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver_message.h,v 1.6 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef IMAPDRIVER_MESSAGE_H + +#define IMAPDRIVER_MESSAGE_H + +#include "imapdriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * imap_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/imapdriver_tools.h b/Sources/libetpan/include/imapdriver_tools.h new file mode 100644 index 00000000..36dc4861 --- /dev/null +++ b/Sources/libetpan/include/imapdriver_tools.h @@ -0,0 +1,88 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver_tools.h,v 1.9 2007/08/08 21:33:30 hoa Exp $ + */ + +#ifndef IMAPDRIVER_TOOLS_H + +#define IMAPDRIVER_TOOLS_H + +#include "mailimap.h" +#include "mailmime.h" +#include "imapdriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int imap_list_to_list(clist * imap_list, struct mail_list ** result); + +int +imap_section_to_imap_section(struct mailmime_section * section, int type, + struct mailimap_section ** result); + +int imap_get_msg_att_info(struct mailimap_msg_att * msg_att, + uint32_t * puid, + struct mailimap_envelope ** pimap_envelope, + char ** preferences, + size_t * pref_size, + struct mailimap_msg_att_dynamic ** patt_dyn, + struct mailimap_body ** pimap_body); + +int imap_add_envelope_fetch_att(struct mailimap_fetch_type * fetch_type); + +int imap_env_to_fields(struct mailimap_envelope * env, + char * ref_str, size_t ref_size, + struct mailimf_fields ** result); + +int +imap_fetch_result_to_envelop_list(clist * fetch_result, + struct mailmessage_list * env_list); + +int imap_body_to_body(struct mailimap_body * imap_body, + struct mailmime ** result); + +int imap_msg_list_to_imap_set(clist * msg_list, + struct mailimap_set ** result); + +int imap_flags_to_imap_flags(struct mail_flags * flags, + struct mailimap_flag_list ** result); + +int imap_flags_to_flags(struct mailimap_msg_att_dynamic * att_dyn, + struct mail_flags ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/imapdriver_tools_private.h b/Sources/libetpan/include/imapdriver_tools_private.h new file mode 100644 index 00000000..0de33cff --- /dev/null +++ b/Sources/libetpan/include/imapdriver_tools_private.h @@ -0,0 +1,62 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef IMAPDRIVER_TOOLS_PRIVATE_H + +#define IMAPDRIVER_TOOLS_PRIVATE_H + +#include "mail_cache_db.h" + +int +imapdriver_get_cached_envelope(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, mailmessage * msg, + struct mailimf_fields ** result); + +int +imapdriver_write_cached_envelope(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, mailmessage * msg, + struct mailimf_fields * fields); + +int imap_error_to_mail_error(int error); + +int imap_store_flags(mailimap * imap, uint32_t first, uint32_t last, + struct mail_flags * flags); + +int imap_fetch_flags(mailimap * imap, + uint32_t indx, struct mail_flags ** result); + +int imap_get_messages_list(mailimap * imap, + mailsession * session, mailmessage_driver * driver, + uint32_t first_index, + struct mailmessage_list ** result); + +#endif diff --git a/Sources/libetpan/include/imapdriver_types.h b/Sources/libetpan/include/imapdriver_types.h new file mode 100644 index 00000000..77a68efc --- /dev/null +++ b/Sources/libetpan/include/imapdriver_types.h @@ -0,0 +1,165 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver_types.h,v 1.27 2007/06/30 12:58:21 hoa Exp $ + */ + +#ifndef IMAPDRIVER_TYPES_H + +#define IMAPDRIVER_TYPES_H + +#include "libetpan-config.h" + +#include "mailimap.h" +#include "maildriver_types.h" +#include "generic_cache_types.h" +#include "mailstorage_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* IMAP driver for session */ + +struct imap_session_state_data { + mailimap * imap_session; + char * imap_mailbox; + struct mail_flags_store * imap_flags_store; + void (* imap_ssl_callback)(struct mailstream_ssl_context * ssl_context, void * data); + void * imap_ssl_cb_data; +}; + +enum { + IMAP_SECTION_MESSAGE, + IMAP_SECTION_HEADER, + IMAP_SECTION_MIME, + IMAP_SECTION_BODY +}; + +/* cached IMAP driver for session */ + +enum { + IMAPDRIVER_CACHED_SET_SSL_CALLBACK = 1, + IMAPDRIVER_CACHED_SET_SSL_CALLBACK_DATA = 2, + /* cache */ + IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY = 1001 +}; + +struct imap_cached_session_state_data { + mailsession * imap_ancestor; + char * imap_quoted_mb; + char imap_cache_directory[PATH_MAX]; + carray * imap_uid_list; + uint32_t imap_uidvalidity; +}; + + +/* IMAP storage */ + +/* + imap_mailstorage is the state data specific to the IMAP4rev1 storage. + + - servername this is the name of the IMAP4rev1 server + + - port is the port to connect to, on the server. + you give 0 to use the default port. + + - command, if non-NULL the command used to connect to the + server instead of allowing normal TCP connections to be used. + + - connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS, + CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS or + CONNECTION_TYPE_COMMAND. + + - auth_type is the authenticate mechanism to use. + The value can be IMAP_AUTH_TYPE_PLAIN. + Other values are not yet implemented. + + - login is the login of the IMAP4rev1 account. + + - password is the password of the IMAP4rev1 account. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache +*/ + +struct imap_mailstorage { + char * imap_servername; + uint16_t imap_port; + char * imap_command; + int imap_connection_type; + + int imap_auth_type; + char * imap_login; /* deprecated */ + char * imap_password; /* deprecated */ + + int imap_cached; + char * imap_cache_directory; + + struct { + int sasl_enabled; + char * sasl_auth_type; + char * sasl_server_fqdn; + char * sasl_local_ip_port; + char * sasl_remote_ip_port; + char * sasl_login; + char * sasl_auth_name; + char * sasl_password; + char * sasl_realm; + } imap_sasl; + + char * imap_local_address; + uint16_t imap_local_port; +}; + +/* this is the type of IMAP4rev1 authentication */ + +enum { + IMAP_AUTH_TYPE_PLAIN, /* plain text authentication */ + IMAP_AUTH_TYPE_SASL_ANONYMOUS, /* SASL anonymous */ + IMAP_AUTH_TYPE_SASL_CRAM_MD5, /* SASL CRAM MD5 */ + IMAP_AUTH_TYPE_SASL_KERBEROS_V4, /* SASL KERBEROS V4 */ + IMAP_AUTH_TYPE_SASL_PLAIN, /* SASL plain */ + IMAP_AUTH_TYPE_SASL_SCRAM_MD5, /* SASL SCRAM MD5 */ + IMAP_AUTH_TYPE_SASL_GSSAPI, /* SASL GSSAPI */ + IMAP_AUTH_TYPE_SASL_DIGEST_MD5 /* SASL digest MD5 */ +}; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/imapstorage.h b/Sources/libetpan/include/imapstorage.h new file mode 100644 index 00000000..d8d98376 --- /dev/null +++ b/Sources/libetpan/include/imapstorage.h @@ -0,0 +1,120 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapstorage.h,v 1.13 2007/06/30 12:58:21 hoa Exp $ + */ + +#ifndef IMAPSTORAGE_H + +#define IMAPSTORAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "imapdriver_types.h" + +/* + imap_mailstorage_init is the constructor for a IMAP4rev1 storage + + @param storage this is the storage to initialize. + + @param servername this is the name of the IMAP4rev1 server + + @param port is the port to connect to, on the server. + you give 0 to use the default port. + + @param command the command used to connect to the server instead of + allowing normal TCP connections to be used. + + @param connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS, + CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS, + CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS, + CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,. + + @param auth_type is the authenticate mechanism to use. + The value can be IMAP_AUTH_TYPE_PLAIN. + Other values are not yet implemented. + + @param login is the login of the IMAP4rev1 account. + + @param password is the password of the IMAP4rev1 account. + If performing OAuth2 login, use the OAuth2 token here + instead of password. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache +*/ + +LIBETPAN_EXPORT +int imap_mailstorage_init(struct mailstorage * storage, + const char * imap_servername, uint16_t imap_port, + const char * imap_command, + int imap_connection_type, int imap_auth_type, + const char * imap_login, const char * imap_password, + int imap_cached, const char * imap_cache_directory); + +LIBETPAN_EXPORT +int imap_mailstorage_init_sasl(struct mailstorage * storage, + const char * imap_servername, uint16_t imap_port, + const char * imap_command, + int imap_connection_type, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm, + int imap_cached, const char * imap_cache_directory); + +LIBETPAN_EXPORT +int imap_mailstorage_init_sasl_with_local_address(struct mailstorage * storage, + const char * imap_servername, uint16_t imap_port, + const char * imap_local_address, uint16_t imap_local_port, + const char * imap_command, + int imap_connection_type, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm, + int imap_cached, const char * imap_cache_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/imfcache.h b/Sources/libetpan/include/imfcache.h new file mode 100644 index 00000000..8122822f --- /dev/null +++ b/Sources/libetpan/include/imfcache.h @@ -0,0 +1,75 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imfcache.h,v 1.10 2008/02/20 22:15:51 hoa Exp $ + */ + +#ifndef IMFCACHE_H + +#define IMFCACHE_H + +#include +#include "mailimf.h" +#include "maildriver_types.h" +#include "mmapstring.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int mail_serialize_clear(MMAPString * mmapstr, size_t * indx); + +int mail_serialize_write(MMAPString * mmapstr, size_t * indx, + char * buf, size_t size); + +int mail_serialize_read(MMAPString * mmapstr, size_t * indx, + char * buf, size_t size); + +int mailimf_cache_int_write(MMAPString * mmapstr, size_t * indx, + uint32_t value); +int mailimf_cache_string_write(MMAPString * mmapstr, size_t * indx, + char * str, size_t length); +int mailimf_cache_int_read(MMAPString * mmapstr, size_t * indx, + uint32_t * result); +int mailimf_cache_string_read(MMAPString * mmapstr, size_t * indx, + char ** result); + +int mailimf_cache_fields_write(MMAPString * mmapstr, size_t * indx, + struct mailimf_fields * fields); +int mailimf_cache_fields_read(MMAPString * mmapstr, size_t * indx, + struct mailimf_fields ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/libetpan-config.h b/Sources/libetpan/include/libetpan-config.h new file mode 100644 index 00000000..8ca9f8b7 --- /dev/null +++ b/Sources/libetpan/include/libetpan-config.h @@ -0,0 +1,26 @@ +#ifndef LIBETPAN_CONFIG_H +#define LIBETPAN_CONFIG_H +#if WIN32 +# define MMAP_UNAVAILABLE +#endif +#if defined(_MSC_VER) && !defined(__cplusplus) +# define inline __inline +#endif +#include "limits.h" +#ifndef PATH_MAX +#define PATH_MAX 4096 +#endif +#include "sys/param.h" +#include "inttypes.h" +#define MAIL_DIR_SEPARATOR '/' +#define MAIL_DIR_SEPARATOR_S "/" +#ifdef _MSC_VER +# ifdef LIBETPAN_DLL +# define LIBETPAN_EXPORT __declspec(dllexport) +# else +# define LIBETPAN_EXPORT __declspec(dllimport) +# endif +#else +# define LIBETPAN_EXPORT +#endif +#endif diff --git a/Sources/libetpan/include/libetpan.h b/Sources/libetpan/include/libetpan.h new file mode 100644 index 00000000..e557efc1 --- /dev/null +++ b/Sources/libetpan/include/libetpan.h @@ -0,0 +1,189 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: libetpan.h,v 1.17 2007/01/18 09:15:02 hoa Exp $ + */ + +#ifndef LIBETPAN_H + +#define LIBETPAN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "libetpan_version.h" +#include "maildriver.h" +#include "mailmessage.h" +#include "mailfolder.h" +#include "mailstorage.h" +#include "mailthread.h" +#include "mailsmtp.h" +#include "charconv.h" +#include "mailsem.h" +#include "carray.h" +#include "chash.h" +#include "maillock.h" + +/* mbox driver */ +#include "mboxdriver.h" +#include "mboxdriver_message.h" +#include "mboxdriver_cached.h" +#include "mboxdriver_cached_message.h" +#include "mboxstorage.h" + +/* MH driver */ +#include "mhdriver.h" +#include "mhdriver_message.h" +#include "mhdriver_cached.h" +#include "mhdriver_cached_message.h" +#include "mhstorage.h" + +/* IMAP4rev1 driver */ +#include "imapdriver.h" +#include "imapdriver_message.h" +#include "imapdriver_cached.h" +#include "imapdriver_cached_message.h" +#include "imapstorage.h" + +/* POP3 driver */ +#include "pop3driver.h" +#include "pop3driver_message.h" +#include "pop3driver_cached.h" +#include "pop3driver_cached_message.h" +#include "pop3storage.h" + +/* Hotmail */ +#include "hotmailstorage.h" + +/* NNTP driver */ +#include "nntpdriver.h" +#include "nntpdriver_message.h" +#include "nntpdriver_cached.h" +#include "nntpdriver_cached_message.h" +#include "nntpstorage.h" + +/* maildir driver */ +#include "maildirdriver.h" +#include "maildirdriver_message.h" +#include "maildirdriver_cached.h" +#include "maildirdriver_cached_message.h" +#include "maildirstorage.h" + +/* db driver */ +#include "dbdriver.h" +#include "dbdriver_message.h" +#include "dbstorage.h" + +/* feed driver */ +#include "feeddriver.h" +#include "feeddriver_message.h" +#include "feedstorage.h" + +/* message which content is given by a MIME structure */ +#include "mime_message_driver.h" + +/* message which content given by a string */ +#include "data_message_driver.h" + +/* engine */ +#include "mailprivacy.h" +#include "mailengine.h" +#include "mailprivacy_gnupg.h" +#include "mailprivacy_smime.h" + +/* utils */ +#include "mailimap_parser.h" + +/* other */ +#include "quota_sender.h" +#include "mailprivacy_tools_private.h" +#include "maildriver_tools.h" +#include "mailmessage_tools.h" +#include "mailstream_cancel.h" +#include "parser_atom10.h" +#include "quota_parser.h" +#include "mailimap_sender.h" +#include "parser_rdf.h" +#include "base64.h" +#include "config.h" +#include "mailimap_id_sender.h" +#include "parser.h" +#include "mailimap_keywords.h" +#include "md5.h" +#include "mmapstring_private.h" +#include "parser_atom03.h" +#include "mailstream_ssl_private.h" +#include "connect.h" +#include "date.h" +#include "mailimap_id_parser.h" +#include "mailsasl_private.h" +#include "mailmime_write.h" +#include "imfcache.h" +#include "timeutils.h" +#include "namespace_parser.h" +#include "mailsasl.h" +#include "mailsmtp_private.h" +#include "mail_cache_db.h" +#include "mail.h" +#include "md5global.h" +#include "parser_rss20.h" +#include "annotatemore_parser.h" +#include "generic_cache.h" +#include "namespace_sender.h" +#include "annotatemore_sender.h" +#include "md5namespace.h" +#include "mailimf_write.h" +#include "condstore_private.h" +#include "uidplus_parser.h" +#include "clientid.h" +#include "mailstream_cancel_types.h" +#include "acl_parser.h" +#include "imapdriver_tools_private.h" +#include "clientid_sender.h" +#include "imapdriver_tools.h" +#include "mail_cache_db_types.h" +#include "acl_sender.h" +#include "maildirdriver_tools.h" +#include "uidplus_sender.h" +#include "qresync_private.h" +#include "mailstream_compress.h" +#include "mailmbox_parse.h" +#include "mailstorage_tools.h" +#include "newsfeed_private.h" +#include "mailimap_print.h" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/libetpan_version.h b/Sources/libetpan/include/libetpan_version.h new file mode 100644 index 00000000..7e9406ca --- /dev/null +++ b/Sources/libetpan/include/libetpan_version.h @@ -0,0 +1,66 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001 - 2003 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LIBETPAN_VERSION_H + +#define LIBETPAN_VERSION_H + +#ifndef LIBETPAN_VERSION_MAJOR +#define LIBETPAN_VERSION_MAJOR 1 +#endif + +#ifndef LIBETPAN_VERSION_MINOR +#define LIBETPAN_VERSION_MINOR 9 +#endif + +#ifndef LIBETPAN_REENTRANT +#if 1 +#define LIBETPAN_REENTRANT 1 +#endif + +#ifndef LIBETPAN_API_CURRENT +#define LIBETPAN_API_CURRENT 24 +#endif + +#ifndef LIBETPAN_API_REVISION +#define LIBETPAN_API_REVISION 0 +#endif + +#ifndef LIBETPAN_API_COMPATIBILITY +#define LIBETPAN_API_COMPATIBILITY 20 +#endif + +#endif + +int libetpan_get_version_major(void); +int libetpan_get_version_minor(void); + +#endif diff --git a/Sources/libetpan/include/mail.h b/Sources/libetpan/include/mail.h new file mode 100644 index 00000000..ed4f5b0a --- /dev/null +++ b/Sources/libetpan/include/mail.h @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mail.h,v 1.8 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef MAIL_H + +#define MAIL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mail_cache_db.h b/Sources/libetpan/include/mail_cache_db.h new file mode 100644 index 00000000..ec8a9fa3 --- /dev/null +++ b/Sources/libetpan/include/mail_cache_db.h @@ -0,0 +1,158 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mail_cache_db.h,v 1.6 2005/04/07 00:05:25 hoa Exp $ + */ + +#ifndef MAIL_CACHE_DB_H + +#define MAIL_CACHE_DB_H + +#include +#include "mail_cache_db_types.h" +#include "chash.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + this module will handle a database "f(key) -> value" in a file + + berkeley DB or other can be used for implementation of low-level file. +*/ + +/* + mail_cache_db_open() + + This function opens the file "filename". + The pointer return in pcache_db should be used for further references + to the database. +*/ + +int mail_cache_db_open(const char * filename, + struct mail_cache_db ** pcache_db); + +/* + mail_cache_db_close() + + This function closes the opened database. + The pointer cannot be used later. +*/ + +void mail_cache_db_close(struct mail_cache_db * cache_db); + +/* + mail_cache_db_open_lock() + + This function opens and locks the file "filename". + The pointer return in pcache_db should be used for further references + to the database. +*/ + +int mail_cache_db_open_lock(const char * filename, + struct mail_cache_db ** pcache_db); + +/* + mail_cache_db_open_unlock() + + This function closes and unlocks the opened database. + The pointer cannot be used later. +*/ + +void mail_cache_db_close_unlock(const char * filename, + struct mail_cache_db * cache_db); + +/* + mail_cache_db_put() + + This function will store a given key and value in the database. +*/ + +int mail_cache_db_put(struct mail_cache_db * cache_db, + const void * key, size_t key_len, const void * value, size_t value_len); + +/* + mail_cache_db_get() + + This function will retrieve the value corresponding to a given key + from the database. +*/ + +int mail_cache_db_get(struct mail_cache_db * cache_db, + const void * key, size_t key_len, void ** pvalue, size_t * pvalue_len); + +/* + mail_cache_db_get_size() + + This function will retrieve the size of the value corresponding + to a given key from the database. +*/ + +int mail_cache_db_get_size(struct mail_cache_db * cache_db, + const void * key, size_t key_len, size_t * pvalue_len); + +/* + mail_cache_db_del() + + This function will delete the given key and the corresponding value + from the database. +*/ + +int mail_cache_db_del(struct mail_cache_db * cache_db, + const void * key, size_t key_len); + +/* + mail_cache_clean_up() + + This function will delete the key all the key/value pairs of the + database file which key does not exist in the given hash. +*/ + +int mail_cache_db_clean_up(struct mail_cache_db * cache_db, + chash * exist); + +/* + mail_cache_db_get_keys() + + This function will get all keys of the database and will + store them to the given chash. +*/ + +int mail_cache_db_get_keys(struct mail_cache_db * cache_db, + chash * keys); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mail_cache_db_types.h b/Sources/libetpan/include/mail_cache_db_types.h new file mode 100644 index 00000000..7ebc1e45 --- /dev/null +++ b/Sources/libetpan/include/mail_cache_db_types.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mail_cache_db_types.h,v 1.2 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef MAIL_CACHE_DB_TYPES_H + +#define MAIL_CACHE_DB_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct mail_cache_db { + void * internal_database; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/maildir.h b/Sources/libetpan/include/maildir.h new file mode 100644 index 00000000..234c7f3c --- /dev/null +++ b/Sources/libetpan/include/maildir.h @@ -0,0 +1,67 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildir.h,v 1.5 2004/11/21 21:53:38 hoa Exp $ + */ + +#ifndef MAILDIR_H + +#define MAILDIR_H + +#include "maildir_types.h" + +struct maildir * maildir_new(const char * path); + +void maildir_free(struct maildir * md); + +int maildir_update(struct maildir * md); + +int maildir_message_add_uid(struct maildir * md, + const char * message, size_t size, + char * uid, size_t max_uid_len); + +int maildir_message_add(struct maildir * md, + const char * message, size_t size); + +int maildir_message_add_file_uid(struct maildir * md, int fd, + char * uid, size_t max_uid_len); + +int maildir_message_add_file(struct maildir * md, int fd); + +char * maildir_message_get(struct maildir * md, const char * uid); + +int maildir_message_remove(struct maildir * md, const char * uid); + +int maildir_message_change_flags(struct maildir * md, + const char * uid, int new_flags); + +#endif diff --git a/Sources/libetpan/include/maildir_types.h b/Sources/libetpan/include/maildir_types.h new file mode 100644 index 00000000..3086d76c --- /dev/null +++ b/Sources/libetpan/include/maildir_types.h @@ -0,0 +1,93 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildir_types.h,v 1.9 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifndef MAILDIR_TYPES_H + +#define MAILDIR_TYPES_H + +#include "sys/types.h" +#include "libetpan-config.h" +#include "chash.h" +#include "carray.h" +#ifdef HAVE_INTTYPES_H +# include +#endif + +#include "libetpan-config.h" + +#define LIBETPAN_MAILDIR + +enum { + MAILDIR_NO_ERROR = 0, + MAILDIR_ERROR_CREATE, + MAILDIR_ERROR_DIRECTORY, + MAILDIR_ERROR_MEMORY, + MAILDIR_ERROR_FILE, + MAILDIR_ERROR_NOT_FOUND, + MAILDIR_ERROR_FOLDER +}; + +#define MAILDIR_FLAG_NEW (1 << 0) +#define MAILDIR_FLAG_SEEN (1 << 1) +#define MAILDIR_FLAG_REPLIED (1 << 2) +#define MAILDIR_FLAG_FLAGGED (1 << 3) +#define MAILDIR_FLAG_TRASHED (1 << 4) + +struct maildir_msg { + char * msg_uid; + char * msg_filename; + int msg_flags; +}; + +/* + work around for missing #define HOST_NAME_MAX in Linux +*/ + +#ifndef HOST_NAME_MAX +#define HOST_NAME_MAX 255 +#endif + +struct maildir { + pid_t mdir_pid; + char mdir_hostname[HOST_NAME_MAX]; + char mdir_path[PATH_MAX]; + uint32_t mdir_counter; + time_t mdir_mtime_new; + time_t mdir_mtime_cur; + carray * mdir_msg_list; + chash * mdir_msg_hash; +}; + +#endif diff --git a/Sources/libetpan/include/maildirdriver.h b/Sources/libetpan/include/maildirdriver.h new file mode 100644 index 00000000..ec0d67da --- /dev/null +++ b/Sources/libetpan/include/maildirdriver.h @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver.h,v 1.4 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MAILDIRDRIVER_H + +#define MAILDIRDRIVER_H + +#include "maildriver.h" +#include "maildirdriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * maildir_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/maildirdriver_cached.h b/Sources/libetpan/include/maildirdriver_cached.h new file mode 100644 index 00000000..16e33289 --- /dev/null +++ b/Sources/libetpan/include/maildirdriver_cached.h @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver_cached.h,v 1.4 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MAILDIRDRIVER_CACHED_H + +#define MAILDIRDRIVER_CACHED_H + +#include "maildriver.h" +#include "maildirdriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * maildir_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/maildirdriver_cached_message.h b/Sources/libetpan/include/maildirdriver_cached_message.h new file mode 100644 index 00000000..c55a0372 --- /dev/null +++ b/Sources/libetpan/include/maildirdriver_cached_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver_cached_message.h,v 1.3 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MAILDIRDRIVER_CACHED_MESSAGE_H + +#define MAILDIRDRIVER_CACHED_MESSAGE_H + +#include "maildirdriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * maildir_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/maildirdriver_message.h b/Sources/libetpan/include/maildirdriver_message.h new file mode 100644 index 00000000..becbbd78 --- /dev/null +++ b/Sources/libetpan/include/maildirdriver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver_message.h,v 1.3 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MAILDIRDRIVER_MESSAGE_H + +#define MAILDIRDRIVER_MESSAGE_H + +#include "maildirdriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * maildir_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/maildirdriver_tools.h b/Sources/libetpan/include/maildirdriver_tools.h new file mode 100644 index 00000000..29200146 --- /dev/null +++ b/Sources/libetpan/include/maildirdriver_tools.h @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver_tools.h,v 1.3 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MAILDIRDRIVER_TOOLS_H + +#define MAILDIRDRIVER_TOOLS_H + +#include "maildriver_types.h" +#include "maildir.h" + +int maildirdriver_maildir_error_to_mail_error(int error); + +uint32_t maildirdriver_maildir_flags_to_flags(uint32_t md_flags); + +uint32_t maildirdriver_flags_to_maildir_flags(uint32_t flags); + +int maildir_get_messages_list(mailsession * session, struct maildir * md, + mailmessage_driver * message_driver, + struct mailmessage_list ** result); + +#endif diff --git a/Sources/libetpan/include/maildirdriver_types.h b/Sources/libetpan/include/maildirdriver_types.h new file mode 100644 index 00000000..0eedb19f --- /dev/null +++ b/Sources/libetpan/include/maildirdriver_types.h @@ -0,0 +1,96 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver_types.h,v 1.6 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifndef MAILDIRDRIVER_TYPES_H + +#define MAILDIRDRIVER_TYPES_H + +#include "libetpan-config.h" + +#include "maildriver_types.h" +#include "maildir.h" +#include "generic_cache_types.h" +#include "mailstorage_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct maildir_session_state_data { + struct maildir * md_session; + struct mail_flags_store * md_flags_store; +}; + +enum { + MAILDIRDRIVER_CACHED_SET_CACHE_DIRECTORY = 1, + MAILDIRDRIVER_CACHED_SET_FLAGS_DIRECTORY +}; + +struct maildir_cached_session_state_data { + mailsession * md_ancestor; + char * md_quoted_mb; + struct mail_flags_store * md_flags_store; + char md_cache_directory[PATH_MAX]; + char md_flags_directory[PATH_MAX]; +}; + +/* maildir storage */ + +/* + maildir_mailstorage is the state data specific to the maildir storage. + + - pathname is the path of the maildir storage. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache. + + - flags_directory is the location of the flags. +*/ + +struct maildir_mailstorage { + char * md_pathname; + + int md_cached; + char * md_cache_directory; + char * md_flags_directory; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/maildirstorage.h b/Sources/libetpan/include/maildirstorage.h new file mode 100644 index 00000000..ab9aaa35 --- /dev/null +++ b/Sources/libetpan/include/maildirstorage.h @@ -0,0 +1,70 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirstorage.h,v 1.7 2006/06/02 15:44:29 smarinier Exp $ + */ + +#ifndef MAILDIRSTORAGE_H + +#define MAILDIRSTORAGE_H + +#include "maildirdriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + maildir_mailstorage_init is the constructor for a maildir storage. + + @param storage this is the storage to initialize. + + @param pathname is the directory that contains the mailbox. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache + + @param flags_directory is the location of the flags +*/ + +LIBETPAN_EXPORT +int maildir_mailstorage_init(struct mailstorage * storage, + const char * md_pathname, int md_cached, + const char * md_cache_directory, const char * md_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/maildriver.h b/Sources/libetpan/include/maildriver.h new file mode 100644 index 00000000..fc74d901 --- /dev/null +++ b/Sources/libetpan/include/maildriver.h @@ -0,0 +1,607 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildriver.h,v 1.34 2006/06/07 15:10:01 smarinier Exp $ + */ + +#ifndef MAILDRIVER_H + +#define MAILDRIVER_H + +#include "maildriver_types.h" +#include "maildriver_types_helper.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* mailsession */ + +/* + mailsession_new creates a new session, using the given driver + + @return the created session is returned +*/ + +LIBETPAN_EXPORT +mailsession * mailsession_new(mailsession_driver * sess_driver); + +/* + mailsession_free release the memory used by the session +*/ + +LIBETPAN_EXPORT +void mailsession_free(mailsession * session); + +/* + mailsession_parameters is used to make calls specific to the driver + + @param id is the command to send to the driver, + usually, commands can be found in the header of the driver + + @param value is the parameter of the specific call + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_parameters(mailsession * session, + int id, void * value); + +/* + There are drivers of two kinds : stream drivers (driver that connects + to servers through TCP or other means of connection) and file drivers + (driver that are based on filesystem) + + The following function can only be used by stream drivers. + mailsession_connect_stream connects a stream to the session + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_connect_stream(mailsession * session, mailstream * s); + +/* + The following function can only be used by file drivers. + mailsession_connect_path selects the main path of the session + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_connect_path(mailsession * session, const char * path); + +/* + NOTE: works only on stream drivers + + mailsession_starttls switches the current connection to TLS (secure layer) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_starttls(mailsession * session); + +/* + mailsession_login notifies the login and the password to authenticate + to the session + + @param userid the given string is only needed at this function call + (it will be duplicated if necessary) + @param password the given string is only needed at this function call + (it will be duplicated if necessary) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_login(mailsession * session, + const char * userid, const char * password); + +/* + NOTE: this function doesn't often work on filsystem drivers + + mailsession_logout deconnects the session and closes the stream. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_logout(mailsession * session); + +/* + mailsession_noop does no operation on the session, but it can be + used to poll for the status of the connection. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_noop(mailsession * session); + +/* + NOTE: driver's specific should be used + + mailsession_build_folder_name will return an allocated string with + that contains the complete path of the folder to create + + @param session the sesion + @param mb is the parent mailbox + @param name is the name of the folder to create + @param result the complete path of the folder to create will be + stored in (* result), this name have to be freed with free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_build_folder_name(mailsession * session, const char * mb, + const char * name, char ** result); + +/* + NOTE: driver's specific should be used + + mailsession_create_folder creates the folder that corresponds to the + given name + + @param session the session + @param mb is the name of the mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_create_folder(mailsession * session, const char * mb); + + +/* + NOTE: driver's specific should be used + + mailsession_delete_folder deletes the folder that corresponds to the + given name + + @param session the session + @param mb is the name of the mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_delete_folder(mailsession * session, const char * mb); + + +/* + mailsession_rename_folder changes the name of the folder + + @param session the session + @param mb is the name of the mailbox whose name has to be changed + @param new_name is the destination name (the parent + of the new folder folder can be other) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_rename_folder(mailsession * session, + const char * mb, const char * new_name); + +/* + mailsession_check_folder makes a checkpoint of the session + + @param session the session + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_check_folder(mailsession * session); + + +/* + NOTE: this function is not implemented in most drivers + + mailsession_examine_folder selects a mailbox as readonly + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_examine_folder(mailsession * session, const char * mb); + + +/* + mailsession_select_folder selects a mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_select_folder(mailsession * session, const char * mb); + + +/* + mailsession_expunge_folder deletes all messages marked \Deleted + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_expunge_folder(mailsession * session); + + +/* + mailsession_status_folder queries the status of the folder + (number of messages, number of recent messages, number of unseen messages) + + @param session the session + @param mb mailbox to query + @param result_messages the number of messages is stored + in (* result_messages) + @param result_recent the number of messages is stored + in (* result_recent) + @param result_unseen the number of messages is stored + in (* result_unseen) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + + +/* + mailsession_messages_number queries the number of messages in the folder + + @param session the session + @param mb mailbox to query + @param result the number of messages is stored in (* result) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_messages_number(mailsession * session, const char * mb, + uint32_t * result); + +/* + mailsession_recent_number queries the number of recent messages in the folder + + @param session the session + @param mb mailbox to query + @param result the number of recent messages is stored in (* result) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_recent_number(mailsession * session, + const char * mb, uint32_t * result); + +/* + mailsession_unseen_number queries the number of unseen messages in the folder + + @param session the session + @param mb mailbox to query + @param result the number of unseen messages is stored in (* result) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_unseen_number(mailsession * session, const char * mb, + uint32_t * result); + +/* + NOTE: driver's specific should be used + + mailsession_list_folders returns the list of all sub-mailboxes + of the given mailbox + + @param session the session + @param mb the mailbox + @param result list of mailboxes if stored in (* result), + this structure have to be freed with mail_list_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_list_folders(mailsession * session, const char * mb, + struct mail_list ** result); + +/* + NOTE: driver's specific should be used + + mailsession_lsub_folders returns the list of subscribed + sub-mailboxes of the given mailbox + + @param session the session + @param mb the mailbox + @param result list of mailboxes if stored in (* result), + this structure have to be freed with mail_list_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result); + +/* + NOTE: driver's specific should be used + + mailsession_subscribe_folder subscribes to the given mailbox + + @param session the session + @param mb the mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_subscribe_folder(mailsession * session, const char * mb); + +/* + NOTE: driver's specific should be used + + mailsession_unsubscribe_folder unsubscribes to the given mailbox + + @param session the session + @param mb the mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_unsubscribe_folder(mailsession * session, const char * mb); + +/* + mailsession_append_message adds a RFC 2822 message to the current + given mailbox + + @param session the session + @param message is a string that contains the RFC 2822 message + @param size this is the size of the message + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_append_message(mailsession * session, + const char * message, size_t size); + +LIBETPAN_EXPORT +int mailsession_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); + +/* + NOTE: some drivers does not implement this + + mailsession_copy_message copies a message whose number is given to + a given mailbox. The mailbox must be accessible from the same session. + + @param session the session + @param num the message number + @param mb the destination mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_copy_message(mailsession * session, + uint32_t num, const char * mb); + +/* + NOTE: some drivers does not implement this + + mailsession_move_message copies a message whose number is given to + a given mailbox. The mailbox must be accessible from the same session. + + @param session the session + @param num the message number + @param mb the destination mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_move_message(mailsession * session, + uint32_t num, const char * mb); + +/* + mailsession_get_messages_list returns the list of message numbers + of the current mailbox. + + @param session the session + @param result the list of message numbers will be stored in (* result), + this structure have to be freed with mailmessage_list_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +/* + mailsession_get_envelopes_list fills the parsed fields in the + mailmessage structures of the mailmessage_list. + + @param session the session + @param result this is the list of mailmessage structures + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_get_envelopes_list(mailsession * session, + struct mailmessage_list * result); + +/* + NOTE: some drivers does not implement this + + mailsession_remove_message removes the given message from the mailbox. + The message is permanently deleted. + + @param session the session + @param num is the message number + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_remove_message(mailsession * session, uint32_t num); + + +/* + NOTE: this function is not implemented in most drivers + + mailsession_search_message returns a list of message numbers that + corresponds to the given criteria. + + @param session the session + @param charset is the charset to use (it can be NULL) + @param key is the list of criteria + @param result the search result is stored in (* result), + this structure have to be freed with mail_search_result_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +#if 0 +LIBETPAN_EXPORT +int mailsession_search_messages(mailsession * session, const char * charset, + struct mail_search_key * key, + struct mail_search_result ** result); +#endif + +/* + mailsession_get_message returns a mailmessage structure that corresponds + to the given message number. + * WARNING * mailsession_get_message_by_uid() should be used instead. + + @param session the session + @param num the message number + @param result the allocated mailmessage structure will be stored + in (* result), this structure have to be freed with mailmessage_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +/* + mailsession_get_message_by_uid returns a mailmessage structure + that corresponds to the given message unique identifier. + This is currently implemented only for cached drivers. + * WARNING * That will deprecates the use of mailsession_get_message() + + @param session the session + @param uid the message unique identifier + @param result the allocated mailmessage structure will be stored + in (* result), this structure have to be freed with mailmessage_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result); + + +/* + mailsession_login notifies the SASL authentication information + to the session + + @param auth_type type of SASL authentication + @param server_fqdn server full qualified domain name + @param local_ip_port local IP:port (client) + @param remote_ip_port remote IP:port (server) + @param login login + @param auth_name authentication name + @param password password (or token for OAuth2 login) + @param realm realm + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_login_sasl(mailsession * session, const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/maildriver_errors.h b/Sources/libetpan/include/maildriver_errors.h new file mode 100644 index 00000000..b131a72e --- /dev/null +++ b/Sources/libetpan/include/maildriver_errors.h @@ -0,0 +1,103 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildriver_errors.h,v 1.9 2006/12/13 18:31:32 hoa Exp $ + */ + +#ifndef MAILDRIVER_ERRORS_H + +#define MAILDRIVER_ERRORS_H + +enum { + MAIL_NO_ERROR = 0, + MAIL_NO_ERROR_AUTHENTICATED, + MAIL_NO_ERROR_NON_AUTHENTICATED, + MAIL_ERROR_NOT_IMPLEMENTED, + MAIL_ERROR_UNKNOWN, + MAIL_ERROR_CONNECT, + MAIL_ERROR_BAD_STATE, + MAIL_ERROR_FILE, + MAIL_ERROR_STREAM, + MAIL_ERROR_LOGIN, + MAIL_ERROR_CREATE, /* 10 */ + MAIL_ERROR_DELETE, + MAIL_ERROR_LOGOUT, + MAIL_ERROR_NOOP, + MAIL_ERROR_RENAME, + MAIL_ERROR_CHECK, + MAIL_ERROR_EXAMINE, + MAIL_ERROR_SELECT, + MAIL_ERROR_MEMORY, + MAIL_ERROR_STATUS, + MAIL_ERROR_SUBSCRIBE, /* 20 */ + MAIL_ERROR_UNSUBSCRIBE, + MAIL_ERROR_LIST, + MAIL_ERROR_LSUB, + MAIL_ERROR_APPEND, + MAIL_ERROR_COPY, + MAIL_ERROR_FETCH, + MAIL_ERROR_STORE, + MAIL_ERROR_SEARCH, + MAIL_ERROR_DISKSPACE, + MAIL_ERROR_MSG_NOT_FOUND, /* 30 */ + MAIL_ERROR_PARSE, + MAIL_ERROR_INVAL, + MAIL_ERROR_PART_NOT_FOUND, + MAIL_ERROR_REMOVE, + MAIL_ERROR_FOLDER_NOT_FOUND, + MAIL_ERROR_MOVE, + MAIL_ERROR_STARTTLS, + MAIL_ERROR_CACHE_MISS, + MAIL_ERROR_NO_TLS, + MAIL_ERROR_EXPUNGE, /* 40 */ + /* misc errors */ + MAIL_ERROR_MISC, + MAIL_ERROR_PROTOCOL, + MAIL_ERROR_CAPABILITY, + MAIL_ERROR_CLOSE, + MAIL_ERROR_FATAL, + MAIL_ERROR_READONLY, + MAIL_ERROR_NO_APOP, + MAIL_ERROR_COMMAND_NOT_SUPPORTED, + MAIL_ERROR_NO_PERMISSION, + MAIL_ERROR_PROGRAM_ERROR, /* 50 */ + MAIL_ERROR_SUBJECT_NOT_FOUND, + MAIL_ERROR_CHAR_ENCODING_FAILED, + MAIL_ERROR_SEND, + MAIL_ERROR_COMMAND, + MAIL_ERROR_SYSTEM, + MAIL_ERROR_UNABLE, + MAIL_ERROR_FOLDER, + MAIL_ERROR_SSL +}; + +#endif diff --git a/Sources/libetpan/include/maildriver_tools.h b/Sources/libetpan/include/maildriver_tools.h new file mode 100644 index 00000000..229e72b7 --- /dev/null +++ b/Sources/libetpan/include/maildriver_tools.h @@ -0,0 +1,81 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildriver_tools.h,v 1.15 2006/06/07 15:10:01 smarinier Exp $ + */ + +#ifndef MAILDRIVER_TOOLS_H + +#define MAILDRIVER_TOOLS_H + +#include "maildriver_types.h" +#include "mail_cache_db_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int +maildriver_generic_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +#if 0 +int maildriver_generic_search_messages(mailsession * session, char * charset, + struct mail_search_key * key, + struct mail_search_result ** result); +#endif + +int +maildriver_env_list_to_msg_list(struct mailmessage_list * env_list, + clist ** result); + +int maildriver_imf_error_to_mail_error(int error); + +char * maildriver_quote_mailbox(const char * mb); + +int +maildriver_env_list_to_msg_list_no_flags(struct mailmessage_list * env_list, + clist ** result); + +int maildriver_cache_clean_up(struct mail_cache_db * cache_db_env, + struct mail_cache_db * cache_db_flags, + struct mailmessage_list * env_list); + +int maildriver_message_cache_clean_up(char * cache_dir, + struct mailmessage_list * env_list, + void (* get_uid_from_filename)(char *)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/maildriver_types.h b/Sources/libetpan/include/maildriver_types.h new file mode 100644 index 00000000..791edd97 --- /dev/null +++ b/Sources/libetpan/include/maildriver_types.h @@ -0,0 +1,822 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildriver_types.h,v 1.49 2008/04/19 09:25:40 hoa Exp $ + */ + +#ifndef MAILDRIVER_TYPES_H + +#define MAILDRIVER_TYPES_H + +#ifndef _MSC_VER +# ifdef HAVE_INTTYPES_H +# include +# endif +# include +#endif + +#include "mailstream.h" +#include "mailimf.h" +#include "mailmime.h" +#include "carray.h" + +#include "mailthread_types.h" +#include "maildriver_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct mailsession_driver mailsession_driver; + +typedef struct mailsession mailsession; + +typedef struct mailmessage_driver mailmessage_driver; + +typedef struct mailmessage mailmessage; + + +/* + mailmessage_list is a list of mailmessage + + - tab is an array of mailmessage structures +*/ + +struct mailmessage_list { + carray * msg_tab; /* elements are (mailmessage *) */ +}; + +LIBETPAN_EXPORT +struct mailmessage_list * mailmessage_list_new(carray * msg_tab); + +LIBETPAN_EXPORT +void mailmessage_list_free(struct mailmessage_list * env_list); + +/* + mail_list is a list of mailbox names + + - list is a list of mailbox names +*/ + +struct mail_list { + clist * mb_list; /* elements are (char *) */ +}; + +LIBETPAN_EXPORT +struct mail_list * mail_list_new(clist * mb_list); + +LIBETPAN_EXPORT +void mail_list_free(struct mail_list * resp); + +/* + This is a flag value. + Flags can be combined with OR operation +*/ + +enum { + MAIL_FLAG_NEW = 1 << 0, + MAIL_FLAG_SEEN = 1 << 1, + MAIL_FLAG_FLAGGED = 1 << 2, + MAIL_FLAG_DELETED = 1 << 3, + MAIL_FLAG_ANSWERED = 1 << 4, + MAIL_FLAG_FORWARDED = 1 << 5, + MAIL_FLAG_CANCELLED = 1 << 6 +}; + +/* + mail_flags is the value of a flag related to a message. + + - flags is the standard flags value + + - extension is a list of unknown flags for libEtPan! +*/ + +struct mail_flags { + uint32_t fl_flags; + clist * fl_extension; /* elements are (char *) */ +}; + +LIBETPAN_EXPORT +struct mail_flags * mail_flags_new(uint32_t fl_flags, clist * fl_ext); + +LIBETPAN_EXPORT +void mail_flags_free(struct mail_flags * flags); + +/* + This function creates a flag for a new message +*/ + +LIBETPAN_EXPORT +struct mail_flags * mail_flags_new_empty(void); + + +/* + mailimf_date_time_comp compares two dates + + +*/ + +LIBETPAN_EXPORT +int32_t mailimf_date_time_comp(struct mailimf_date_time * date1, + struct mailimf_date_time * date2); + +/* + this is type type of the search criteria +*/ + +enum { + MAIL_SEARCH_KEY_ALL, /* all messages correspond */ + MAIL_SEARCH_KEY_ANSWERED, /* messages with flag \Answered */ + MAIL_SEARCH_KEY_BCC, /* messages which Bcc field contains + a given string */ + MAIL_SEARCH_KEY_BEFORE, /* messages which internal date is earlier + than the specified date */ + MAIL_SEARCH_KEY_BODY, /* message that contains the given string + (in header and text parts) */ + MAIL_SEARCH_KEY_CC, /* messages whose Cc field contains the + given string */ + MAIL_SEARCH_KEY_DELETED, /* messages with the flag \Deleted */ + MAIL_SEARCH_KEY_FLAGGED, /* messages with the flag \Flagged */ + MAIL_SEARCH_KEY_FROM, /* messages whose From field contains the + given string */ + MAIL_SEARCH_KEY_NEW, /* messages with the flag \Recent and not + the \Seen flag */ + MAIL_SEARCH_KEY_OLD, /* messages that do not have the + \Recent flag set */ + MAIL_SEARCH_KEY_ON, /* messages whose internal date is the + specified date */ + MAIL_SEARCH_KEY_RECENT, /* messages with the flag \Recent */ + MAIL_SEARCH_KEY_SEEN, /* messages with the flag \Seen */ + MAIL_SEARCH_KEY_SINCE, /* messages whose internal date is later + than specified date */ + MAIL_SEARCH_KEY_SUBJECT, /* messages whose Subject field contains the + given string */ + MAIL_SEARCH_KEY_TEXT, /* messages whose text part contains the + given string */ + MAIL_SEARCH_KEY_TO, /* messages whose To field contains the + given string */ + MAIL_SEARCH_KEY_UNANSWERED, /* messages with no flag \Answered */ + MAIL_SEARCH_KEY_UNDELETED, /* messages with no flag \Deleted */ + MAIL_SEARCH_KEY_UNFLAGGED, /* messages with no flag \Flagged */ + MAIL_SEARCH_KEY_UNSEEN, /* messages with no flag \Seen */ + MAIL_SEARCH_KEY_HEADER, /* messages whose given field + contains the given string */ + MAIL_SEARCH_KEY_LARGER, /* messages whose size is larger then + the given size */ + MAIL_SEARCH_KEY_NOT, /* not operation of the condition */ + MAIL_SEARCH_KEY_OR, /* or operation between two conditions */ + MAIL_SEARCH_KEY_SMALLER, /* messages whose size is smaller than + the given size */ + MAIL_SEARCH_KEY_MULTIPLE /* the boolean operator between the + conditions is AND */ +}; + +/* + mail_search_key is the condition on the messages to return + + - type is the type of the condition + + - bcc is the text to search in the Bcc field when type is + MAIL_SEARCH_KEY_BCC, should be allocated with malloc() + + - before is a date when type is MAIL_SEARCH_KEY_BEFORE + + - body is the text to search in the message when type is + MAIL_SEARCH_KEY_BODY, should be allocated with malloc() + + - cc is the text to search in the Cc field when type is + MAIL_SEARCH_KEY_CC, should be allocated with malloc() + + - from is the text to search in the From field when type is + MAIL_SEARCH_KEY_FROM, should be allocated with malloc() + + - on is a date when type is MAIL_SEARCH_KEY_ON + + - since is a date when type is MAIL_SEARCH_KEY_SINCE + + - subject is the text to search in the Subject field when type is + MAILIMAP_SEARCH_KEY_SUBJECT, should be allocated with malloc() + + - text is the text to search in the text part of the message when + type is MAILIMAP_SEARCH_KEY_TEXT, should be allocated with malloc() + + - to is the text to search in the To field when type is + MAILIMAP_SEARCH_KEY_TO, should be allocated with malloc() + + - header_name is the header name when type is MAILIMAP_SEARCH_KEY_HEADER, + should be allocated with malloc() + + - header_value is the text to search in the given header when type is + MAILIMAP_SEARCH_KEY_HEADER, should be allocated with malloc() + + - larger is a size when type is MAILIMAP_SEARCH_KEY_LARGER + + - not is a condition when type is MAILIMAP_SEARCH_KEY_NOT + + - or1 is a condition when type is MAILIMAP_SEARCH_KEY_OR + + - or2 is a condition when type is MAILIMAP_SEARCH_KEY_OR + + - sentbefore is a date when type is MAILIMAP_SEARCH_KEY_SENTBEFORE + + - senton is a date when type is MAILIMAP_SEARCH_KEY_SENTON + + - sentsince is a date when type is MAILIMAP_SEARCH_KEY_SENTSINCE + + - smaller is a size when type is MAILIMAP_SEARCH_KEY_SMALLER + + - multiple is a set of message when type is MAILIMAP_SEARCH_KEY_MULTIPLE +*/ + +#if 0 +struct mail_search_key { + int sk_type; + union { + char * sk_bcc; + struct mailimf_date_time * sk_before; + char * sk_body; + char * sk_cc; + char * sk_from; + struct mailimf_date_time * sk_on; + struct mailimf_date_time * sk_since; + char * sk_subject; + char * sk_text; + char * sk_to; + char * sk_header_name; + char * sk_header_value; + size_t sk_larger; + struct mail_search_key * sk_not; + struct mail_search_key * sk_or1; + struct mail_search_key * sk_or2; + size_t sk_smaller; + clist * sk_multiple; /* list of (struct mailimap_search_key *) */ + } sk_data; +}; + + +struct mail_search_key * +mail_search_key_new(int sk_type, + char * sk_bcc, struct mailimf_date_time * sk_before, + char * sk_body, char * sk_cc, char * sk_from, + struct mailimf_date_time * sk_on, struct mailimf_date_time * sk_since, + char * sk_subject, char * sk_text, char * sk_to, + char * sk_header_name, char * sk_header_value, size_t sk_larger, + struct mail_search_key * sk_not, struct mail_search_key * sk_or1, + struct mail_search_key * sk_or2, size_t sk_smaller, + clist * sk_multiple); + +void mail_search_key_free(struct mail_search_key * key); +#endif + +/* + mail_search_result is a list of message numbers that is returned + by the mailsession_search_messages function() +*/ + +#if 0 +struct mail_search_result { + clist * sr_list; /* list of (uint32_t *) */ +}; + +struct mail_search_result * mail_search_result_new(clist * sr_list); + +void mail_search_result_free(struct mail_search_result * search_result); +#endif + + +/* + There is three kinds of identities : + - storage + - folders + - session + + A storage (struct mailstorage) represents whether a server or + a main path, + + A storage can be an IMAP server, the root path of a MH or a mbox file. + + Folders (struct mailfolder) are the mailboxes we can + choose in the server or as sub-folder of the main path. + + Folders for IMAP are the IMAP mailboxes, for MH this is one of the + folder of the MH storage, for mbox, there is only one folder, the + mbox file content; + + A mail session (struct mailsession) is whether a connection to a server + or a path that is open. It is the abstraction lower folders and storage. + It allow us to send commands. + + We have a session driver for mail session for each kind of storage. + + From a session, we can get a message (struct mailmessage) to read. + We have a message driver for each kind of storage. +*/ + +/* + maildriver is the driver structure for mail sessions + + - name is the name of the driver + + - initialize() is the function that will initializes a data structure + specific to the driver, it returns a value that will be stored + in the field data of the session. + The field data of the session is the state of the session, + the internal data structure used by the driver. + It is called when creating the mailsession structure with + mailsession_new(). + + - uninitialize() frees the structure created with initialize() + + - parameters() implements functions specific to the given mail access + + - connect_stream() connects a stream to the session + + - connect_path() notify a main path to the session + + - starttls() changes the current stream to a TLS stream + + - login() notifies the user and the password to authenticate to the + session + + - logout() exits the session and closes the stream + + - noop() does no operation on the session, but it can be + used to poll for the status of the connection. + + - build_folder_name() will return an allocated string with + that contains the complete path of the folder to create + + - create_folder() creates the folder that corresponds to the + given name + + - delete_folder() deletes the folder that corresponds to the + given name + + - rename_folder() change the name of the folder + + - check_folder() makes a checkpoint of the session + + - examine_folder() selects a mailbox as readonly + + - select_folder() selects a mailbox + + - expunge_folder() deletes all messages marked \Deleted + + - status_folder() queries the status of the folder + (number of messages, number of recent messages, number of + unseen messages) + + - messages_number() queries the number of messages in the folder + + - recent_number() queries the number of recent messages in the folder + + - unseen_number() queries the number of unseen messages in the folder + + - list_folders() returns the list of all sub-mailboxes + of the given mailbox + + - lsub_folders() returns the list of subscribed + sub-mailboxes of the given mailbox + + - subscribe_folder() subscribes to the given mailbox + + - unsubscribe_folder() unsubscribes to the given mailbox + + - append_message() adds a RFC 2822 message to the current + given mailbox + + - copy_message() copies a message whose number is given to + a given mailbox. The mailbox must be accessible from + the same session. + + - move_message() copies a message whose number is given to + a given mailbox. The mailbox must be accessible from the + same session. + + - get_messages_list() returns the list of message numbers + of the current mailbox. + + - get_envelopes_list() fills the parsed fields in the + mailmessage structures of the mailmessage_list. + + - remove_message() removes the given message from the mailbox. + The message is permanently deleted. + + - search_message() returns a list of message numbers that + corresponds to the given criteria. + + - get_message returns a mailmessage structure that corresponds + to the given message number. + + - get_message_by_uid returns a mailmessage structure that corresponds + to the given message unique identifier. + + * mandatory functions are the following : + + - connect_stream() of connect_path() + - logout() + - get_messages_list() + - get_envelopes_list() + + * we advise you to implement these functions : + + - select_folder() (in case a session can access several folders) + - noop() (to check if the server is responding) + - check_folder() (to make a checkpoint of the session) + - status_folder(), messages_number(), recent_number(), unseen_number() + (to get stat of the folder) + - append_message() (but can't be done in the case of POP3 at least) + - login() in a case of an authenticated driver. + - starttls() in a case of a stream driver, if the procotol supports + STARTTLS. + - get_message_by_uid() so that the application can remember the message + by UID and build its own list of messages. + - login_sasl() notifies the SASL information to authenticate to the + session. + + * drivers' specific : + + Everything that is specific to the driver will be implemented in this + function : + + - parameters() +*/ + +struct mailsession_driver { + char * sess_name; + + int (* sess_initialize)(mailsession * session); + void (* sess_uninitialize)(mailsession * session); + + int (* sess_parameters)(mailsession * session, + int id, void * value); + + int (* sess_connect_stream)(mailsession * session, mailstream * s); + int (* sess_connect_path)(mailsession * session, const char * path); + + int (* sess_starttls)(mailsession * session); + + int (* sess_login)(mailsession * session, const char * userid, const char * password); + int (* sess_logout)(mailsession * session); + int (* sess_noop)(mailsession * session); + + /* folders operations */ + + int (* sess_build_folder_name)(mailsession * session, const char * mb, + const char * name, char ** result); + + int (* sess_create_folder)(mailsession * session, const char * mb); + int (* sess_delete_folder)(mailsession * session, const char * mb); + int (* sess_rename_folder)(mailsession * session, const char * mb, + const char * new_name); + int (* sess_check_folder)(mailsession * session); + int (* sess_examine_folder)(mailsession * session, const char * mb); + int (* sess_select_folder)(mailsession * session, const char * mb); + int (* sess_expunge_folder)(mailsession * session); + int (* sess_status_folder)(mailsession * session, const char * mb, + uint32_t * result_num, uint32_t * result_recent, + uint32_t * result_unseen); + int (* sess_messages_number)(mailsession * session, const char * mb, + uint32_t * result); + int (* sess_recent_number)(mailsession * session, const char * mb, + uint32_t * result); + int (* sess_unseen_number)(mailsession * session, const char * mb, + uint32_t * result); + + int (* sess_list_folders)(mailsession * session, const char * mb, + struct mail_list ** result); + int (* sess_lsub_folders)(mailsession * session, const char * mb, + struct mail_list ** result); + + int (* sess_subscribe_folder)(mailsession * session, const char * mb); + int (* sess_unsubscribe_folder)(mailsession * session, const char * mb); + + /* messages operations */ + + int (* sess_append_message)(mailsession * session, + const char * message, size_t size); + int (* sess_append_message_flags)(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); + int (* sess_copy_message)(mailsession * session, + uint32_t num, const char * mb); + int (* sess_move_message)(mailsession * session, + uint32_t num, const char * mb); + + int (* sess_get_message)(mailsession * session, + uint32_t num, mailmessage ** result); + + int (* sess_get_message_by_uid)(mailsession * session, + const char * uid, mailmessage ** result); + + int (* sess_get_messages_list)(mailsession * session, + struct mailmessage_list ** result); + int (* sess_get_envelopes_list)(mailsession * session, + struct mailmessage_list * env_list); + int (* sess_remove_message)(mailsession * session, uint32_t num); + + int (* sess_login_sasl)(mailsession * session, const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); +}; + + +/* + session is the data structure for a mail session. + + - data is the internal data structure used by the driver + It is called when initializing the mailsession structure. + + - driver is the driver used for the session +*/ + +struct mailsession { + void * sess_data; + mailsession_driver * sess_driver; +}; + + + + +/* + mailmessage_driver is the driver structure to get information from messages. + + - name is the name of the driver + + - initialize() is the function that will initializes a data structure + specific to the driver, it returns a value that will be stored + in the field data of the mailsession. + The field data of the session is the state of the session, + the internal data structure used by the driver. + It is called when initializing the mailmessage structure with + mailmessage_init(). + + - uninitialize() frees the structure created with initialize(). + It will be called by mailmessage_free(). + + - flush() will free from memory all temporary structures of the message + (for example, the MIME structure of the message). + + - fetch_result_free() will free all strings resulted by fetch() or + any fetch_xxx() functions that returns a string. + + - fetch() returns the content of the message (headers and text). + + - fetch_header() returns the content of the headers. + + - fetch_body() returns the message text (message content without headers) + + - fetch_size() returns the size of the message content. + + - get_bodystructure() returns the MIME structure of the message. + + - fetch_section() returns the content of a given MIME part + + - fetch_section_header() returns the header of the message + contained by the given MIME part. + + - fetch_section_mime() returns the MIME headers of the + given MIME part. + + - fetch_section_body() returns the text (if this is a message, this is the + message content without headers) of the given MIME part. + + - fetch_envelope() returns a mailimf_fields structure, with a list of + fields chosen by the driver. + + - get_flags() returns a the flags related to the message. + When you want to get flags of a message, you have to make sure to + call get_flags() at least once before using directly message->flags. +*/ + +#define LIBETPAN_MAIL_MESSAGE_CHECK + +struct mailmessage_driver { + char * msg_name; + + int (* msg_initialize)(mailmessage * msg_info); + + void (* msg_uninitialize)(mailmessage * msg_info); + + void (* msg_flush)(mailmessage * msg_info); + + void (* msg_check)(mailmessage * msg_info); + + void (* msg_fetch_result_free)(mailmessage * msg_info, + char * msg); + + int (* msg_fetch)(mailmessage * msg_info, + char ** result, + size_t * result_len); + + int (* msg_fetch_header)(mailmessage * msg_info, + char ** result, + size_t * result_len); + + int (* msg_fetch_body)(mailmessage * msg_info, + char ** result, size_t * result_len); + + int (* msg_fetch_size)(mailmessage * msg_info, + size_t * result); + + int (* msg_get_bodystructure)(mailmessage * msg_info, + struct mailmime ** result); + + int (* msg_fetch_section)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + + int (* msg_fetch_section_header)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_section_mime)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_section_body)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_envelope)(mailmessage * msg_info, + struct mailimf_fields ** result); + + int (* msg_get_flags)(mailmessage * msg_info, + struct mail_flags ** result); +}; + + +/* + mailmessage is a data structure to get information from messages + + - session is the session linked to the given message, it can be NULL + + - driver is the message driver + + - index is the message number + + - uid, when it is not NULL, it means that the folder + the folder has persistant message numbers, the string is + the unique message number in the folder. + uid should be implemented if possible. + for drivers where we cannot generate real uid, + a suggestion is "AAAA-IIII" where AAAA is some + random session number and IIII the content of index field. + + - size, when it is not 0, is the size of the message content. + + - fields, when it is not NULL, are the header fields of the message. + + - flags, when it is not NULL, are the flags related to the message. + + - single_fields, when resolved != 0, is filled with the data of fields. + + - mime, when it is not NULL + + - cached is != 0 when the header fields were read from the cache. + + - data is data specific to the driver, this is internal data structure, + some state of the message. +*/ + +struct mailmessage { + mailsession * msg_session; + mailmessage_driver * msg_driver; + uint32_t msg_index; + char * msg_uid; + + size_t msg_size; + struct mailimf_fields * msg_fields; + struct mail_flags * msg_flags; + + int msg_resolved; + struct mailimf_single_fields msg_single_fields; + struct mailmime * msg_mime; + + /* internal data */ + + int msg_cached; + void * msg_data; + + /* + msg_folder field : + used to reference the mailfolder, this is a workaround due + to the problem with initial conception, where folder notion + did not exist. + */ + void * msg_folder; + /* user data */ + void * msg_user_data; +}; + + +/* + mailmessage_tree is a node in the messages tree (thread) + + - node_parent is the parent of the message, it is NULL if the message + is the root of the message tree. + + - node_msgid is the message ID of this node. + + - node_date is the date of the message in number of second elapsed + since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC). + + - node_msg is the message structure that is stored referenced by the node. + is msg is NULL, this is a dummy node. + + - node_children is an array that contains all the children of the node. + children are mailmessage_tree structures. + + - node_is_reply is != 0 when the message is a reply or a forward + + - node_base_subject is the extracted subject of the message. +*/ + +struct mailmessage_tree { + struct mailmessage_tree * node_parent; + char * node_msgid; + time_t node_date; + mailmessage * node_msg; + carray * node_children; /* array of (struct mailmessage_tree *) */ + + /* private, used for threading */ + int node_is_reply; + char * node_base_subject; +}; + +LIBETPAN_EXPORT +struct mailmessage_tree * +mailmessage_tree_new(char * node_msgid, time_t node_date, + mailmessage * node_msg); + +LIBETPAN_EXPORT +void mailmessage_tree_free(struct mailmessage_tree * tree); + +/* + mailmessage_tree_free_recursive + + if you want to release memory of the given tree and all the sub-trees, + you can use this function. +*/ +LIBETPAN_EXPORT +void mailmessage_tree_free_recursive(struct mailmessage_tree * tree); + + +struct generic_message_t { + int (* msg_prefetch)(mailmessage * msg_info); + void (* msg_prefetch_free)(struct generic_message_t * msg); + int msg_fetched; + char * msg_message; + size_t msg_length; + void * msg_data; +}; + +LIBETPAN_EXPORT +const char * maildriver_strerror(int err); + +/* basic malloc / free functions to be compliant with the library allocations */ +LIBETPAN_EXPORT +void *libetpan_malloc(size_t length); + +LIBETPAN_EXPORT +void libetpan_free(void* data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/maildriver_types_helper.h b/Sources/libetpan/include/maildriver_types_helper.h new file mode 100644 index 00000000..d9e2d619 --- /dev/null +++ b/Sources/libetpan/include/maildriver_types_helper.h @@ -0,0 +1,99 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildriver_types_helper.h,v 1.6 2004/11/21 21:53:35 hoa Exp $ + */ + +#ifndef MAILDRIVER_TYPES_HELPER_H + +#define MAILDRIVER_TYPES_HELPER_H + +#include "maildriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mail_flags_add_extension adds the given flag if it does not exists in + the flags. + + @param flags this is the flag to change + + @param ext_flag this is the name of an extension flag + the given flag name is duplicated and is no more needed after + the function call. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mail_flags_add_extension(struct mail_flags * flags, + char * ext_flag); + +/* + mail_flags_remove_extension removes the given flag if it does not exists in + the flags. + + @param flags this is the flag to change + + @param ext_flag this is the name of an extension flag + the given flag name is no more needed after the function call. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mail_flags_remove_extension(struct mail_flags * flags, + char * ext_flag); + +/* + mail_flags_has_extension returns 1 if the flags is in the given flags, + 0 is returned otherwise. + + @param flags this is the flag to change + + @param ext_flag this is the name of an extension flag + the given flag name is no more needed after the function call. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mail_flags_has_extension(struct mail_flags * flags, + char * ext_flag); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailengine.h b/Sources/libetpan/include/mailengine.h new file mode 100644 index 00000000..36294040 --- /dev/null +++ b/Sources/libetpan/include/mailengine.h @@ -0,0 +1,190 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailengine.h,v 1.3 2004/11/21 21:53:35 hoa Exp $ + */ + +#ifndef MAILENGINE_H + +#define MAILENGINE_H + +#include "mailmessage.h" +#include "mailfolder.h" +#include "mailprivacy_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + to run things in thread, you must protect the storage again concurrency. +*/ + + +/* + storage data +*/ + +struct mailengine * +libetpan_engine_new(struct mailprivacy * privacy); + +void libetpan_engine_free(struct mailengine * engine); + + +struct mailprivacy * +libetpan_engine_get_privacy(struct mailengine * engine); + + +/* + message ref and unref +*/ + +/* + these function can only take messages returned by get_msg_list() + as arguments. + + these functions cannot fail. +*/ + +int libetpan_message_ref(struct mailengine * engine, + mailmessage * msg); + +int libetpan_message_unref(struct mailengine * engine, + mailmessage * msg); + + +/* + when you want to access the MIME structure of the message + with msg->mime, you have to call libetpan_message_mime_ref() + and libetpan_message_mime_unref() when you have finished. + + if libetpan_mime_ref() returns a value <= 0, it means this failed. + the value is -MAIL_ERROR_XXX +*/ + +int libetpan_message_mime_ref(struct mailengine * engine, + mailmessage * msg); + +int libetpan_message_mime_unref(struct mailengine * engine, + mailmessage * msg); + +/* + message list +*/ + +/* + libetpan_folder_get_msg_list() + + This function returns two list. + - List of lost message (the messages that were previously returned + but that does no more exist) (p_lost_msg_list) + - List of valid messages (p_new_msg_list). + + These two list can only be freed by libetpan_folder_free_msg_list() +*/ + +int libetpan_folder_get_msg_list(struct mailengine * engine, + struct mailfolder * folder, + struct mailmessage_list ** p_new_msg_list, + struct mailmessage_list ** p_lost_msg_list); + +int libetpan_folder_fetch_env_list(struct mailengine * engine, + struct mailfolder * folder, + struct mailmessage_list * msg_list); + +void libetpan_folder_free_msg_list(struct mailengine * engine, + struct mailfolder * folder, + struct mailmessage_list * env_list); + + +/* + connect and disconnect storage +*/ + +int libetpan_storage_add(struct mailengine * engine, + struct mailstorage * storage); + +void libetpan_storage_remove(struct mailengine * engine, + struct mailstorage * storage); + +int libetpan_storage_connect(struct mailengine * engine, + struct mailstorage * storage); + +void libetpan_storage_disconnect(struct mailengine * engine, + struct mailstorage * storage); + +int libetpan_storage_used(struct mailengine * engine, + struct mailstorage * storage); + + +/* + libetpan_folder_connect() + libetpan_folder_disconnect() + + You can disconnect the folder only when you have freed all the message + you were given. +*/ + +int libetpan_folder_connect(struct mailengine * engine, + struct mailfolder * folder); + +void libetpan_folder_disconnect(struct mailengine * engine, + struct mailfolder * folder); + + +struct mailfolder * +libetpan_message_get_folder(struct mailengine * engine, + mailmessage * msg); + +struct mailstorage * +libetpan_message_get_storage(struct mailengine * engine, + mailmessage * msg); + + +/* + register a message +*/ + +int libetpan_message_register(struct mailengine * engine, + struct mailfolder * folder, + mailmessage * msg); + + +void libetpan_engine_debug(struct mailengine * engine, FILE * f); + +extern void * engine_app; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailfolder.h b/Sources/libetpan/include/mailfolder.h new file mode 100644 index 00000000..4ec60251 --- /dev/null +++ b/Sources/libetpan/include/mailfolder.h @@ -0,0 +1,80 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailfolder.h,v 1.4 2006/04/06 22:54:56 hoa Exp $ + */ + +#ifndef MAILFOLDER_H + +#define MAILFOLDER_H + +#include "mailstorage_types.h" + +LIBETPAN_EXPORT +int mailfolder_noop(struct mailfolder * folder); + +LIBETPAN_EXPORT +int mailfolder_check(struct mailfolder * folder); + +LIBETPAN_EXPORT +int mailfolder_expunge(struct mailfolder * folder); + +LIBETPAN_EXPORT +int mailfolder_status(struct mailfolder * folder, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +LIBETPAN_EXPORT +int mailfolder_append_message(struct mailfolder * folder, + char * message, size_t size); + +LIBETPAN_EXPORT +int mailfolder_append_message_flags(struct mailfolder * folder, + char * message, size_t size, struct mail_flags * flags); + +LIBETPAN_EXPORT +int mailfolder_get_messages_list(struct mailfolder * folder, + struct mailmessage_list ** result); + +LIBETPAN_EXPORT +int mailfolder_get_envelopes_list(struct mailfolder * folder, + struct mailmessage_list * result); + +LIBETPAN_EXPORT +int mailfolder_get_message(struct mailfolder * folder, + uint32_t num, mailmessage ** result); + +LIBETPAN_EXPORT +int mailfolder_get_message_by_uid(struct mailfolder * folder, + const char * uid, mailmessage ** result); + +#endif diff --git a/Sources/libetpan/include/mailimap.h b/Sources/libetpan/include/mailimap.h new file mode 100644 index 00000000..b2031780 --- /dev/null +++ b/Sources/libetpan/include/mailimap.h @@ -0,0 +1,935 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap.h,v 1.23 2011/03/29 23:59:05 hoa Exp $ + */ + +#ifndef MAILIMAP_H + +#define MAILIMAP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_types.h" +#include "mailimap_types_helper.h" +#include "mailimap_helper.h" + +#include "mailimap_socket.h" +#include "mailimap_ssl.h" + +#include "acl.h" +#include "annotatemore.h" +#include "uidplus.h" +#include "idle.h" +#include "quota.h" +#include "namespace.h" +#include "mailimap_id.h" +#include "enable.h" +#include "xlist.h" +#include "xgmlabels.h" +#include "xgmmsgid.h" +#include "xgmthrid.h" +#include "condstore.h" +#include "qresync.h" +#include "mailimap_sort.h" +#include "mailimap_compress.h" +#include "mailimap_oauth2.h" + +/* + mailimap_connect() + + This function will connect the IMAP session with the given stream. + + @param session the IMAP session + @param s stream to use + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + + note that on success, MAILIMAP_NO_ERROR_AUTHENTICATED or + MAILIMAP_NO_ERROR_NON_AUTHENTICATED is returned + + MAILIMAP_NO_ERROR_NON_AUTHENTICATED is returned when you need to + use mailimap_login() to authenticate, else + MAILIMAP_NO_ERROR_AUTHENTICATED is returned. +*/ + +LIBETPAN_EXPORT +int mailimap_connect(mailimap * session, mailstream * s); + +/* + mailimap_append() + + This function will append a given message to the given mailbox + by sending an APPEND command. + + @param session the IMAP session + @param mailbox name of the mailbox + @param flag_list flags of the message + @param date_time timestamp of the message + @param literal content of the message + @param literal_size size of the message + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_append(mailimap * session, const char * mailbox, + struct mailimap_flag_list * flag_list, + struct mailimap_date_time * date_time, + const char * literal, size_t literal_size); + +/* + mailimap_noop() + + This function will poll for an event on the server by + sending a NOOP command to the IMAP server + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR_XXX codes +*/ + +LIBETPAN_EXPORT +int mailimap_noop(mailimap * session); + +/* + mailimap_logout() + + This function will logout from an IMAP server by sending + a LOGOUT command. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_logout(mailimap * session); + +/* + mailimap_capability() + + This function will query an IMAP server for his capabilities + by sending a CAPABILITY command. + + @param session IMAP session + @param result The result of this command is a list of + capabilities and it is stored into (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +LIBETPAN_EXPORT +int mailimap_capability(mailimap * session, + struct mailimap_capability_data ** result); + +/* + mailimap_check() + + This function will request for a checkpoint of the mailbox by + sending a CHECK command. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +LIBETPAN_EXPORT +int mailimap_check(mailimap * session); + +/* + mailimap_close() + + This function will close the selected mailbox by sending + a CLOSE command. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +LIBETPAN_EXPORT +int mailimap_close(mailimap * session); + +/* + mailimap_expunge() + + This function will permanently remove from the selected mailbox + message that have the \Deleted flag set. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_expunge(mailimap * session); + +/* + mailimap_copy() + + This function will copy the given messages from the selected mailbox + to the given mailbox. + + @param session IMAP session + @param set This is a set of message numbers. + @param mb This is the destination mailbox. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +LIBETPAN_EXPORT +int mailimap_copy(mailimap * session, struct mailimap_set * set, + const char * mb); + +/* + mailimap_uid_copy() + + This function will copy the given messages from the selected mailbox + to the given mailbox. + + @param session IMAP session + @param set This is a set of message unique identifiers. + @param mb This is the destination mailbox. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +LIBETPAN_EXPORT +int mailimap_uid_copy(mailimap * session, + struct mailimap_set * set, const char * mb); + +/* + mailimap_move() + + This function will move the given messages from the selected mailbox + to the given mailbox. + + @param session IMAP session + @param set This is a set of message numbers. + @param mb This is the destination mailbox. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +LIBETPAN_EXPORT +int mailimap_move(mailimap * session, struct mailimap_set * set, + const char * mb); + +/* + mailimap_uid_move() + + This function will move the given messages from the selected mailbox + to the given mailbox. + + @param session IMAP session + @param set This is a set of message unique identifiers. + @param mb This is the destination mailbox. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +LIBETPAN_EXPORT +int mailimap_uid_move(mailimap * session, struct mailimap_set * set, + const char * mb); + +/* + mailimap_create() + + This function will create a mailbox. + + @param session IMAP session + @param mb This is the name of the mailbox to create. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_create(mailimap * session, const char * mb); + +/* + mailimap_delete() + + This function will delete a mailox. + + @param session IMAP session + @param mb This is the name of the mailbox to delete. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_delete(mailimap * session, const char * mb); + +/* + mailimap_examine() + + This function will select the mailbox for read-only operations. + + @param session IMAP session + @param mb This is the name of the mailbox to select. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_examine(mailimap * session, const char * mb); + +/* + mailimap_fetch() + + This function will retrieve data associated with the given message + numbers. + + @param session IMAP session + @param set set of message numbers + @param fetch_type type of information to be retrieved + @param result The result of this command is a clist + and it is stored into (* result). Each element of the clist is a + (struct mailimap_msg_att *). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int +mailimap_fetch(mailimap * session, struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, clist ** result); + +/* + mailimap_fetch() + + This function will retrieve data associated with the given message + numbers. + + @param session IMAP session + @param set set of message unique identifiers + @param fetch_type type of information to be retrieved + @param result The result of this command is a clist + and it is stored into (* result). Each element of the clist is a + (struct mailimap_msg_att *). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int +mailimap_uid_fetch(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, clist ** result); + +/* + mailimap_fetch_list_free() + + This function will free the result of a fetch command. + + @param fetch_list This is the clist containing + (struct mailimap_msg_att *) elements to free. +*/ + +LIBETPAN_EXPORT +void mailimap_fetch_list_free(clist * fetch_list); + +/* + mailimap_list() + + This function will return the list of the mailbox + available on the server. + + @param session IMAP session + @param mb This is the reference name that informs + of the level of hierarchy + @param list_mb mailbox name with possible wildcard + @param result This will store a clist of (struct mailimap_mailbox_list *) + in (* result) + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_list(mailimap * session, const char * mb, + const char * list_mb, clist ** result); + +/* + mailimap_login() + + This function will authenticate the client. + + @param session IMAP session + @param userid login of the user + @param password password of the user + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_login(mailimap * session, + const char * userid, const char * password); + +/* + mailimap_authenticate() + + This function will authenticate the client. + TODO : documentation +*/ + +LIBETPAN_EXPORT +int mailimap_authenticate(mailimap * session, const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); + +/* + mailimap_lsub() + + This function will return the list of the mailbox + that the client has subscribed to. + + @param session IMAP session + @param mb This is the reference name that informs + of the level of hierarchy + @param list_mb mailbox name with possible wildcard + @param result This will store a list of (struct mailimap_mailbox_list *) + in (* result) + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_lsub(mailimap * session, const char * mb, + const char * list_mb, clist ** result); + +/* + mailimap_list_result_free() + + This function will free the clist of (struct mailimap_mailbox_list *) + + @param list This is the clist to free. +*/ + +LIBETPAN_EXPORT +void mailimap_list_result_free(clist * list); + +/* + mailimap_rename() + + This function will change the name of a mailbox. + + @param session IMAP session + @param mb current name + @param new_name new name + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_rename(mailimap * session, + const char * mb, const char * new_name); + +/* + mailimap_search() + + All mails that match the given criteria will be returned + their numbers in the result list. + + @param session IMAP session + @param charset This indicates the charset of the strings that appears + in the searching criteria + @param key This is the searching criteria + @param result The result is a clist of (uint32_t *) and will be + stored in (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int +mailimap_search(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result); + +/* + mailimap_uid_search() + + + All mails that match the given criteria will be returned + their unique identifiers in the result list. + + @param session IMAP session + @param charset This indicates the charset of the strings that appears + in the searching criteria + @param key This is the searching criteria + @param result The result is a clist of (uint32_t *) and will be + stored in (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int +mailimap_uid_search(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result); + +/* + mailimap_search_literalplus() + + All mails that match the given criteria will be returned + their numbers in the result list. + LITERAL+ feature will be used to send strings. + + @param session IMAP session + @param charset This indicates the charset of the strings that appears + in the searching criteria + @param key This is the searching criteria + @param result The result is a clist of (uint32_t *) and will be + stored in (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT int mailimap_search_literalplus(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result); + +/* + mailimap_uid_search_literalplus() + + All mails that match the given criteria will be returned + their numbers in the result list. + LITERAL+ feature will be used to send strings. + + @param session IMAP session + @param charset This indicates the charset of the strings that appears + in the searching criteria + @param key This is the searching criteria + @param result The result is a clist of (uint32_t *) and will be + stored in (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT int mailimap_uid_search_literalplus(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result); + +/* + mailimap_search_result_free() + + This function will free the result of the a search. + + @param search_result This is a clist of (uint32_t *) returned + by mailimap_uid_search() or mailimap_search() +*/ + +LIBETPAN_EXPORT +void mailimap_search_result_free(clist * search_result); + +/* + mailimap_select() + + This function will select a given mailbox so that messages in the + mailbox can be accessed. + + @param session IMAP session + @param mb This is the name of the mailbox to select. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int +mailimap_select(mailimap * session, const char * mb); + +/* + mailimap_custom_command() + + @param session IMAP session + @param command Custom IMAP command to be send + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR_XXX codes + */ + +LIBETPAN_EXPORT +int mailimap_custom_command(mailimap * session, const char * command); + +/* + mailimap_status() + + This function will return informations about a given mailbox. + + @param session IMAP session + @param mb This is the name of the mailbox + @param status_att_list This is the list of mailbox information to return + @param result List of returned values + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int +mailimap_status(mailimap * session, const char * mb, + struct mailimap_status_att_list * status_att_list, + struct mailimap_mailbox_data_status ** result); + +/* + mailimap_uid_store() + + This function will alter the data associated with some messages + (flags of the messages). + + @param session IMAP session + @param set This is a list of message numbers. + @param store_att_flags This is the data to associate with the + given messages + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int +mailimap_store(mailimap * session, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags); + +/* + mailimap_uid_store() + + This function will alter the data associated with some messages + (flags of the messages). + + @param session IMAP session + @param set This is a list of message unique identifiers. + @param store_att_flags This is the data to associate with the + given messages + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int +mailimap_uid_store(mailimap * session, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags); + +/* + mailimap_subscribe() + + This function adds the specified mailbox name to the + server's set of "active" or "subscribed" mailboxes. + + @param session IMAP session + @param mb This is the name of the mailbox + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_subscribe(mailimap * session, const char * mb); + +/* + mailimap_unsubscribe() + + This function removes the specified mailbox name to the + server's set of "active" or "subscribed" mailboxes. + + @param session IMAP session + @param mb This is the name of the mailbox + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_unsubscribe(mailimap * session, const char * mb); + +/* + mailimap_starttls() + + This function starts change the mode of the connection to + switch to SSL connection. + It won't change the stream connection to SSL rightway. + See mailimap_socket_starttls() will switch the mailstream too. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR_XXX codes + */ + +LIBETPAN_EXPORT +int mailimap_starttls(mailimap * session); + +/* + mailimap_new() + + This function returns a new IMAP session. + + @param progr_rate When downloading messages, a function will be called + each time the amount of bytes downloaded reaches a multiple of this + value, this can be 0. + @param progr_fun This is the function to call to notify the progress, + this can be NULL. + + @return an IMAP session is returned. + */ + +LIBETPAN_EXPORT +mailimap * mailimap_new(size_t imap_progr_rate, + progress_function * imap_progr_fun); + +/* + mailimap_free() + + This function will free the data structures associated with + the IMAP session. + + @param session IMAP session + */ + +LIBETPAN_EXPORT +void mailimap_free(mailimap * session); + +/* + mailimap_send_current_tag() send current IMAP tag. See RFC 3501. + + @param session IMAP session + + @return MAILIMAP_NO_ERROR if the tag could be sent on the network. +*/ + +int mailimap_send_current_tag(mailimap * session); + +/* + mailimap_read_line() receive a line line buffer into memory. + + It needs to be called before starting to parse a response. + + @param session IMAP session + + @return MAILIMAP_NO_ERROR if a line could be buffered. +*/ + +char * mailimap_read_line(mailimap * session); + +/* + mailimap_parse_response() parse an IMAP response. + + @param session IMAP session + @param result an IMAP response data structure will be allocated and + filled with the parsed response. The pointer to the + allocated data structure will be stored in result. + + @return MAILIMAP_NO_ERROR if a line could be buffered. +*/ + +int mailimap_parse_response(mailimap * session, + struct mailimap_response ** result); + +/* + mailimap_set_progress_callback() set IMAP progression callbacks. + + @param session IMAP session + @param body_progr_fun set callback function for a progression of an imap + call that involves the download of a significant amount of data. + @param items_progr_fun set callback function for a progression of an imap + call that involves the download of information of several items. +*/ + +LIBETPAN_EXPORT +void mailimap_set_progress_callback(mailimap * session, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context); + +/* + mailimap_set_msg_att_handler() set a callback when a message information is + downloaded using FETCH. + + @param session IMAP session + @param handler set a callback function. This function will be called + during the download of the response each time a new message information + has just been downloaded. + @param context parameter that's passed to the callback function. +*/ + +LIBETPAN_EXPORT +void mailimap_set_msg_att_handler(mailimap * session, + mailimap_msg_att_handler * handler, + void * context); + +/* + mailimap_set_msg_body_handler() set a callback when a message body is + downloaded using FETCH. + + @param session IMAP session + @param handler set a callback function. This function will be called + during the download of the response to process the message body + as data become available from the network. + This can be used, for example, for downloading big messages (or it attachments) + to the file without keeping it in memory. + @param context parameter that's passed to the callback function. +*/ + +LIBETPAN_EXPORT +void mailimap_set_msg_body_handler(mailimap * session, + mailimap_msg_body_handler * handler, + void * context); + +/* + mailimap_set_timeout() set the network timeout of the IMAP session. + + @param session IMAP session + @param timeout value of the timeout in seconds. +*/ + +LIBETPAN_EXPORT +void mailimap_set_timeout(mailimap * session, time_t timeout);; + +/* + mailimap_get_timeout() get the network timeout of the IMAP session. + + @param session IMAP session + @return the value of the timeout in seconds. +*/ + +LIBETPAN_EXPORT +time_t mailimap_get_timeout(mailimap * session); + +/* + mailimap_set_logger() get the network timeout of the IMAP session. + + @param session IMAP session + @param logger logger function. See mailstream_types.h to know possible log_type values. + str is the log, data received or data sent. + @param logger_context parameter that is passed to the logger function. + @return the value of the timeout in seconds. +*/ + +LIBETPAN_EXPORT +void mailimap_set_logger(mailimap * session, void (* logger)(mailimap * session, int log_type, + const char * str, size_t size, void * context), void * logger_context); + +#ifndef LIBETPAN_HAS_MAILIMAP_163_WORKAROUND + #define LIBETPAN_HAS_MAILIMAP_163_WORKAROUND 1 +#endif + +LIBETPAN_EXPORT +int mailimap_is_163_workaround_enabled(mailimap * session); + +LIBETPAN_EXPORT +void mailimap_set_163_workaround_enabled(mailimap * session, int enabled); + +#ifndef LIBETPAN_HAS_MAILIMAP_RAMBLER_WORKAROUND + #define LIBETPAN_HAS_MAILIMAP_RAMBLER_WORKAROUND 1 +#endif + +/* + Enable workaround for Rambler IMAP server. + + Occasionally, for large attachments (~20MB) Rambler returns wrong length of the literal. + Since this workaround is not completely free from false positives, by default is is off. + + It is proposed to enable it only during downloading large attachments from Rambler: + + @code + if (encoding is (base64 or uuencode) and server is rambler.ru) { + mailimap_set_rambler_workaround_enabled(imap, 1); + … fetch part ... + mailimap_set_rambler_workaround_enabled(imap, 0); + } + @endcode +*/ + +LIBETPAN_EXPORT +int mailimap_is_rambler_workaround_enabled(mailimap * session); + +LIBETPAN_EXPORT +void mailimap_set_rambler_workaround_enabled(mailimap * session, int enabled); + +#ifndef LIBETPAN_HAS_MAILIMAP_QIP_WORKAROUND +#define LIBETPAN_HAS_MAILIMAP_QIP_WORKAROUND 1 +#endif + +/* + Enable workaround for QIP IMAP server. + + QIP returns invalid (?) response for storeFlags operation: + C: A999 UID STORE 123 +FLAGS.SILENT (\Seen) + S: * 6 FETCH () + S: A999 OK STORE completed + + Enabling this workaround allows successfully parse such responses. +*/ + +LIBETPAN_EXPORT +int mailimap_is_qip_workaround_enabled(mailimap * session); + +LIBETPAN_EXPORT +void mailimap_set_qip_workaround_enabled(mailimap * session, int enabled); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailimap_compress.h b/Sources/libetpan/include/mailimap_compress.h new file mode 100644 index 00000000..0656c501 --- /dev/null +++ b/Sources/libetpan/include/mailimap_compress.h @@ -0,0 +1,68 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef MAILIMAP_COMPRESS_H + +#define MAILIMAP_COMPRESS_H + +#include "mailimap_types.h" + +/* + mailimap_compress() + + This function will request IMAP compression by sending + a COMPRESS command. It will also change the stream connection to + a compressed stream (mailstream_compress). + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +LIBETPAN_EXPORT +int mailimap_compress(mailimap * session); + +/* + mailimap_has_compress_deflate() + + This function will return 1 if compression deflate is available + on the server else it will return 0. + + @param session IMAP session + + @return returns 1 if compression deflate is available on the server. + */ + +LIBETPAN_EXPORT +int mailimap_has_compress_deflate(mailimap * session); + +#endif diff --git a/Sources/libetpan/include/mailimap_extension.h b/Sources/libetpan/include/mailimap_extension.h new file mode 100644 index 00000000..80c0deb4 --- /dev/null +++ b/Sources/libetpan/include/mailimap_extension.h @@ -0,0 +1,111 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef MAILIMAP_EXTENSION_H + +#define MAILIMAP_EXTENSION_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_types.h" +#include "mailimap_extension_types.h" + +/* + you add a (static) mailimap_extension_api to the list of extensions + by calling register. making the list of + extensions contain all extensions statically may prove detrimental + to speed if you have many extensions and don't need any of them. + as unregistering single extensions does not really make any sense, + it's not provided - just an unregister_all which is primarily used + to free the clist on exit. +*/ + +LIBETPAN_EXPORT +int +mailimap_extension_register(struct mailimap_extension_api * extension); + +LIBETPAN_EXPORT +void +mailimap_extension_unregister_all(void); + +/* + this is called as the main parser wrapper for all extensions. + it gos through the list of registered extensions and calls + all of the extensions' parsers looking for one that doesn't + return MAILIMAP_ERROR_PARSE. +*/ +LIBETPAN_EXPORT +int +mailimap_extension_data_parse(int calling_parser, + mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +LIBETPAN_EXPORT +struct mailimap_extension_data * +mailimap_extension_data_new(struct mailimap_extension_api * extension, + int type, void * data); + +/* + wrapper for the extensions' free. calls the correct extension's free + based on data->extension. +*/ +LIBETPAN_EXPORT +void +mailimap_extension_data_free(struct + mailimap_extension_data * data); + +/* + stores the ext_data in the session (only needed for extensions + that embed directly into response-data). +*/ +void mailimap_extension_data_store(mailimap * session, + struct mailimap_extension_data ** ext_data); + +/* + return 1 if the extension of the given name is supported. + the name is searched in the capabilities. +*/ + +LIBETPAN_EXPORT +int mailimap_has_extension(mailimap * session, const char * extension_name); + +LIBETPAN_EXPORT +int mailimap_has_authentication(mailimap * session, const char * authentication_name); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailimap_extension_types.h b/Sources/libetpan/include/mailimap_extension_types.h new file mode 100644 index 00000000..cee33bc8 --- /dev/null +++ b/Sources/libetpan/include/mailimap_extension_types.h @@ -0,0 +1,115 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILIMAP_EXTENSION_TYPES_H + +#define MAILIMAP_EXTENSION_TYPES_H + +#include "mailstream.h" +#include "mailimap_types.h" + +struct mailimap_extension_data; + +/* + this is the list of known extensions with the purpose to + get integer identifers for the extensions. +*/ + +enum { + MAILIMAP_EXTENSION_ANNOTATEMORE, /* the annotatemore-draft */ + MAILIMAP_EXTENSION_ACL, /* the acl capability */ + MAILIMAP_EXTENSION_UIDPLUS, /* UIDPLUS */ + MAILIMAP_EXTENSION_QUOTA, /* quota */ + MAILIMAP_EXTENSION_NAMESPACE, /* namespace */ + MAILIMAP_EXTENSION_XLIST, /* XLIST (Gmail and Zimbra have this) */ + MAILIMAP_EXTENSION_XGMLABELS, /* X-GM-LABELS (Gmail) */ + MAILIMAP_EXTENSION_XGMMSGID, /* X-GM-MSGID (Gmail) */ + MAILIMAP_EXTENSION_XGMTHRID, /* X-GM-THRID (Gmail) */ + MAILIMAP_EXTENSION_ID, /* ID */ + MAILIMAP_EXTENSION_ENABLE, /* ENABLE */ + MAILIMAP_EXTENSION_CONDSTORE, /* CONDSTORE */ + MAILIMAP_EXTENSION_QRESYNC, /* QRESYNC */ + MAILIMAP_EXTENSION_SORT /* SORT */ +}; + + +/* + this is a list of extended parser functions. The extended parser + passes its identifier to the extension parser. +*/ + +enum { + MAILIMAP_EXTENDED_PARSER_RESPONSE_DATA, + MAILIMAP_EXTENDED_PARSER_RESP_TEXT_CODE, + MAILIMAP_EXTENDED_PARSER_MAILBOX_DATA, + MAILIMAP_EXTENDED_PARSER_FETCH_DATA, + MAILIMAP_EXTENDED_PARSER_STATUS_ATT +}; + +/* + this is the extension interface. each extension consists + of a initial parser and an initial free. the parser is + passed the calling parser's identifier. based on this + identifier the initial parser can then decide which + actual parser to call. free has mailimap_extension_data + as parameter. if you look at mailimap_extension_data + you'll see that it contains "type" as one of its + elements. thus an extension's initial free can call + the correct actual free to free its data. +*/ +struct mailimap_extension_api { + char * ext_name; + int ext_id; /* use -1 if this is an extension outside libetpan */ + + int (* ext_parser)(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun); + + void (* ext_free)(struct mailimap_extension_data * ext_data); +}; + +/* + mailimap_extension_data is a wrapper for values parsed by extensions + + - extension is an identifier for the extension that parsed the value. + + - type is an identifier for the real type of the data. + + - data is a pointer to the real data. +*/ +struct mailimap_extension_data { + struct mailimap_extension_api * ext_extension; + int ext_type; + void * ext_data; +}; + +#endif diff --git a/Sources/libetpan/include/mailimap_helper.h b/Sources/libetpan/include/mailimap_helper.h new file mode 100644 index 00000000..e4f15f16 --- /dev/null +++ b/Sources/libetpan/include/mailimap_helper.h @@ -0,0 +1,71 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_helper.h,v 1.12 2006/06/07 15:10:01 smarinier Exp $ + */ + +#ifndef MAILIMAP_HELPER_H + +#define MAILIMAP_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_types.h" + +LIBETPAN_EXPORT +int mailimap_fetch_rfc822(mailimap * session, + uint32_t msgid, char ** result); + +LIBETPAN_EXPORT +int mailimap_fetch_rfc822_header(mailimap * session, + uint32_t msgid, char ** result); + +LIBETPAN_EXPORT +int mailimap_fetch_envelope(mailimap * session, + uint32_t first, uint32_t last, + clist ** result); + +LIBETPAN_EXPORT +int mailimap_append_simple(mailimap * session, const char * mailbox, + const char * content, size_t size); + +LIBETPAN_EXPORT +int mailimap_login_simple(mailimap * session, + const char * userid, const char * password); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailimap_id.h b/Sources/libetpan/include/mailimap_id.h new file mode 100644 index 00000000..ef4c773e --- /dev/null +++ b/Sources/libetpan/include/mailimap_id.h @@ -0,0 +1,64 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2011 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef MAILIMAP_ID_H + +#define MAILIMAP_ID_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "libetpan-config.h" +#include "mailimap_extension.h" +#include "mailimap_id_types.h" + +LIBETPAN_EXPORT extern struct mailimap_extension_api mailimap_extension_id; + +LIBETPAN_EXPORT +int mailimap_has_id(mailimap * session); + +LIBETPAN_EXPORT +int mailimap_id(mailimap * session, struct mailimap_id_params_list * client_identification, + struct mailimap_id_params_list ** result); + +/* Helpers */ + +/* result must be freed */ +LIBETPAN_EXPORT +int mailimap_id_basic(mailimap * session, const char * name, const char * version, + char ** p_server_name, char ** p_server_version); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailimap_id_parser.h b/Sources/libetpan/include/mailimap_id_parser.h new file mode 100644 index 00000000..c8036b17 --- /dev/null +++ b/Sources/libetpan/include/mailimap_id_parser.h @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILIMAP_ID_PARSER_H + +#define MAILIMAP_ID_PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "libetpan-config.h" +#include "mailimap_extension.h" +#include "mailimap_id_types.h" + +int mailimap_id_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailimap_id_sender.h b/Sources/libetpan/include/mailimap_id_sender.h new file mode 100644 index 00000000..bd3a6dc3 --- /dev/null +++ b/Sources/libetpan/include/mailimap_id_sender.h @@ -0,0 +1,50 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILIMAP_ID_SENDER_H + +#define MAILIMAP_ID_SENDER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "libetpan-config.h" +#include "mailimap_extension.h" +#include "mailimap_id_types.h" + +LIBETPAN_EXPORT +int mailimap_id_send(mailstream * fd, struct mailimap_id_params_list * client_identification); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailimap_id_types.h b/Sources/libetpan/include/mailimap_id_types.h new file mode 100644 index 00000000..2d747faf --- /dev/null +++ b/Sources/libetpan/include/mailimap_id_types.h @@ -0,0 +1,72 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILIMAP_ID_TYPES_H + +#define MAILIMAP_ID_TYPES_H + +#include "clist.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct mailimap_id_params_list { + clist * /* struct mailimap_id_param */ idpa_list; +}; + +LIBETPAN_EXPORT +struct mailimap_id_params_list * mailimap_id_params_list_new(clist * items); + +LIBETPAN_EXPORT +void mailimap_id_params_list_free(struct mailimap_id_params_list * list); + +struct mailimap_id_param { + char * idpa_name; + char * idpa_value; +}; + +LIBETPAN_EXPORT +struct mailimap_id_param * mailimap_id_param_new(char * name, char * value); + +LIBETPAN_EXPORT +void mailimap_id_param_free(struct mailimap_id_param * param); + +LIBETPAN_EXPORT +struct mailimap_id_params_list * mailimap_id_params_list_new_empty(void); + +LIBETPAN_EXPORT +int mailimap_id_params_list_add_name_value(struct mailimap_id_params_list * list, char * name, char * value); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailimap_keywords.h b/Sources/libetpan/include/mailimap_keywords.h new file mode 100644 index 00000000..d1350628 --- /dev/null +++ b/Sources/libetpan/include/mailimap_keywords.h @@ -0,0 +1,107 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_keywords.h,v 1.9 2008/02/20 22:15:51 hoa Exp $ + */ + +#ifndef MAILIMAP_COMMON_H + +#define MAILIMAP_COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailstream.h" + + +/* tools */ + +int mailimap_char_parse(mailstream * fd, MMAPString * buffer, + size_t * indx, char token); + +int mailimap_space_parse(mailstream * fd, MMAPString * buffer, + size_t * indx); + +/* tokens */ + +int mailimap_token_case_insensitive_parse(mailstream * fd, + MMAPString * buffer, + size_t * indx, + const char * token); + +int mailimap_status_att_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * indx); +const char * mailimap_status_att_get_token_str(int indx); + + +int mailimap_month_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * indx); +const char * mailimap_month_get_token_str(int indx); + + +int mailimap_flag_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * indx); + +const char * mailimap_flag_get_token_str(int indx); + +int mailimap_encoding_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * indx); + +int mailimap_mbx_list_sflag_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * indx); + +int mailimap_media_basic_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * indx); + +int mailimap_resp_cond_state_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * indx); + +int mailimap_resp_text_code_1_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * indx); + +int mailimap_resp_text_code_2_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * indx); + +int mailimap_section_msgtext_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * indx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailimap_oauth2.h b/Sources/libetpan/include/mailimap_oauth2.h new file mode 100644 index 00000000..f2e28e34 --- /dev/null +++ b/Sources/libetpan/include/mailimap_oauth2.h @@ -0,0 +1,102 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILIMAP_OAUTH2_H + +#define MAILIMAP_OAUTH2_H + +#include "mailimap_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mailimap_oauth2_authenticate() + Authenticates the client using using an oauth2 token. + To gather a deeper understanding of the OAuth2 aunthentication + process refer to: https://developers.google.com/gmail/xoauth2_protocol + For a quick start you may follow this brief set of steps: + 1. Set up a profile for your app in the Google + API Console: https://code.google.com/apis/console + 2. With your recently obtained client_id and secret + load the following URL (everything goes ina single line): + https://accounts.google.com/o/oauth2/auth?client_id=[YOUR_CLIENT_ID]& + redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob& + response_type=code&scope=https%3A%2F%2Fmail.google.com%2F%20email& + &access_type=offline + 3. The user most follow instructions to authorize application access + to Gmail. + 4. After the user hits the "Accept" button it will be redirected to another + page where the access token will be issued. + 5. Now from the app we need and authorization token, to get one we issue a POST request + the following URL: https://accounts.google.com/o/oauth2/token using these parameters: + client_id: This is the client id we got from step 1 + client_secret: Client secret as we got it from step 1 + code: This is the code we received in step 4 + redirect_uri: This is a redirect URI where the access token will be sent, for non + web applications this is usually urn:ietf:wg:oauth:2.0:oob (as we got from step 1) + grant_type: Always use the authorization_code parameter to retrieve an access and refresh tokens + 6. After step 5 completes we receive a JSON object similar to: + { + "access_token":"1/fFAGRNJru1FTz70BzhT3Zg", + "refresh_token":"1/fFAGRNJrufoiWEGIWEFJFJF", + "expires_in":3920, + "token_type":"Bearer" + } + The above output gives us the access_token, now we need to also retrieve the user's e-mail, + to do that we need to perform an HTTP GET request to Google's UserInfo API using this URL: + https://www.googleapis.com/oauth2/v1/userinfo?access_token=[YOUR_ACCESS_TOKEN] + this will return the following JSON output: + { + "id": "00000000000002222220000000", + "email": "email@example.com", + "verified_email": true + } + @param session IMAP session + @param auth_user Authentication user (tipically an e-mail address, depends on server) + @param access_token OAuth2 access token + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +LIBETPAN_EXPORT +int mailimap_oauth2_authenticate(mailimap * session, const char * auth_user, + const char * access_token); + +LIBETPAN_EXPORT +int mailimap_has_xoauth2(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Sources/libetpan/include/mailimap_parser.h b/Sources/libetpan/include/mailimap_parser.h new file mode 100644 index 00000000..fa4fbc56 --- /dev/null +++ b/Sources/libetpan/include/mailimap_parser.h @@ -0,0 +1,221 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_parser.h,v 1.17 2011/03/30 13:29:49 hoa Exp $ + */ + +#ifndef MAILIMAP_PARSER_H + +#define MAILIMAP_PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_types.h" + +int mailimap_greeting_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_greeting ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_response_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_response ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_response_parse_with_context(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_response ** result, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context); + +int +mailimap_continue_req_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_continue_req ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_response_data_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_response_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +typedef int mailimap_struct_parser(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, void * result, + size_t progr_rate, + progress_function * progr_fun); + +typedef void mailimap_struct_destructor(void * result); + +int +mailimap_mailbox_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); +int +mailimap_mailbox_list_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_mailbox_list ** result, + size_t progr_rate, + progress_function * progr_fun); + +int mailimap_nstring_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_string_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_struct_spaced_list_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, clist ** result, + mailimap_struct_parser * parser, + mailimap_struct_destructor * destructor, + size_t progr_rate, + progress_function * progr_fun); + +int mailimap_oparenth_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx); + +int mailimap_cparenth_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx); + +int mailimap_atom_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_astring_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + char ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_number_parse(mailstream * fd, MMAPString * buffer, + size_t * indx, uint32_t * result); + +int +mailimap_nz_number_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, uint32_t * result); + +int +mailimap_struct_list_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, clist ** result, + char symbol, + mailimap_struct_parser * parser, + mailimap_struct_destructor * destructor, + size_t progr_rate, + progress_function * progr_fun); + +int mailimap_uniqueid_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, uint32_t * result); + +int mailimap_colon_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx); + +int mailimap_dquote_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx); + +int +mailimap_quoted_char_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char * result); + +int mailimap_nil_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx); + +int +mailimap_struct_multiple_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, clist ** result, + mailimap_struct_parser * parser, + mailimap_struct_destructor * destructor, + size_t progr_rate, + progress_function * progr_fun); + +int mailimap_capability_data_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_capability_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +int mailimap_capability_list_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + clist ** result, + size_t progr_rate, + progress_function * progr_fun); + +int mailimap_status_att_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, int * result); + +int mailimap_nz_number_alloc_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + uint32_t ** result, + size_t progr_rate, + progress_function * progr_fun); + +int mailimap_mod_sequence_value_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, uint64_t * result); + +int mailimap_uint64_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, uint64_t * result); + +int mailimap_set_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, struct mailimap_set ** result); + +LIBETPAN_EXPORT +int mailimap_hack_date_time_parse(char * str, + struct mailimap_date_time ** result, + size_t progr_rate, + progress_function * progr_fun); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailimap_print.h b/Sources/libetpan/include/mailimap_print.h new file mode 100644 index 00000000..050322ed --- /dev/null +++ b/Sources/libetpan/include/mailimap_print.h @@ -0,0 +1,54 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_print.h,v 1.6 2004/11/21 21:53:36 hoa Exp $ + */ + +#ifndef MAILIMAP_PRINT_H + +#define MAILIMAP_PRINT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_types.h" + +void mailimap_response_print(struct mailimap_response * resp); + +void mailimap_greeting_print(struct mailimap_greeting * greeting); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailimap_sender.h b/Sources/libetpan/include/mailimap_sender.h new file mode 100644 index 00000000..4f44f32f --- /dev/null +++ b/Sources/libetpan/include/mailimap_sender.h @@ -0,0 +1,223 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_sender.h,v 1.15 2010/11/28 17:01:26 hoa Exp $ + */ + +#ifndef MAILIMAP_SENDER_H + +#define MAILIMAP_SENDER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_types.h" + +int mailimap_append_send(mailstream * fd, + const char * mailbox, + struct mailimap_flag_list * flag_list, + struct mailimap_date_time * date_time, + size_t literal_size); + +int mailimap_authenticate_send(mailstream * fd, + const char * auth_type); + +int mailimap_authenticate_resp_send(mailstream * fd, + const char * base64); + +int mailimap_noop_send(mailstream * fd); + +int mailimap_logout_send(mailstream * fd); + +int mailimap_capability_send(mailstream * fd); + +int mailimap_check_send(mailstream * fd); + +int mailimap_close_send(mailstream * fd); + +int mailimap_expunge_send(mailstream * fd); + +int mailimap_copy_send(mailstream * fd, + struct mailimap_set * set, + const char * mb); + +int mailimap_uid_copy_send(mailstream * fd, + struct mailimap_set * set, + const char * mb); + +int mailimap_move_send(mailstream * fd, + struct mailimap_set * set, + const char * mb); + +int mailimap_uid_move_send(mailstream * fd, + struct mailimap_set * set, + const char * mb); + +int mailimap_create_send(mailstream * fd, + const char * mb); + + +int mailimap_delete_send(mailstream * fd, const char * mb); + +int mailimap_examine_send(mailstream * fd, const char * mb, int condstore); + +int +mailimap_fetch_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type); + +int +mailimap_uid_fetch_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type); + +int mailimap_list_send(mailstream * fd, + const char * mb, const char * list_mb); + +int mailimap_login_send(mailstream * fd, + const char * userid, const char * password); + +int mailimap_lsub_send(mailstream * fd, + const char * mb, const char * list_mb); + +int mailimap_rename_send(mailstream * fd, const char * mb, + const char * new_name); + +int +mailimap_search_send(mailstream * fd, const char * charset, + struct mailimap_search_key * key); + +int +mailimap_uid_search_send(mailstream * fd, const char * charset, + struct mailimap_search_key * key); + +int mailimap_search_literalplus_send(mailstream * fd, const char * charset, + struct mailimap_search_key * key); + +int mailimap_uid_search_literalplus_send(mailstream * fd, const char * charset, + struct mailimap_search_key * key); + +int mailimap_search_key_send(mailstream * fd, + struct mailimap_search_key * key); + +int mailimap_search_key_literalplus_send(mailstream * fd, + struct mailimap_search_key * key); + +int +mailimap_select_send(mailstream * fd, const char * mb, int condstore); + +int +mailimap_status_send(mailstream * fd, const char * mb, + struct mailimap_status_att_list * status_att_list); + +int + mailimap_store_send(mailstream * fd, + struct mailimap_set * set, int use_unchangedsince, uint64_t mod_sequence_valzer, + struct mailimap_store_att_flags * store_att_flags); + +int + mailimap_uid_store_send(mailstream * fd, + struct mailimap_set * set, int use_unchangedsince, uint64_t mod_sequence_valzer, + struct mailimap_store_att_flags * store_att_flags); + +int mailimap_subscribe_send(mailstream * fd, const char * mb); + + +int mailimap_tag_send(mailstream * fd, const char * tag); + +int mailimap_unsubscribe_send(mailstream * fd, + const char * mb); + +int mailimap_crlf_send(mailstream * fd); + +int mailimap_space_send(mailstream * fd); + +int +mailimap_literal_send(mailstream * fd, const char * literal, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_literal_count_send(mailstream * fd, size_t count); + +int +mailimap_literal_data_send(mailstream * fd, const char * literal, size_t len, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_literal_data_send_with_context(mailstream * fd, const char * literal, size_t len, + mailprogress_function * progr_fun, + void * context); + +int mailimap_starttls_send(mailstream * fd); + +int mailimap_token_send(mailstream * fd, const char * atom); + +int mailimap_quoted_send(mailstream * fd, const char * quoted); + +typedef int mailimap_struct_sender(mailstream * fd, void * data); + +int +mailimap_struct_spaced_list_send(mailstream * fd, clist * list, + mailimap_struct_sender * sender); + +int +mailimap_list_mailbox_send(mailstream * fd, const char * pattern); + +int mailimap_char_send(mailstream * fd, char ch); + +int mailimap_mailbox_send(mailstream * fd, const char * mb); + +int mailimap_astring_send(mailstream * fd, const char * astring); + +int mailimap_set_send(mailstream * fd, + struct mailimap_set * set); + +int mailimap_oparenth_send(mailstream * fd); + +int mailimap_cparenth_send(mailstream * fd); + +int mailimap_mod_sequence_value_send(mailstream * fd, uint64_t modseq); + +int mailimap_uint64_send(mailstream * fd, uint64_t number); + +int mailimap_number_send(mailstream * fd, uint32_t number); + +int mailimap_send_custom_command(mailstream *fd, const char * command); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailimap_socket.h b/Sources/libetpan/include/mailimap_socket.h new file mode 100644 index 00000000..2e8639fd --- /dev/null +++ b/Sources/libetpan/include/mailimap_socket.h @@ -0,0 +1,67 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_socket.h,v 1.16 2006/12/26 13:13:24 hoa Exp $ + */ + +#ifndef MAILIMAP_SOCKET_H + +#define MAILIMAP_SOCKET_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_INTTYPES_H +# include +#endif + +#include "mailimap_types.h" + +LIBETPAN_EXPORT +int mailimap_socket_connect_voip(mailimap * f, const char * server, uint16_t port, int voip_enabled); + +LIBETPAN_EXPORT +int mailimap_socket_connect(mailimap * f, const char * server, uint16_t port); + +LIBETPAN_EXPORT +int mailimap_socket_starttls(mailimap * f); + +LIBETPAN_EXPORT +int mailimap_socket_starttls_with_callback(mailimap * f, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailimap_sort.h b/Sources/libetpan/include/mailimap_sort.h new file mode 100644 index 00000000..a6770f36 --- /dev/null +++ b/Sources/libetpan/include/mailimap_sort.h @@ -0,0 +1,102 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2011 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef libetpan_mailimap_sort_h +#define libetpan_mailimap_sort_h + +#ifdef __cplusplus +extern "C" { +#endif + +#include "libetpan-config.h" +#include "mailimap_extension.h" +#include "mailimap_sort_types.h" + + LIBETPAN_EXPORT + extern struct mailimap_extension_api mailimap_extension_sort; + + + /* + mailimap_sort() + + All mails that match the given criteria will be returned + their numbers sorted by the given sorting criteria in the result list. + + @param session IMAP session + @param charset This indicates the charset of the strings that appears + in the searching criteria + @param key This is the searching criteria + @param result The result is a clist of (uint32_t *) and will be + stored in (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + + LIBETPAN_EXPORT + int + mailimap_sort(mailimap * session, const char * charset, + struct mailimap_sort_key * key, struct mailimap_search_key * searchkey, + clist ** result); + + /* + mailimap_uid_sort() + + + All mails that match the given criteria will be returned + their unique identifiers sorted by the given sorting criteria in the result list. + + @param session IMAP session + @param charset This indicates the charset of the strings that appears + in the searching criteria + @param key This is the sorting criteria + @param searchkey This is the searching criteria + @param result The result is a clist of (uint32_t *) and will be + stored in (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + + LIBETPAN_EXPORT + int + mailimap_uid_sort(mailimap * session, const char * charset, + struct mailimap_sort_key * key, struct mailimap_search_key * searchkey, + clist ** result); + + LIBETPAN_EXPORT + void mailimap_sort_result_free(clist * search_result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailimap_sort_types.h b/Sources/libetpan/include/mailimap_sort_types.h new file mode 100644 index 00000000..f61305d9 --- /dev/null +++ b/Sources/libetpan/include/mailimap_sort_types.h @@ -0,0 +1,121 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2011 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef MAILIMAP_SORT_TYPES_H + +#define MAILIMAP_SORT_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef WIN32 +#include "inttypes.h" +#endif + +#include "mailimap_types.h" + + /* this is the condition of the SORT operation */ + + enum { + MAILIMAP_SORT_KEY_ARRIVAL, + MAILIMAP_SORT_KEY_CC, + MAILIMAP_SORT_KEY_DATE, + MAILIMAP_SORT_KEY_FROM, + MAILIMAP_SORT_KEY_SIZE, + MAILIMAP_SORT_KEY_SUBJECT, + MAILIMAP_SORT_KEY_TO, + MAILIMAP_SORT_KEY_MULTIPLE + }; + + struct mailimap_sort_key { + int sortk_type; + int sortk_is_reverse; + clist * sortk_multiple; /* list of (struct mailimap_sort_key *) */ + }; + + + LIBETPAN_EXPORT + struct mailimap_sort_key * + mailimap_sort_key_new(int sortk_type, + int is_reverse, + clist * sortk_multiple); + + LIBETPAN_EXPORT + void mailimap_sort_key_free(struct mailimap_sort_key * key); + + LIBETPAN_EXPORT + struct mailimap_sort_key * + mailimap_sort_key_new_arrival(int is_reverse); + + LIBETPAN_EXPORT + struct mailimap_sort_key * + mailimap_sort_key_new_cc(int is_reverse); + + LIBETPAN_EXPORT + struct mailimap_sort_key * + mailimap_sort_key_new_date(int is_reverse); + + LIBETPAN_EXPORT + struct mailimap_sort_key * + mailimap_sort_key_new_from(int is_reverse); + + LIBETPAN_EXPORT + struct mailimap_sort_key * + mailimap_sort_key_new_size(int is_reverse); + + LIBETPAN_EXPORT + struct mailimap_sort_key * + mailimap_sort_key_new_subject(int is_reverse); + + LIBETPAN_EXPORT + struct mailimap_sort_key * + mailimap_sort_key_new_to(int is_reverse); + + LIBETPAN_EXPORT + struct mailimap_sort_key * + mailimap_sort_key_new_multiple(clist * keys); + + LIBETPAN_EXPORT + struct mailimap_sort_key * + mailimap_sort_key_new_multiple_empty(void); + + LIBETPAN_EXPORT + int + mailimap_sort_key_multiple_add(struct mailimap_sort_key * keys, + struct mailimap_sort_key * key_item); + + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/Sources/libetpan/include/mailimap_ssl.h b/Sources/libetpan/include/mailimap_ssl.h new file mode 100644 index 00000000..a8a84ec1 --- /dev/null +++ b/Sources/libetpan/include/mailimap_ssl.h @@ -0,0 +1,68 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_ssl.h,v 1.16 2006/12/26 13:13:24 hoa Exp $ + */ + +#ifndef MAILIMAP_SSL_H + +#define MAILIMAP_SSL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_INTTYPES_H +# include +#endif + +#include "mailimap_types.h" + +LIBETPAN_EXPORT +int mailimap_ssl_connect(mailimap * f, const char * server, uint16_t port); + +LIBETPAN_EXPORT +int mailimap_ssl_connect_voip(mailimap * f, const char * server, uint16_t port, int voip_enabled); + +LIBETPAN_EXPORT +int mailimap_ssl_connect_with_callback(mailimap * f, const char * server, uint16_t port, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +LIBETPAN_EXPORT +int mailimap_ssl_connect_voip_with_callback(mailimap * f, const char * server, uint16_t port, int voip_enabled, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailimap_types.h b/Sources/libetpan/include/mailimap_types.h new file mode 100644 index 00000000..abb60916 --- /dev/null +++ b/Sources/libetpan/include/mailimap_types.h @@ -0,0 +1,3611 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_types.h,v 1.34 2011/01/06 00:09:52 hoa Exp $ + */ + +/* + IMAP4rev1 grammar + + address = "(" addr-name SP addr-adl SP addr-mailbox SP + addr-host ")" + + addr-adl = nstring + ; Holds route from [RFC-822] route-addr if + ; non-NIL + + addr-host = nstring + ; NIL indicates [RFC-822] group syntax. + ; Otherwise, holds [RFC-822] domain name + + addr-mailbox = nstring + ; NIL indicates end of [RFC-822] group; if + ; non-NIL and addr-host is NIL, holds + ; [RFC-822] group name. + ; Otherwise, holds [RFC-822] local-part + ; after removing [RFC-822] quoting + + + + addr-name = nstring + ; If non-NIL, holds phrase from [RFC-822] + ; mailbox after removing [RFC-822] quoting + + append = "APPEND" SP mailbox [SP flag-list] [SP date-time] SP + literal + + astring = 1*ASTRING-CHAR / string + + ASTRING-CHAR = ATOM-CHAR / resp-specials + + atom = 1*ATOM-CHAR + + ATOM-CHAR = + + atom-specials = "(" / ")" / "{" / SP / CTL / list-wildcards / + quoted-specials / resp-specials + + authenticate = "AUTHENTICATE" SP auth-type *(CRLF base64) + + auth-type = atom + ; Defined by [SASL] + + base64 = *(4base64-char) [base64-terminal] + + base64-char = ALPHA / DIGIT / "+" / "/" + ; Case-sensitive + + base64-terminal = (2base64-char "==") / (3base64-char "=") + + body = "(" (body-type-1part / body-type-mpart) ")" + + body-extension = nstring / number / + "(" body-extension *(SP body-extension) ")" + ; Future expansion. Client implementations + ; MUST accept body-extension fields. Server + ; implementations MUST NOT generate + ; body-extension fields except as defined by + ; future standard or standards-track + ; revisions of this specification. + + body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] + ; MUST NOT be returned on non-extensible + ; "BODY" fetch + + + body-ext-mpart = body-fld-param [SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] + ; MUST NOT be returned on non-extensible + ; "BODY" fetch + + body-fields = body-fld-param SP body-fld-id SP body-fld-desc SP + body-fld-enc SP body-fld-octets + + body-fld-desc = nstring + + body-fld-dsp = "(" string SP body-fld-param ")" / nil + + body-fld-enc = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/ + "QUOTED-PRINTABLE") DQUOTE) / string + + body-fld-id = nstring + + body-fld-lang = nstring / "(" string *(SP string) ")" + + body-fld-lines = number + + body-fld-md5 = nstring + + body-fld-octets = number + + body-fld-param = "(" string SP string *(SP string SP string) ")" / nil + + body-type-1part = (body-type-basic / body-type-msg / body-type-text) + [SP body-ext-1part] + + body-type-basic = media-basic SP body-fields + ; MESSAGE subtype MUST NOT be "RFC822" + + body-type-mpart = 1*body SP media-subtype + [SP body-ext-mpart] + + body-type-msg = media-message SP body-fields SP envelope + SP body SP body-fld-lines + + body-type-text = media-text SP body-fields SP body-fld-lines + + capability = ("AUTH=" auth-type) / atom + ; New capabilities MUST begin with "X" or be + ; registered with IANA as standard or + ; standards-track + + + capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev1" + *(SP capability) + ; IMAP4rev1 servers which offer RFC 1730 + ; compatibility MUST list "IMAP4" as the first + ; capability. + + CHAR8 = %x01-ff + ; any OCTET except NUL, %x00 + + command = tag SP (command-any / command-auth / command-nonauth / + command-select) CRLF + ; Modal based on state + + command-any = "CAPABILITY" / "LOGOUT" / "NOOP" / x-command + ; Valid in all states + + command-auth = append / create / delete / examine / list / lsub / + rename / select / status / subscribe / unsubscribe + ; Valid only in Authenticated or Selected state + + command-nonauth = login / authenticate + ; Valid only when in Not Authenticated state + + command-select = "CHECK" / "CLOSE" / "EXPUNGE" / copy / fetch / store / + uid / search + ; Valid only when in Selected state + + continue-req = "+" SP (resp-text / base64) CRLF + + copy = "COPY" SP set SP mailbox + + create = "CREATE" SP mailbox + ; Use of INBOX gives a NO error + + date = date-text / DQUOTE date-text DQUOTE + + date-day = 1*2DIGIT + ; Day of month + + date-day-fixed = (SP DIGIT) / 2DIGIT + ; Fixed-format version of date-day + + date-month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / + "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" + + date-text = date-day "-" date-month "-" date-year + + date-year = 4DIGIT + + date-time = DQUOTE date-day-fixed "-" date-month "-" date-year + SP time SP zone DQUOTE + + delete = "DELETE" SP mailbox + ; Use of INBOX gives a NO error + + digit-nz = %x31-39 + ; 1-9 + + envelope = "(" env-date SP env-subject SP env-from SP env-sender SP + env-reply-to SP env-to SP env-cc SP env-bcc SP + env-in-reply-to SP env-message-id ")" + + env-bcc = "(" 1*address ")" / nil + + env-cc = "(" 1*address ")" / nil + + env-date = nstring + + env-from = "(" 1*address ")" / nil + + env-in-reply-to = nstring + + env-message-id = nstring + + env-reply-to = "(" 1*address ")" / nil + + env-sender = "(" 1*address ")" / nil + + env-subject = nstring + + env-to = "(" 1*address ")" / nil + + examine = "EXAMINE" SP mailbox + + fetch = "FETCH" SP set SP ("ALL" / "FULL" / "FAST" / fetch-att / + "(" fetch-att *(SP fetch-att) ")") + + fetch-att = "ENVELOPE" / "FLAGS" / "INTERNALDATE" / + "RFC822" [".HEADER" / ".SIZE" / ".TEXT"] / + "BODY" ["STRUCTURE"] / "UID" / + "BODY" [".PEEK"] section ["<" number "." nz-number ">"] + + flag = "\Answered" / "\Flagged" / "\Deleted" / + "\Seen" / "\Draft" / flag-keyword / flag-extension + ; Does not include "\Recent" + + flag-extension = "\" atom + ; Future expansion. Client implementations + ; MUST accept flag-extension flags. Server + ; implementations MUST NOT generate + ; flag-extension flags except as defined by + ; future standard or standards-track + ; revisions of this specification. + + flag-fetch = flag / "\Recent" + + flag-keyword = atom + + flag-list = "(" [flag *(SP flag)] ")" + + flag-perm = flag / "\*" + + greeting = "*" SP (resp-cond-auth / resp-cond-bye) CRLF + + header-fld-name = astring + + header-list = "(" header-fld-name *(SP header-fld-name) ")" + + list = "LIST" SP mailbox SP list-mailbox + + list-mailbox = 1*list-char / string + + list-char = ATOM-CHAR / list-wildcards / resp-specials + + list-wildcards = "%" / "*" + + literal = "{" number "}" CRLF *CHAR8 + ; Number represents the number of CHAR8s + + login = "LOGIN" SP userid SP password + + lsub = "LSUB" SP mailbox SP list-mailbox + + mailbox = "INBOX" / astring + ; INBOX is case-insensitive. All case variants of + ; INBOX (e.g. "iNbOx") MUST be interpreted as INBOX + ; not as an astring. An astring which consists of + ; the case-insensitive sequence "I" "N" "B" "O" "X" + ; is considered to be INBOX and not an astring. + ; Refer to section 5.1 for further + ; semantic details of mailbox names. + + mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list / + "LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) / + "STATUS" SP mailbox SP "(" + [status-att SP number *(SP status-att SP number)] ")" / + number SP "EXISTS" / number SP "RECENT" + + mailbox-list = "(" [mbx-list-flags] ")" SP + (DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox + + mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag + *(SP mbx-list-oflag) / + mbx-list-oflag *(SP mbx-list-oflag) + + mbx-list-oflag = "\Noinferiors" / flag-extension + ; Other flags; multiple possible per LIST response + + mbx-list-sflag = "\Noselect" / "\Marked" / "\Unmarked" + ; Selectability flags; only one per LIST response + + media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" / + "VIDEO") DQUOTE) / string) SP media-subtype + ; Defined in [MIME-IMT] + + media-message = DQUOTE "MESSAGE" DQUOTE SP DQUOTE "RFC822" DQUOTE + ; Defined in [MIME-IMT] + + media-subtype = string + ; Defined in [MIME-IMT] + + media-text = DQUOTE "TEXT" DQUOTE SP media-subtype + ; Defined in [MIME-IMT] + + message-data = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att)) + + msg-att = "(" (msg-att-dynamic / msg-att-static) + *(SP (msg-att-dynamic / msg-att-static)) ")" + + msg-att-dynamic = "FLAGS" SP "(" [flag-fetch *(SP flag-fetch)] ")" + ; MAY change for a message + + msg-att-static = "ENVELOPE" SP envelope / "INTERNALDATE" SP date-time / + "RFC822" [".HEADER" / ".TEXT"] SP nstring / + "RFC822.SIZE" SP number / "BODY" ["STRUCTURE"] SP body / + "BODY" section ["<" number ">"] SP nstring / + "UID" SP uniqueid + ; MUST NOT change for a message + + nil = "NIL" + + nstring = string / nil + + number = 1*DIGIT + ; Unsigned 32-bit integer + ; (0 <= n < 4,294,967,296) + + nz-number = digit-nz *DIGIT + ; Non-zero unsigned 32-bit integer + ; (0 < n < 4,294,967,296) + + password = astring + + quoted = DQUOTE *QUOTED-CHAR DQUOTE + + QUOTED-CHAR = / + "\" quoted-specials + + quoted-specials = DQUOTE / "\" + + rename = "RENAME" SP mailbox SP mailbox + ; Use of INBOX as a destination gives a NO error + + response = *(continue-req / response-data) response-done + + response-data = "*" SP (resp-cond-state / resp-cond-bye / + mailbox-data / message-data / capability-data) CRLF + + response-done = response-tagged / response-fatal + + response-fatal = "*" SP resp-cond-bye CRLF + ; Server closes connection immediately + + response-tagged = tag SP resp-cond-state CRLF + + resp-cond-auth = ("OK" / "PREAUTH") SP resp-text + ; Authentication condition + + resp-cond-bye = "BYE" SP resp-text + + resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text + ; Status condition + + resp-specials = "]" + + resp-text = ["[" resp-text-code "]" SP] text + + resp-text-code = "ALERT" / + "BADCHARSET" [SP "(" astring *(SP astring) ")" ] / + capability-data / "PARSE" / + "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" / + "READ-ONLY" / "READ-WRITE" / "TRYCREATE" / + "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number / + "UNSEEN" SP nz-number / + atom [SP 1*] + + search = "SEARCH" [SP "CHARSET" SP astring] 1*(SP search-key) + ; CHARSET argument to MUST be registered with IANA + + search-key = "ALL" / "ANSWERED" / "BCC" SP astring / + "BEFORE" SP date / "BODY" SP astring / + "CC" SP astring / "DELETED" / "FLAGGED" / + "FROM" SP astring / "KEYWORD" SP flag-keyword / "NEW" / + "OLD" / "ON" SP date / "RECENT" / "SEEN" / + "SINCE" SP date / "SUBJECT" SP astring / + "TEXT" SP astring / "TO" SP astring / + "UNANSWERED" / "UNDELETED" / "UNFLAGGED" / + "UNKEYWORD" SP flag-keyword / "UNSEEN" / + ; Above this line were in [IMAP2] + "DRAFT" / "HEADER" SP header-fld-name SP astring / + "LARGER" SP number / "NOT" SP search-key / + "OR" SP search-key SP search-key / + "SENTBEFORE" SP date / "SENTON" SP date / + "SENTSINCE" SP date / "SMALLER" SP number / + "UID" SP set / "UNDRAFT" / set / + "(" search-key *(SP search-key) ")" + + section = "[" [section-spec] "]" + + section-msgtext = "HEADER" / "HEADER.FIELDS" [".NOT"] SP header-list / + "TEXT" + ; top-level or MESSAGE/RFC822 part + + section-part = nz-number *("." nz-number) + ; body part nesting + + section-spec = section-msgtext / (section-part ["." section-text]) + + section-text = section-msgtext / "MIME" + ; text other than actual body part (headers, etc.) + + select = "SELECT" SP mailbox + + sequence-num = nz-number / "*" + ; * is the largest number in use. For message + ; sequence numbers, it is the number of messages + ; in the mailbox. For unique identifiers, it is + ; the unique identifier of the last message in + ; the mailbox. + + set = sequence-num / (sequence-num ":" sequence-num) / + (set "," set) + ; Identifies a set of messages. For message + ; sequence numbers, these are consecutive + ; numbers from 1 to the number of messages in + ; the mailbox + ; Comma delimits individual numbers, colon + ; delimits between two numbers inclusive. + ; Example: 2,4:7,9,12:* is 2,4,5,6,7,9,12,13, + ; 14,15 for a mailbox with 15 messages. + + + status = "STATUS" SP mailbox SP "(" status-att *(SP status-att) ")" + + status-att = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" / + "UNSEEN" + + store = "STORE" SP set SP store-att-flags + + store-att-flags = (["+" / "-"] "FLAGS" [".SILENT"]) SP + (flag-list / (flag *(SP flag))) + + string = quoted / literal + + subscribe = "SUBSCRIBE" SP mailbox + + tag = 1* + + text = 1*TEXT-CHAR + + TEXT-CHAR = + + time = 2DIGIT ":" 2DIGIT ":" 2DIGIT + ; Hours minutes seconds + + uid = "UID" SP (copy / fetch / search / store) + ; Unique identifiers used instead of message + ; sequence numbers + + uniqueid = nz-number + ; Strictly ascending + + unsubscribe = "UNSUBSCRIBE" SP mailbox + + userid = astring + + x-command = "X" atom + + zone = ("+" / "-") 4DIGIT + ; Signed four-digit value of hhmm representing + ; hours and minutes east of Greenwich (that is, + ; the amount that the given time differs from + ; Universal Time). Subtracting the timezone + ; from the given time will give the UT form. + ; The Universal Time zone is "+0000". +*/ + + +#ifndef MAILIMAP_TYPES_H + +#define MAILIMAP_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "libetpan-config.h" +#include "mailstream.h" +#include "clist.h" +#include "stdbool.h" + + +/* + IMPORTANT NOTE: + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + allocation functions will return NULL on failure +*/ + + +/* + mailimap_address represents a mail address + + - personal_name is the name to display in an address + '"name"' in '"name" ', should be allocated + with a malloc() + + - source_route is the source-route information in the + mail address (RFC 822), should be allocated with a malloc() + + - mailbox_name is the name of the mailbox 'address' in + '"name" ', should be allocated with a malloc() + + - host_name is the name of the host 'domain' in + '"name" ', should be allocated with a malloc() + + if mailbox_name is not NULL and host_name is NULL, this is the name + of a group, the next addresses in the list are elements of the group + until we reach an address with a NULL mailbox_name. +*/ + +struct mailimap_address { + char * ad_personal_name; /* can be NULL */ + char * ad_source_route; /* can be NULL */ + char * ad_mailbox_name; /* can be NULL */ + char * ad_host_name; /* can be NULL */ +}; + + +LIBETPAN_EXPORT +struct mailimap_address * +mailimap_address_new(char * ad_personal_name, char * ad_source_route, + char * ad_mailbox_name, char * ad_host_name); + +LIBETPAN_EXPORT +void mailimap_address_free(struct mailimap_address * addr); + + +/* this is the type of MIME body parsed by IMAP server */ + +enum { + MAILIMAP_BODY_ERROR, + MAILIMAP_BODY_1PART, /* single part */ + MAILIMAP_BODY_MPART /* multi-part */ +}; + +/* + mailimap_body represent a MIME body parsed by IMAP server + + - type is the type of the MIME part (single part or multipart) + + - body_1part is defined if this is a single part + + - body_mpart is defined if this is a multipart +*/ + +struct mailimap_body { + int bd_type; + /* can be MAILIMAP_BODY_1PART or MAILIMAP_BODY_MPART */ + union { + struct mailimap_body_type_1part * bd_body_1part; /* can be NULL */ + struct mailimap_body_type_mpart * bd_body_mpart; /* can be NULL */ + } bd_data; +}; + + +LIBETPAN_EXPORT +struct mailimap_body * +mailimap_body_new(int bd_type, + struct mailimap_body_type_1part * bd_body_1part, + struct mailimap_body_type_mpart * bd_body_mpart); + +LIBETPAN_EXPORT +void mailimap_body_free(struct mailimap_body * body); + + + +/* + this is the type of MIME body extension +*/ + +enum { + MAILIMAP_BODY_EXTENSION_ERROR, + MAILIMAP_BODY_EXTENSION_NSTRING, /* string */ + MAILIMAP_BODY_EXTENSION_NUMBER, /* number */ + MAILIMAP_BODY_EXTENSION_LIST /* list of + (struct mailimap_body_extension *) */ +}; + +/* + mailimap_body_extension is a future extension header field value + + - type is the type of the body extension (string, number or + list of extension) + + - nstring is a string value if the type is string + + - number is a integer value if the type is number + + - list is a list of body extension if the type is a list +*/ + +struct mailimap_body_extension { + int ext_type; + /* + can be MAILIMAP_BODY_EXTENSION_NSTRING, MAILIMAP_BODY_EXTENSION_NUMBER + or MAILIMAP_BODY_EXTENSION_LIST + */ + union { + char * ext_nstring; /* can be NULL */ + uint32_t ext_number; + clist * ext_body_extension_list; + /* list of (struct mailimap_body_extension *) */ + /* can be NULL */ + } ext_data; +}; + +LIBETPAN_EXPORT +struct mailimap_body_extension * +mailimap_body_extension_new(int ext_type, char * ext_nstring, + uint32_t ext_number, + clist * ext_body_extension_list); + +LIBETPAN_EXPORT +void mailimap_body_extension_free(struct mailimap_body_extension * be); + + +/* + mailimap_body_ext_1part is the extended result part of a single part + bodystructure. + + - body_md5 is the value of the Content-MD5 header field, should be + allocated with malloc() + + - body_disposition is the value of the Content-Disposition header field + + - body_language is the value of the Content-Language header field + + - body_extension_list is the list of extension fields value. +*/ + +struct mailimap_body_ext_1part { + char * bd_md5; /* can be NULL */ + struct mailimap_body_fld_dsp * bd_disposition; /* can be NULL */ + struct mailimap_body_fld_lang * bd_language; /* can be NULL */ + char * bd_loc; /* can be NULL */ + + clist * bd_extension_list; /* list of (struct mailimap_body_extension *) */ + /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_body_ext_1part * +mailimap_body_ext_1part_new(char * bd_md5, + struct mailimap_body_fld_dsp * bd_disposition, + struct mailimap_body_fld_lang * bd_language, + char * bd_loc, + clist * bd_extension_list); + + +LIBETPAN_EXPORT +void +mailimap_body_ext_1part_free(struct mailimap_body_ext_1part * body_ext_1part); + + +/* + mailimap_body_ext_mpart is the extended result part of a multipart + bodystructure. + + - body_parameter is the list of parameters of Content-Type header field + + - body_disposition is the value of Content-Disposition header field + + - body_language is the value of Content-Language header field + + - body_extension_list is the list of extension fields value. +*/ + +struct mailimap_body_ext_mpart { + struct mailimap_body_fld_param * bd_parameter; /* can be NULL */ + struct mailimap_body_fld_dsp * bd_disposition; /* can be NULL */ + struct mailimap_body_fld_lang * bd_language; /* can be NULL */ + char * bd_loc; /* can be NULL */ + clist * bd_extension_list; /* list of (struct mailimap_body_extension *) */ + /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_body_ext_mpart * +mailimap_body_ext_mpart_new(struct mailimap_body_fld_param * bd_parameter, + struct mailimap_body_fld_dsp * bd_disposition, + struct mailimap_body_fld_lang * bd_language, + char * bd_loc, + clist * bd_extension_list); + +LIBETPAN_EXPORT +void +mailimap_body_ext_mpart_free(struct mailimap_body_ext_mpart * body_ext_mpart); + + +/* + mailimap_body_fields is the MIME fields of a MIME part. + + - body_parameter is the list of parameters of Content-Type header field + + - body_id is the value of Content-ID header field, should be allocated + with malloc() + + - body_description is the value of Content-Description header field, + should be allocated with malloc() + + - body_encoding is the value of Content-Transfer-Encoding header field + + - body_disposition is the value of Content-Disposition header field + + - body_size is the size of the MIME part +*/ + +struct mailimap_body_fields { + struct mailimap_body_fld_param * bd_parameter; /* can be NULL */ + char * bd_id; /* can be NULL */ + char * bd_description; /* can be NULL */ + struct mailimap_body_fld_enc * bd_encoding; /* != NULL */ + uint32_t bd_size; +}; + +LIBETPAN_EXPORT +struct mailimap_body_fields * +mailimap_body_fields_new(struct mailimap_body_fld_param * bd_parameter, + char * bd_id, + char * bd_description, + struct mailimap_body_fld_enc * bd_encoding, + uint32_t bd_size); + +LIBETPAN_EXPORT +void +mailimap_body_fields_free(struct mailimap_body_fields * body_fields); + + + +/* + mailimap_body_fld_dsp is the parsed value of the Content-Disposition field + + - disposition_type is the type of Content-Disposition + (usually attachment or inline), should be allocated with malloc() + + - attributes is the list of Content-Disposition attributes +*/ + +struct mailimap_body_fld_dsp { + char * dsp_type; /* != NULL */ + struct mailimap_body_fld_param * dsp_attributes; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_body_fld_dsp * +mailimap_body_fld_dsp_new(char * dsp_type, + struct mailimap_body_fld_param * dsp_attributes); + +LIBETPAN_EXPORT +void mailimap_body_fld_dsp_free(struct mailimap_body_fld_dsp * bfd); + + + +/* these are the different parsed values for Content-Transfer-Encoding */ + +enum { + MAILIMAP_BODY_FLD_ENC_7BIT, /* 7bit */ + MAILIMAP_BODY_FLD_ENC_8BIT, /* 8bit */ + MAILIMAP_BODY_FLD_ENC_BINARY, /* binary */ + MAILIMAP_BODY_FLD_ENC_BASE64, /* base64 */ + MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE, /* quoted-printable */ + MAILIMAP_BODY_FLD_ENC_OTHER /* other */ +}; + +/* + mailimap_body_fld_enc is a parsed value for Content-Transfer-Encoding + + - type is the kind of Content-Transfer-Encoding, this can be + MAILIMAP_BODY_FLD_ENC_7BIT, MAILIMAP_BODY_FLD_ENC_8BIT, + MAILIMAP_BODY_FLD_ENC_BINARY, MAILIMAP_BODY_FLD_ENC_BASE64, + MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE or MAILIMAP_BODY_FLD_ENC_OTHER + + - in case of MAILIMAP_BODY_FLD_ENC_OTHER, this value is defined, + should be allocated with malloc() +*/ + +struct mailimap_body_fld_enc { + int enc_type; + char * enc_value; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_body_fld_enc * +mailimap_body_fld_enc_new(int enc_type, char * enc_value); + +LIBETPAN_EXPORT +void mailimap_body_fld_enc_free(struct mailimap_body_fld_enc * bfe); + + +/* this is the type of Content-Language header field value */ + +enum { + MAILIMAP_BODY_FLD_LANG_ERROR, /* error parse */ + MAILIMAP_BODY_FLD_LANG_SINGLE, /* single value */ + MAILIMAP_BODY_FLD_LANG_LIST /* list of values */ +}; + +/* + mailimap_body_fld_lang is the parsed value of the Content-Language field + + - type is the type of content, this can be MAILIMAP_BODY_FLD_LANG_SINGLE + if this is a single value or MAILIMAP_BODY_FLD_LANG_LIST if there are + several values + + - single is the single value if the type is MAILIMAP_BODY_FLD_LANG_SINGLE, + should be allocated with malloc() + + - list is the list of value if the type is MAILIMAP_BODY_FLD_LANG_LIST, + all elements of the list should be allocated with malloc() +*/ + +struct mailimap_body_fld_lang { + int lg_type; + union { + char * lg_single; /* can be NULL */ + clist * lg_list; /* list of string (char *), can be NULL */ + } lg_data; +}; + +LIBETPAN_EXPORT +struct mailimap_body_fld_lang * +mailimap_body_fld_lang_new(int lg_type, char * lg_single, clist * lg_list); + +LIBETPAN_EXPORT +void +mailimap_body_fld_lang_free(struct mailimap_body_fld_lang * fld_lang); + + + +/* + mailimap_single_body_fld_param is a body field parameter + + - name is the name of the parameter, should be allocated with malloc() + + - value is the value of the parameter, should be allocated with malloc() +*/ + +struct mailimap_single_body_fld_param { + char * pa_name; /* != NULL */ + char * pa_value; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_single_body_fld_param * +mailimap_single_body_fld_param_new(char * pa_name, char * pa_value); + +LIBETPAN_EXPORT +void +mailimap_single_body_fld_param_free(struct mailimap_single_body_fld_param * p); + + +/* + mailmap_body_fld_param is a list of parameters + + - list is the list of parameters. +*/ + +struct mailimap_body_fld_param { + clist * pa_list; /* list of (struct mailimap_single_body_fld_param *) */ + /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_body_fld_param * +mailimap_body_fld_param_new(clist * pa_list); + +LIBETPAN_EXPORT +void +mailimap_body_fld_param_free(struct mailimap_body_fld_param * fld_param); + + +/* + this is the kind of single part: a text part + (when Content-Type is text/xxx), a message part (when Content-Type is + message/rfc2822) or a basic part (others than multpart/xxx) +*/ + +enum { + MAILIMAP_BODY_TYPE_1PART_ERROR, /* parse error */ + MAILIMAP_BODY_TYPE_1PART_BASIC, /* others then multipart/xxx */ + MAILIMAP_BODY_TYPE_1PART_MSG, /* message/rfc2822 */ + MAILIMAP_BODY_TYPE_1PART_TEXT /* text/xxx */ +}; + + +/* + mailimap_body_type_1part is + + - type is the kind of single part, this can be + MAILIMAP_BODY_TYPE_1PART_BASIC, MAILIMAP_BODY_TYPE_1PART_MSG or + MAILIMAP_BODY_TYPE_1PART_TEXT. + + - body_type_basic is the basic part when type is + MAILIMAP_BODY_TYPE_1PART_BASIC + + - body_type_msg is the message part when type is + MAILIMAP_BODY_TYPE_1PART_MSG + + - body_type_text is the text part when type is + MAILIMAP_BODY_TYPE_1PART_TEXT +*/ + +struct mailimap_body_type_1part { + int bd_type; + union { + struct mailimap_body_type_basic * bd_type_basic; /* can be NULL */ + struct mailimap_body_type_msg * bd_type_msg; /* can be NULL */ + struct mailimap_body_type_text * bd_type_text; /* can be NULL */ + } bd_data; + struct mailimap_body_ext_1part * bd_ext_1part; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_body_type_1part * +mailimap_body_type_1part_new(int bd_type, + struct mailimap_body_type_basic * bd_type_basic, + struct mailimap_body_type_msg * bd_type_msg, + struct mailimap_body_type_text * bd_type_text, + struct mailimap_body_ext_1part * bd_ext_1part); + +LIBETPAN_EXPORT +void +mailimap_body_type_1part_free(struct mailimap_body_type_1part * bt1p); + + + +/* + mailimap_body_type_basic is a basic field (with Content-Type other + than multipart/xxx, message/rfc2822 and text/xxx + + - media_basic will be the MIME type of the part + + - body_fields will be the parsed fields of the MIME part +*/ + +struct mailimap_body_type_basic { + struct mailimap_media_basic * bd_media_basic; /* != NULL */ + struct mailimap_body_fields * bd_fields; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_body_type_basic * +mailimap_body_type_basic_new(struct mailimap_media_basic * bd_media_basic, + struct mailimap_body_fields * bd_fields); + +LIBETPAN_EXPORT +void mailimap_body_type_basic_free(struct mailimap_body_type_basic * + body_type_basic); + +/* + mailimap_body_type_mpart is a MIME multipart. + + - body_list is the list of sub-parts. + + - media_subtype is the subtype of the multipart (for example + in multipart/alternative, this is "alternative") + + - body_ext_mpart is the extended fields of the MIME multipart +*/ + +struct mailimap_body_type_mpart { + clist * bd_list; /* list of (struct mailimap_body *) */ + /* != NULL */ + char * bd_media_subtype; /* != NULL */ + struct mailimap_body_ext_mpart * bd_ext_mpart; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_body_type_mpart * +mailimap_body_type_mpart_new(clist * bd_list, char * bd_media_subtype, + struct mailimap_body_ext_mpart * bd_ext_mpart); + +LIBETPAN_EXPORT +void mailimap_body_type_mpart_free(struct mailimap_body_type_mpart * + body_type_mpart); + +/* + mailimap_body_type_msg is a MIME message part + + - body_fields is the MIME fields of the MIME message part + + - envelope is the list of parsed RFC 822 fields of the MIME message + + - body is the sub-part of the message + + - body_lines is the number of lines of the message part +*/ + +struct mailimap_body_type_msg { + struct mailimap_body_fields * bd_fields; /* != NULL */ + struct mailimap_envelope * bd_envelope; /* != NULL */ + struct mailimap_body * bd_body; /* != NULL */ + uint32_t bd_lines; +}; + +LIBETPAN_EXPORT +struct mailimap_body_type_msg * +mailimap_body_type_msg_new(struct mailimap_body_fields * bd_fields, + struct mailimap_envelope * bd_envelope, + struct mailimap_body * bd_body, + uint32_t bd_lines); + +LIBETPAN_EXPORT +void +mailimap_body_type_msg_free(struct mailimap_body_type_msg * body_type_msg); + + + +/* + mailimap_body_type_text is a single MIME part where Content-Type is text/xxx + + - media-text is the subtype of the text part (for example, in "text/plain", + this is "plain", should be allocated with malloc() + + - body_fields is the MIME fields of the MIME message part + + - body_lines is the number of lines of the message part +*/ + +struct mailimap_body_type_text { + char * bd_media_text; /* != NULL */ + struct mailimap_body_fields * bd_fields; /* != NULL */ + uint32_t bd_lines; +}; + +LIBETPAN_EXPORT +struct mailimap_body_type_text * +mailimap_body_type_text_new(char * bd_media_text, + struct mailimap_body_fields * bd_fields, + uint32_t bd_lines); + +LIBETPAN_EXPORT +void +mailimap_body_type_text_free(struct mailimap_body_type_text * body_type_text); + + + +/* this is the type of capability field */ + +enum { + MAILIMAP_CAPABILITY_AUTH_TYPE, /* when the capability is an + authentication type */ + MAILIMAP_CAPABILITY_NAME /* other type of capability */ +}; + +/* + mailimap_capability is a capability of the IMAP server + + - type is the type of capability, this is either a authentication type + (MAILIMAP_CAPABILITY_AUTH_TYPE) or an other type of capability + (MAILIMAP_CAPABILITY_NAME) + + - auth_type is a type of authentication "name" in "AUTH=name", + auth_type can be for example "PLAIN", when this is an authentication type, + should be allocated with malloc() + + - name is a type of capability when this is not an authentication type, + should be allocated with malloc() +*/ + +struct mailimap_capability { + int cap_type; + union { + char * cap_auth_type; /* can be NULL */ + char * cap_name; /* can be NULL */ + } cap_data; +}; + +LIBETPAN_EXPORT +struct mailimap_capability * +mailimap_capability_new(int cap_type, char * cap_auth_type, char * cap_name); + +LIBETPAN_EXPORT +void mailimap_capability_free(struct mailimap_capability * c); + + + + +/* + mailimap_capability_data is a list of capability + + - list is the list of capability +*/ + +struct mailimap_capability_data { + clist * cap_list; /* list of (struct mailimap_capability *), != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_capability_data * +mailimap_capability_data_new(clist * cap_list); + +LIBETPAN_EXPORT +void +mailimap_capability_data_free(struct mailimap_capability_data * cap_data); + + + +/* this is the type of continue request data */ + +enum { + MAILIMAP_CONTINUE_REQ_ERROR, /* on parse error */ + MAILIMAP_CONTINUE_REQ_TEXT, /* when data is a text response */ + MAILIMAP_CONTINUE_REQ_BASE64 /* when data is a base64 response */ +}; + +/* + mailimap_continue_req is a continue request (a response prefixed by "+") + + - type is the type of continue request response + MAILIMAP_CONTINUE_REQ_TEXT (when information data is text), + MAILIMAP_CONTINUE_REQ_BASE64 (when information data is base64) + + - text is the information of type text in case of text data + + - base64 is base64 encoded data in the other case, should be allocated + with malloc() +*/ + +struct mailimap_continue_req { + int cr_type; + union { + struct mailimap_resp_text * cr_text; /* can be NULL */ + char * cr_base64; /* can be NULL */ + } cr_data; +}; + +LIBETPAN_EXPORT +struct mailimap_continue_req * +mailimap_continue_req_new(int cr_type, struct mailimap_resp_text * cr_text, + char * cr_base64); + +LIBETPAN_EXPORT +void mailimap_continue_req_free(struct mailimap_continue_req * cont_req); + + +/* + mailimap_date_time is a date + + - day is the day of month (1 to 31) + + - month (1 to 12) + + - year (4 digits) + + - hour (0 to 23) + + - min (0 to 59) + + - sec (0 to 59) + + - zone (this is the decimal value that we can read, for example: + for "-0200", the value is -200) +*/ + +struct mailimap_date_time { + int dt_day; + int dt_month; + int dt_year; + int dt_hour; + int dt_min; + int dt_sec; + int dt_zone; +}; + +LIBETPAN_EXPORT +struct mailimap_date_time * +mailimap_date_time_new(int dt_day, int dt_month, int dt_year, int dt_hour, + int dt_min, int dt_sec, int dt_zone); + +LIBETPAN_EXPORT +void mailimap_date_time_free(struct mailimap_date_time * date_time); + + + +/* + mailimap_envelope is the list of fields that can be parsed by + the IMAP server. + + - date is the (non-parsed) content of the "Date" header field, + should be allocated with malloc() + + - subject is the subject of the message, should be allocated with + malloc() + + - sender is the the parsed content of the "Sender" field + + - reply-to is the parsed content of the "Reply-To" field + + - to is the parsed content of the "To" field + + - cc is the parsed content of the "Cc" field + + - bcc is the parsed content of the "Bcc" field + + - in_reply_to is the content of the "In-Reply-To" field, + should be allocated with malloc() + + - message_id is the content of the "Message-ID" field, + should be allocated with malloc() +*/ + +struct mailimap_envelope { + char * env_date; /* can be NULL */ + char * env_subject; /* can be NULL */ + struct mailimap_env_from * env_from; /* can be NULL */ + struct mailimap_env_sender * env_sender; /* can be NULL */ + struct mailimap_env_reply_to * env_reply_to; /* can be NULL */ + struct mailimap_env_to * env_to; /* can be NULL */ + struct mailimap_env_cc * env_cc; /* can be NULL */ + struct mailimap_env_bcc * env_bcc; /* can be NULL */ + char * env_in_reply_to; /* can be NULL */ + char * env_message_id; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_envelope * +mailimap_envelope_new(char * env_date, char * env_subject, + struct mailimap_env_from * env_from, + struct mailimap_env_sender * env_sender, + struct mailimap_env_reply_to * env_reply_to, + struct mailimap_env_to * env_to, + struct mailimap_env_cc* env_cc, + struct mailimap_env_bcc * env_bcc, + char * env_in_reply_to, char * env_message_id); + +LIBETPAN_EXPORT +void mailimap_envelope_free(struct mailimap_envelope * env); + + + +/* + mailimap_env_bcc is the parsed "Bcc" field + + - list is the list of addresses +*/ + +struct mailimap_env_bcc { + clist * bcc_list; /* list of (struct mailimap_address *), can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_env_bcc * mailimap_env_bcc_new(clist * bcc_list); + +LIBETPAN_EXPORT +void mailimap_env_bcc_free(struct mailimap_env_bcc * env_bcc); + + +/* + mailimap_env_cc is the parsed "Cc" field + + - list is the list of addresses +*/ + +struct mailimap_env_cc { + clist * cc_list; /* list of (struct mailimap_address *), can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_env_cc * mailimap_env_cc_new(clist * cc_list); + +LIBETPAN_EXPORT +void mailimap_env_cc_free(struct mailimap_env_cc * env_cc); + + + +/* + mailimap_env_from is the parsed "From" field + + - list is the list of addresses +*/ + +struct mailimap_env_from { + clist * frm_list; /* list of (struct mailimap_address *) */ + /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_env_from * mailimap_env_from_new(clist * frm_list); + +LIBETPAN_EXPORT +void mailimap_env_from_free(struct mailimap_env_from * env_from); + + + +/* + mailimap_env_reply_to is the parsed "Reply-To" field + + - list is the list of addresses +*/ + +struct mailimap_env_reply_to { + clist * rt_list; /* list of (struct mailimap_address *), can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_env_reply_to * mailimap_env_reply_to_new(clist * rt_list); + +LIBETPAN_EXPORT +void +mailimap_env_reply_to_free(struct mailimap_env_reply_to * env_reply_to); + + + +/* + mailimap_env_sender is the parsed "Sender" field + + - list is the list of addresses +*/ + +struct mailimap_env_sender { + clist * snd_list; /* list of (struct mailimap_address *), can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_env_sender * mailimap_env_sender_new(clist * snd_list); + +LIBETPAN_EXPORT +void mailimap_env_sender_free(struct mailimap_env_sender * env_sender); + + + +/* + mailimap_env_to is the parsed "To" field + + - list is the list of addresses +*/ + +struct mailimap_env_to { + clist * to_list; /* list of (struct mailimap_address *), can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_env_to * mailimap_env_to_new(clist * to_list); + +LIBETPAN_EXPORT +void mailimap_env_to_free(struct mailimap_env_to * env_to); + + +/* this is the type of flag */ + +enum { + MAILIMAP_FLAG_ANSWERED, /* \Answered flag */ + MAILIMAP_FLAG_FLAGGED, /* \Flagged flag */ + MAILIMAP_FLAG_DELETED, /* \Deleted flag */ + MAILIMAP_FLAG_SEEN, /* \Seen flag */ + MAILIMAP_FLAG_DRAFT, /* \Draft flag */ + MAILIMAP_FLAG_KEYWORD, /* keyword flag */ + MAILIMAP_FLAG_EXTENSION /* \extension flag */ +}; + + +/* + mailimap_flag is a message flag (that we can associate with a message) + + - type is the type of the flag, MAILIMAP_FLAG_XXX + + - keyword is the flag when the flag is of keyword type, + should be allocated with malloc() + + - extension is the flag when the flag is of extension type, should be + allocated with malloc() +*/ + +struct mailimap_flag { + int fl_type; + union { + char * fl_keyword; /* can be NULL */ + char * fl_extension; /* can be NULL */ + } fl_data; +}; + +LIBETPAN_EXPORT +struct mailimap_flag * mailimap_flag_new(int fl_type, + char * fl_keyword, char * fl_extension); + +LIBETPAN_EXPORT +void mailimap_flag_free(struct mailimap_flag * f); + + + + +/* this is the type of flag */ + +enum { + MAILIMAP_FLAG_FETCH_ERROR, /* on parse error */ + MAILIMAP_FLAG_FETCH_RECENT, /* \Recent flag */ + MAILIMAP_FLAG_FETCH_OTHER /* other type of flag */ +}; + +/* + mailimap_flag_fetch is a message flag (when we fetch it) + + - type is the type of flag fetch + + - flag is the flag when this is not a \Recent flag +*/ + +struct mailimap_flag_fetch { + int fl_type; + struct mailimap_flag * fl_flag; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_flag_fetch * +mailimap_flag_fetch_new(int fl_type, struct mailimap_flag * fl_flag); + +LIBETPAN_EXPORT +void mailimap_flag_fetch_free(struct mailimap_flag_fetch * flag_fetch); + + + + +/* this is the type of flag */ + +enum { + MAILIMAP_FLAG_PERM_ERROR, /* on parse error */ + MAILIMAP_FLAG_PERM_FLAG, /* to specify that usual flags can be changed */ + MAILIMAP_FLAG_PERM_ALL /* to specify that new flags can be created */ +}; + + +/* + mailimap_flag_perm is a flag returned in case of PERMANENTFLAGS response + + - type is the type of returned PERMANENTFLAGS, it can be + MAILIMAP_FLAG_PERM_FLAG (the given flag can be changed permanently) or + MAILIMAP_FLAG_PERM_ALL (new flags can be created) + + - flag is the given flag when type is MAILIMAP_FLAG_PERM_FLAG +*/ + +struct mailimap_flag_perm { + int fl_type; + struct mailimap_flag * fl_flag; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_flag_perm * +mailimap_flag_perm_new(int fl_type, struct mailimap_flag * fl_flag); + +LIBETPAN_EXPORT +void mailimap_flag_perm_free(struct mailimap_flag_perm * flag_perm); + + +/* + mailimap_flag_list is a list of flags + + - list is a list of flags +*/ + +struct mailimap_flag_list { + clist * fl_list; /* list of (struct mailimap_flag *), != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_flag_list * +mailimap_flag_list_new(clist * fl_list); + +LIBETPAN_EXPORT +void mailimap_flag_list_free(struct mailimap_flag_list * flag_list); + + + + +/* this is the type of greeting response */ + +enum { + MAILIMAP_GREETING_RESP_COND_ERROR, /* on parse error */ + MAILIMAP_GREETING_RESP_COND_AUTH, /* when connection is accepted */ + MAILIMAP_GREETING_RESP_COND_BYE /* when connection is refused */ +}; + +/* + mailimap_greeting is the response returned on connection + + - type is the type of response on connection, either + MAILIMAP_GREETING_RESP_COND_AUTH if connection is accepted or + MAIMIMAP_GREETING_RESP_COND_BYE if connection is refused +*/ + +struct mailimap_greeting { + int gr_type; + union { + struct mailimap_resp_cond_auth * gr_auth; /* can be NULL */ + struct mailimap_resp_cond_bye * gr_bye; /* can be NULL */ + } gr_data; +}; + +LIBETPAN_EXPORT +struct mailimap_greeting * +mailimap_greeting_new(int gr_type, + struct mailimap_resp_cond_auth * gr_auth, + struct mailimap_resp_cond_bye * gr_bye); + +LIBETPAN_EXPORT +void mailimap_greeting_free(struct mailimap_greeting * greeting); + + +/* + mailimap_header_list is a list of headers that can be specified when + we want to fetch fields + + - list is a list of header names, each header name should be allocated + with malloc() +*/ + +struct mailimap_header_list { + clist * hdr_list; /* list of astring (char *), != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_header_list * +mailimap_header_list_new(clist * hdr_list); + +LIBETPAN_EXPORT +void +mailimap_header_list_free(struct mailimap_header_list * header_list); + + + +/* this is the type of mailbox STATUS that can be returned */ + +enum { + MAILIMAP_STATUS_ATT_MESSAGES, /* when requesting the number of + messages */ + MAILIMAP_STATUS_ATT_RECENT, /* when requesting the number of + recent messages */ + MAILIMAP_STATUS_ATT_UIDNEXT, /* when requesting the next unique + identifier */ + MAILIMAP_STATUS_ATT_UIDVALIDITY, /* when requesting the validity of + message unique identifiers*/ + MAILIMAP_STATUS_ATT_UNSEEN, /* when requesting the number of + unseen messages */ + MAILIMAP_STATUS_ATT_HIGHESTMODSEQ, /* when requesting the highest + mod-sequence value of all messages in + the mailbox */ + MAILIMAP_STATUS_ATT_EXTENSION +}; + +/* + mailimap_status_info is a returned information when a STATUS of + a mailbox is requested + + - att is the type of mailbox STATUS, the value can be + MAILIMAP_STATUS_ATT_MESSAGES, MAILIMAP_STATUS_ATT_RECENT, + MAILIMAP_STATUS_ATT_UIDNEXT, MAILIMAP_STATUS_ATT_UIDVALIDITY, + MAILIMAP_STATUS_ATT_UNSEEN or MAILIMAP_STATUS_ATT_EXTENSION + + - value is the value of the given information + + - st_ext_data is the data of the extension. +*/ + +struct mailimap_status_info { + int st_att; + uint32_t st_value; + struct mailimap_extension_data * st_ext_data; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_status_info * + mailimap_status_info_new(int st_att, uint32_t st_value, + struct mailimap_extension_data * st_ext_data); + +LIBETPAN_EXPORT +void mailimap_status_info_free(struct mailimap_status_info * info); + + + +/* + mailimap_mailbox_data_status is the list of information returned + when a STATUS of a mailbox is requested + + - mailbox is the name of the mailbox, should be allocated with malloc() + + - status_info_list is the list of information returned +*/ + +struct mailimap_mailbox_data_status { + char * st_mailbox; + clist * st_info_list; /* list of (struct mailimap_status_info *) */ + /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_mailbox_data_status * +mailimap_mailbox_data_status_new(char * st_mailbox, + clist * st_info_list); + +LIBETPAN_EXPORT +void +mailimap_mailbox_data_status_free(struct mailimap_mailbox_data_status * info); + + + +/* this is the type of mailbox information that is returned */ + +enum { + MAILIMAP_MAILBOX_DATA_ERROR, /* on parse error */ + MAILIMAP_MAILBOX_DATA_FLAGS, /* flag that are applicable to the mailbox */ + MAILIMAP_MAILBOX_DATA_LIST, /* this is a mailbox in the list of mailboxes + returned on LIST command*/ + MAILIMAP_MAILBOX_DATA_LSUB, /* this is a mailbox in the list of + subscribed mailboxes returned on LSUB + command */ + MAILIMAP_MAILBOX_DATA_SEARCH, /* this is a list of messages numbers or + unique identifiers returned + on a SEARCH command*/ + MAILIMAP_MAILBOX_DATA_STATUS, /* this is the list of information returned + on a STATUS command */ + MAILIMAP_MAILBOX_DATA_EXISTS, /* this is the number of messages in the + mailbox */ + MAILIMAP_MAILBOX_DATA_RECENT, /* this is the number of recent messages + in the mailbox */ + MAILIMAP_MAILBOX_DATA_EXTENSION_DATA /* this mailbox-data stores data + returned by an extension */ +}; + +/* + mailimap_mailbox_data is an information related to a mailbox + + - type is the type of mailbox_data that is filled, the value of this field + can be MAILIMAP_MAILBOX_DATA_FLAGS, MAILIMAP_MAILBOX_DATA_LIST, + MAILIMAP_MAILBOX_DATA_LSUB, MAILIMAP_MAILBOX_DATA_SEARCH, + MAILIMAP_MAILBOX_DATA_STATUS, MAILIMAP_MAILBOX_DATA_EXISTS + or MAILIMAP_MAILBOX_DATA_RECENT. + + - flags is the flags that are applicable to the mailbox when + type is MAILIMAP_MAILBOX_DATA_FLAGS + + - list is a mailbox in the list of mailboxes returned on LIST command + when type is MAILIMAP_MAILBOX_DATA_LIST + + - lsub is a mailbox in the list of subscribed mailboxes returned on + LSUB command when type is MAILIMAP_MAILBOX_DATA_LSUB + + - search is a list of messages numbers or unique identifiers returned + on SEARCH command when type MAILIMAP_MAILBOX_DATA_SEARCH, each element + should be allocated with malloc() + + - status is a list of information returned on STATUS command when + type is MAILIMAP_MAILBOX_DATA_STATUS + + - exists is the number of messages in the mailbox when type + is MAILIMAP_MAILBOX_DATA_EXISTS + + - recent is the number of recent messages in the mailbox when type + is MAILIMAP_MAILBOX_DATA_RECENT +*/ + +struct mailimap_mailbox_data { + int mbd_type; + union { + struct mailimap_flag_list * mbd_flags; /* can be NULL */ + struct mailimap_mailbox_list * mbd_list; /* can be NULL */ + struct mailimap_mailbox_list * mbd_lsub; /* can be NULL */ + clist * mbd_search; /* list of nz-number (uint32_t *), can be NULL */ + struct mailimap_mailbox_data_status * mbd_status; /* can be NULL */ + uint32_t mbd_exists; + uint32_t mbd_recent; + struct mailimap_extension_data * mbd_extension; /* can be NULL */ + } mbd_data; +}; + +LIBETPAN_EXPORT +struct mailimap_mailbox_data * +mailimap_mailbox_data_new(int mbd_type, struct mailimap_flag_list * mbd_flags, + struct mailimap_mailbox_list * mbd_list, + struct mailimap_mailbox_list * mbd_lsub, + clist * mbd_search, + struct mailimap_mailbox_data_status * mbd_status, + uint32_t mbd_exists, + uint32_t mbd_recent, + struct mailimap_extension_data * mbd_extension); + +LIBETPAN_EXPORT +void +mailimap_mailbox_data_free(struct mailimap_mailbox_data * mb_data); + + + +/* this is the type of mailbox flags */ + +enum { + MAILIMAP_MBX_LIST_FLAGS_SFLAG, /* mailbox single flag - a flag in + {\NoSelect, \Marked, \Unmarked} */ + MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG /* mailbox other flag - mailbox flag + other than \NoSelect \Marked and + \Unmarked) */ +}; + +/* this is a single flag type */ + +enum { + MAILIMAP_MBX_LIST_SFLAG_ERROR, + MAILIMAP_MBX_LIST_SFLAG_MARKED, + MAILIMAP_MBX_LIST_SFLAG_NOSELECT, + MAILIMAP_MBX_LIST_SFLAG_UNMARKED +}; + +/* + mailimap_mbx_list_flags is a mailbox flag + + - type is the type of mailbox flag, it can be MAILIMAP_MBX_LIST_FLAGS_SFLAG, + or MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG. + + - oflags is a list of "mailbox other flag" + + - sflag is a mailbox single flag +*/ + +struct mailimap_mbx_list_flags { + int mbf_type; + clist * mbf_oflags; /* list of + (struct mailimap_mbx_list_oflag *), != NULL */ + int mbf_sflag; +}; + +LIBETPAN_EXPORT +struct mailimap_mbx_list_flags * +mailimap_mbx_list_flags_new(int mbf_type, + clist * mbf_oflags, int mbf_sflag); + +LIBETPAN_EXPORT +void +mailimap_mbx_list_flags_free(struct mailimap_mbx_list_flags * mbx_list_flags); + + + +/* this is the type of the mailbox other flag */ + +enum { + MAILIMAP_MBX_LIST_OFLAG_ERROR, /* on parse error */ + MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS, /* \NoInferior flag */ + MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT /* other flag */ +}; + +/* + mailimap_mbx_list_oflag is a mailbox other flag + + - type can be MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS when this is + a \NoInferior flag or MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT + + - flag_ext is set when MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT and is + an extension flag, should be allocated with malloc() +*/ + +struct mailimap_mbx_list_oflag { + int of_type; + char * of_flag_ext; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_mbx_list_oflag * +mailimap_mbx_list_oflag_new(int of_type, char * of_flag_ext); + +LIBETPAN_EXPORT +void +mailimap_mbx_list_oflag_free(struct mailimap_mbx_list_oflag * oflag); + + + +/* + mailimap_mailbox_list is a list of mailbox flags + + - mb_flag is a list of mailbox flags + + - delimiter is the delimiter of the mailbox path + + - mb is the name of the mailbox, should be allocated with malloc() +*/ + +struct mailimap_mailbox_list { + struct mailimap_mbx_list_flags * mb_flag; /* can be NULL */ + char mb_delimiter; + char * mb_name; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_mailbox_list * +mailimap_mailbox_list_new(struct mailimap_mbx_list_flags * mbx_flags, + char mb_delimiter, char * mb_name); + +LIBETPAN_EXPORT +void +mailimap_mailbox_list_free(struct mailimap_mailbox_list * mb_list); + + + +/* this is the MIME type */ + +enum { + MAILIMAP_MEDIA_BASIC_APPLICATION, /* application/xxx */ + MAILIMAP_MEDIA_BASIC_AUDIO, /* audio/xxx */ + MAILIMAP_MEDIA_BASIC_IMAGE, /* image/xxx */ + MAILIMAP_MEDIA_BASIC_MESSAGE, /* message/xxx */ + MAILIMAP_MEDIA_BASIC_VIDEO, /* video/xxx */ + MAILIMAP_MEDIA_BASIC_OTHER /* for all other cases */ +}; + + +/* + mailimap_media_basic is the MIME type + + - type can be MAILIMAP_MEDIA_BASIC_APPLICATION, MAILIMAP_MEDIA_BASIC_AUDIO, + MAILIMAP_MEDIA_BASIC_IMAGE, MAILIMAP_MEDIA_BASIC_MESSAGE, + MAILIMAP_MEDIA_BASIC_VIDEO or MAILIMAP_MEDIA_BASIC_OTHER + + - basic_type is defined when type is MAILIMAP_MEDIA_BASIC_OTHER, should + be allocated with malloc() + + - subtype is the subtype of the MIME type, for example, this is + "data" in "application/data", should be allocated with malloc() +*/ + +struct mailimap_media_basic { + int med_type; + char * med_basic_type; /* can be NULL */ + char * med_subtype; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_media_basic * +mailimap_media_basic_new(int med_type, + char * med_basic_type, char * med_subtype); + +LIBETPAN_EXPORT +void +mailimap_media_basic_free(struct mailimap_media_basic * media_basic); + + + +/* this is the type of message data */ + +enum { + MAILIMAP_MESSAGE_DATA_ERROR, + MAILIMAP_MESSAGE_DATA_EXPUNGE, + MAILIMAP_MESSAGE_DATA_FETCH +}; + +/* + mailimap_message_data is an information related to a message + + - number is the number or the unique identifier of the message + + - type is the type of information, this value can be + MAILIMAP_MESSAGE_DATA_EXPUNGE or MAILIMAP_MESSAGE_DATA_FETCH + + - msg_att is the message data +*/ + +struct mailimap_message_data { + uint32_t mdt_number; + int mdt_type; + struct mailimap_msg_att * mdt_msg_att; /* can be NULL */ + /* if type = EXPUNGE, can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_message_data * +mailimap_message_data_new(uint32_t mdt_number, int mdt_type, + struct mailimap_msg_att * mdt_msg_att); + +LIBETPAN_EXPORT +void +mailimap_message_data_free(struct mailimap_message_data * msg_data); + + + +/* this the type of the message attributes */ + +enum { + MAILIMAP_MSG_ATT_ITEM_ERROR, /* on parse error */ + MAILIMAP_MSG_ATT_ITEM_DYNAMIC, /* dynamic message attributes (flags) */ + MAILIMAP_MSG_ATT_ITEM_STATIC, /* static messages attributes + (message content) */ + MAILIMAP_MSG_ATT_ITEM_EXTENSION /* extension data */ +}; + +/* + mailimap_msg_att_item is a message attribute + + - type is the type of message attribute, the value can be + MAILIMAP_MSG_ATT_ITEM_DYNAMIC, MAILIMAP_MSG_ATT_ITEM_STATIC or MAILIMAP_MSG_ATT_ITEM_EXTENSION + + - att_dyn is a dynamic message attribute when type is + MAILIMAP_MSG_ATT_ITEM_DYNAMIC + + - att_static is a static message attribute when type is + MAILIMAP_MSG_ATT_ITEM_STATIC + + - att_extension_data is an extension data. +*/ + +struct mailimap_msg_att_item { + int att_type; + union { + struct mailimap_msg_att_dynamic * att_dyn; /* can be NULL */ + struct mailimap_msg_att_static * att_static; /* can be NULL */ + struct mailimap_extension_data * att_extension_data; /* can be NULL */ + } att_data; +}; + +LIBETPAN_EXPORT +struct mailimap_msg_att_item * +mailimap_msg_att_item_new(int att_type, + struct mailimap_msg_att_dynamic * att_dyn, + struct mailimap_msg_att_static * att_static, + struct mailimap_extension_data * att_extension_data); + +LIBETPAN_EXPORT +void +mailimap_msg_att_item_free(struct mailimap_msg_att_item * item); + + +/* + mailimap_msg_att is a list of attributes + + - list is a list of message attributes + + - number is the message number or unique identifier, this field + has been added for implementation purpose +*/ + +struct mailimap_msg_att { + clist * att_list; /* list of (struct mailimap_msg_att_item *) */ + /* != NULL */ + uint32_t att_number; /* extra field to store the message number, + used for mailimap */ +}; + +LIBETPAN_EXPORT +struct mailimap_msg_att * mailimap_msg_att_new(clist * att_list); + +LIBETPAN_EXPORT +void mailimap_msg_att_free(struct mailimap_msg_att * msg_att); + + +/* + mailimap_msg_att_dynamic is a dynamic message attribute + + - list is a list of flags (that have been fetched) +*/ + +struct mailimap_msg_att_dynamic { + clist * att_list; /* list of (struct mailimap_flag_fetch *) */ + /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_msg_att_dynamic * +mailimap_msg_att_dynamic_new(clist * att_list); + +LIBETPAN_EXPORT +void +mailimap_msg_att_dynamic_free(struct mailimap_msg_att_dynamic * msg_att_dyn); + + + +/* + mailimap_msg_att_body_section is a MIME part content + + - section is the location of the MIME part in the message + + - origin_octet is the offset of the requested part of the MIME part + + - body_part is the content or partial content of the MIME part, + should be allocated through a MMAPString + + - length is the size of the content +*/ + +struct mailimap_msg_att_body_section { + struct mailimap_section * sec_section; /* != NULL */ + uint32_t sec_origin_octet; + char * sec_body_part; /* can be NULL */ + size_t sec_length; +}; + +LIBETPAN_EXPORT +struct mailimap_msg_att_body_section * +mailimap_msg_att_body_section_new(struct mailimap_section * section, + uint32_t sec_origin_octet, + char * sec_body_part, + size_t sec_length); + +LIBETPAN_EXPORT +void +mailimap_msg_att_body_section_free(struct mailimap_msg_att_body_section * + msg_att_body_section); + + + +/* + this is the type of static message attribute +*/ + +enum { + MAILIMAP_MSG_ATT_ERROR, /* on parse error */ + MAILIMAP_MSG_ATT_ENVELOPE, /* this is the fields that can be + parsed by the server */ + MAILIMAP_MSG_ATT_INTERNALDATE, /* this is the message date kept + by the server */ + MAILIMAP_MSG_ATT_RFC822, /* this is the message content + (header and body) */ + MAILIMAP_MSG_ATT_RFC822_HEADER, /* this is the message header */ + MAILIMAP_MSG_ATT_RFC822_TEXT, /* this is the message text part */ + MAILIMAP_MSG_ATT_RFC822_SIZE, /* this is the size of the message content */ + MAILIMAP_MSG_ATT_BODY, /* this is the MIME description of + the message */ + MAILIMAP_MSG_ATT_BODYSTRUCTURE, /* this is the MIME description of the + message with additional information */ + MAILIMAP_MSG_ATT_BODY_SECTION, /* this is a MIME part content */ + MAILIMAP_MSG_ATT_UID /* this is the message unique identifier */ +}; + +/* + mailimap_msg_att_static is a given part of the message + + - type is the type of the static message attribute, the value can be + MAILIMAP_MSG_ATT_ENVELOPE, MAILIMAP_MSG_ATT_INTERNALDATE, + MAILIMAP_MSG_ATT_RFC822, MAILIMAP_MSG_ATT_RFC822_HEADER, + MAILIMAP_MSG_ATT_RFC822_TEXT, MAILIMAP_MSG_ATT_RFC822_SIZE, + MAILIMAP_MSG_ATT_BODY, MAILIMAP_MSG_ATT_BODYSTRUCTURE, + MAILIMAP_MSG_ATT_BODY_SECTION, MAILIMAP_MSG_ATT_UID + + - env is the headers parsed by the server if type is + MAILIMAP_MSG_ATT_ENVELOPE + + - internal_date is the date of message kept by the server if type is + MAILIMAP_MSG_ATT_INTERNALDATE + + - rfc822 is the message content if type is MAILIMAP_MSG_ATT_RFC822, + should be allocated through a MMAPString + + - rfc822_header is the message header if type is + MAILIMAP_MSG_ATT_RFC822_HEADER, should be allocated through a MMAPString + + - rfc822_text is the message text part if type is + MAILIMAP_MSG_ATT_RFC822_TEXT, should be allocated through a MMAPString + + - rfc822_size is the message size if type is MAILIMAP_MSG_ATT_SIZE + + - body is the MIME description of the message + + - bodystructure is the MIME description of the message with additional + information + + - body_section is a MIME part content + + - uid is a unique message identifier +*/ + +struct mailimap_msg_att_static { + int att_type; + union { + struct mailimap_envelope * att_env; /* can be NULL */ + struct mailimap_date_time * att_internal_date; /* can be NULL */ + struct { + char * att_content; /* can be NULL */ + size_t att_length; + } att_rfc822; + struct { + char * att_content; /* can be NULL */ + size_t att_length; + } att_rfc822_header; + struct { + char * att_content; /* can be NULL */ + size_t att_length; + } att_rfc822_text; + uint32_t att_rfc822_size; + struct mailimap_body * att_bodystructure; /* can be NULL */ + struct mailimap_body * att_body; /* can be NULL */ + struct mailimap_msg_att_body_section * att_body_section; /* can be NULL */ + uint32_t att_uid; + } att_data; +}; + +LIBETPAN_EXPORT +struct mailimap_msg_att_static * +mailimap_msg_att_static_new(int att_type, struct mailimap_envelope * att_env, + struct mailimap_date_time * att_internal_date, + char * att_rfc822, + char * att_rfc822_header, + char * att_rfc822_text, + size_t att_length, + uint32_t att_rfc822_size, + struct mailimap_body * att_bodystructure, + struct mailimap_body * att_body, + struct mailimap_msg_att_body_section * att_body_section, + uint32_t att_uid); + +LIBETPAN_EXPORT +void +mailimap_msg_att_static_free(struct mailimap_msg_att_static * item); + + + +/* this is the type of a response element */ + +enum { + MAILIMAP_RESP_ERROR, /* on parse error */ + MAILIMAP_RESP_CONT_REQ, /* continuation request */ + MAILIMAP_RESP_RESP_DATA /* response data */ +}; + +/* + mailimap_cont_req_or_resp_data is a response element + + - type is the type of response, the value can be MAILIMAP_RESP_CONT_REQ + or MAILIMAP_RESP_RESP_DATA + + - cont_req is a continuation request + + - resp_data is a reponse data +*/ + +struct mailimap_cont_req_or_resp_data { + int rsp_type; + union { + struct mailimap_continue_req * rsp_cont_req; /* can be NULL */ + struct mailimap_response_data * rsp_resp_data; /* can be NULL */ + } rsp_data; +}; + +LIBETPAN_EXPORT +struct mailimap_cont_req_or_resp_data * +mailimap_cont_req_or_resp_data_new(int rsp_type, + struct mailimap_continue_req * rsp_cont_req, + struct mailimap_response_data * rsp_resp_data); + +LIBETPAN_EXPORT +void +mailimap_cont_req_or_resp_data_free(struct mailimap_cont_req_or_resp_data * + cont_req_or_resp_data); + + +/* + mailimap_response is a list of response elements + + - cont_req_or_resp_data_list is a list of response elements + + - resp_done is an ending response element +*/ + +struct mailimap_response { + clist * rsp_cont_req_or_resp_data_list; + /* list of (struct mailiap_cont_req_or_resp_data *) */ + /* can be NULL */ + struct mailimap_response_done * rsp_resp_done; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_response * +mailimap_response_new(clist * rsp_cont_req_or_resp_data_list, + struct mailimap_response_done * rsp_resp_done); + +LIBETPAN_EXPORT +void +mailimap_response_free(struct mailimap_response * resp); + + + +/* this is the type of an untagged response */ + +enum { + MAILIMAP_RESP_DATA_TYPE_ERROR, /* on parse error */ + MAILIMAP_RESP_DATA_TYPE_COND_STATE, /* condition state response */ + MAILIMAP_RESP_DATA_TYPE_COND_BYE, /* BYE response (server is about + to close the connection) */ + MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA, /* response related to a mailbox */ + MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA, /* response related to a message */ + MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA, /* capability information */ + MAILIMAP_RESP_DATA_TYPE_EXTENSION_DATA /* data parsed by extension */ +}; + +/* + mailimap_reponse_data is an untagged response + + - type is the type of the untagged response, it can be + MAILIMAP_RESP_DATA_COND_STATE, MAILIMAP_RESP_DATA_COND_BYE, + MAILIMAP_RESP_DATA_MAILBOX_DATA, MAILIMAP_RESP_DATA_MESSAGE_DATA + or MAILIMAP_RESP_DATA_CAPABILITY_DATA + + - cond_state is a condition state response + + - bye is a BYE response (server is about to close the connection) + + - mailbox_data is a response related to a mailbox + + - message_data is a response related to a message + + - capability is information about capabilities +*/ + +struct mailimap_response_data { + int rsp_type; + union { + struct mailimap_resp_cond_state * rsp_cond_state; /* can be NULL */ + struct mailimap_resp_cond_bye * rsp_bye; /* can be NULL */ + struct mailimap_mailbox_data * rsp_mailbox_data; /* can be NULL */ + struct mailimap_message_data * rsp_message_data; /* can be NULL */ + struct mailimap_capability_data * rsp_capability_data; /* can be NULL */ + struct mailimap_extension_data * rsp_extension_data; /* can be NULL */ + } rsp_data; +}; + +LIBETPAN_EXPORT +struct mailimap_response_data * +mailimap_response_data_new(int rsp_type, + struct mailimap_resp_cond_state * rsp_cond_state, + struct mailimap_resp_cond_bye * rsp_bye, + struct mailimap_mailbox_data * rsp_mailbox_data, + struct mailimap_message_data * rsp_message_data, + struct mailimap_capability_data * rsp_capability_data, + struct mailimap_extension_data * rsp_extension_data); + +LIBETPAN_EXPORT +void +mailimap_response_data_free(struct mailimap_response_data * resp_data); + + + +/* this is the type of an ending response */ + +enum { + MAILIMAP_RESP_DONE_TYPE_ERROR, /* on parse error */ + MAILIMAP_RESP_DONE_TYPE_TAGGED, /* tagged response */ + MAILIMAP_RESP_DONE_TYPE_FATAL /* fatal error response */ +}; + +/* + mailimap_response_done is an ending response + + - type is the type of the ending response + + - tagged is a tagged response + + - fatal is a fatal error response +*/ + +struct mailimap_response_done { + int rsp_type; + union { + struct mailimap_response_tagged * rsp_tagged; /* can be NULL */ + struct mailimap_response_fatal * rsp_fatal; /* can be NULL */ + } rsp_data; +}; + +LIBETPAN_EXPORT +struct mailimap_response_done * +mailimap_response_done_new(int rsp_type, + struct mailimap_response_tagged * rsp_tagged, + struct mailimap_response_fatal * rsp_fatal); + +LIBETPAN_EXPORT +void mailimap_response_done_free(struct mailimap_response_done * + resp_done); + + +/* + mailimap_response_fatal is a fatal error response + + - bye is a BYE response text +*/ + +struct mailimap_response_fatal { + struct mailimap_resp_cond_bye * rsp_bye; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_response_fatal * +mailimap_response_fatal_new(struct mailimap_resp_cond_bye * rsp_bye); + +LIBETPAN_EXPORT +void mailimap_response_fatal_free(struct mailimap_response_fatal * resp_fatal); + + + +/* + mailimap_response_tagged is a tagged response + + - tag is the sent tag, should be allocated with malloc() + + - cond_state is a condition state response +*/ + +struct mailimap_response_tagged { + char * rsp_tag; /* != NULL */ + struct mailimap_resp_cond_state * rsp_cond_state; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_response_tagged * +mailimap_response_tagged_new(char * rsp_tag, + struct mailimap_resp_cond_state * rsp_cond_state); + +LIBETPAN_EXPORT +void +mailimap_response_tagged_free(struct mailimap_response_tagged * tagged); + + +/* this is the type of an authentication condition response */ + +enum { + MAILIMAP_RESP_COND_AUTH_ERROR, /* on parse error */ + MAILIMAP_RESP_COND_AUTH_OK, /* authentication is needed */ + MAILIMAP_RESP_COND_AUTH_PREAUTH /* authentication is not needed */ +}; + +/* + mailimap_resp_cond_auth is an authentication condition response + + - type is the type of the authentication condition response, + the value can be MAILIMAP_RESP_COND_AUTH_OK or + MAILIMAP_RESP_COND_AUTH_PREAUTH + + - text is a text response +*/ + +struct mailimap_resp_cond_auth { + int rsp_type; + struct mailimap_resp_text * rsp_text; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_resp_cond_auth * +mailimap_resp_cond_auth_new(int rsp_type, + struct mailimap_resp_text * rsp_text); + +LIBETPAN_EXPORT +void +mailimap_resp_cond_auth_free(struct mailimap_resp_cond_auth * cond_auth); + + + +/* + mailimap_resp_cond_bye is a BYE response + + - text is a text response +*/ + +struct mailimap_resp_cond_bye { + struct mailimap_resp_text * rsp_text; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_resp_cond_bye * +mailimap_resp_cond_bye_new(struct mailimap_resp_text * rsp_text); + +LIBETPAN_EXPORT +void +mailimap_resp_cond_bye_free(struct mailimap_resp_cond_bye * cond_bye); + + + +/* this is the type of a condition state response */ + +enum { + MAILIMAP_RESP_COND_STATE_OK, + MAILIMAP_RESP_COND_STATE_NO, + MAILIMAP_RESP_COND_STATE_BAD +}; + +/* + mailimap_resp_cond_state is a condition state reponse + + - type is the type of the condition state response + + - text is a text response +*/ + +struct mailimap_resp_cond_state { + int rsp_type; + struct mailimap_resp_text * rsp_text; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_resp_cond_state * +mailimap_resp_cond_state_new(int rsp_type, + struct mailimap_resp_text * rsp_text); + +LIBETPAN_EXPORT +void +mailimap_resp_cond_state_free(struct mailimap_resp_cond_state * cond_state); + + + +/* + mailimap_resp_text is a text response + + - resp_code is a response code + + - text is a human readable text, should be allocated with malloc() +*/ + +struct mailimap_resp_text { + struct mailimap_resp_text_code * rsp_code; /* can be NULL */ + char * rsp_text; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_resp_text * +mailimap_resp_text_new(struct mailimap_resp_text_code * resp_code, + char * rsp_text); + +LIBETPAN_EXPORT +void mailimap_resp_text_free(struct mailimap_resp_text * resp_text); + + + +/* this is the type of the response code */ + +enum { + MAILIMAP_RESP_TEXT_CODE_ALERT, /* ALERT response */ + MAILIMAP_RESP_TEXT_CODE_BADCHARSET, /* BADCHARSET response */ + MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA, /* CAPABILITY response */ + MAILIMAP_RESP_TEXT_CODE_PARSE, /* PARSE response */ + MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS, /* PERMANENTFLAGS response */ + MAILIMAP_RESP_TEXT_CODE_READ_ONLY, /* READONLY response */ + MAILIMAP_RESP_TEXT_CODE_READ_WRITE, /* READWRITE response */ + MAILIMAP_RESP_TEXT_CODE_TRY_CREATE, /* TRYCREATE response */ + MAILIMAP_RESP_TEXT_CODE_UIDNEXT, /* UIDNEXT response */ + MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY, /* UIDVALIDITY response */ + MAILIMAP_RESP_TEXT_CODE_UNSEEN, /* UNSEEN response */ + MAILIMAP_RESP_TEXT_CODE_OTHER, /* other type of response */ + MAILIMAP_RESP_TEXT_CODE_EXTENSION /* extension response */ +}; + +/* + mailimap_resp_text_code is a response code + + - type is the type of the response code, the value can be + MAILIMAP_RESP_TEXT_CODE_ALERT, MAILIMAP_RESP_TEXT_CODE_BADCHARSET, + MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA, MAILIMAP_RESP_TEXT_CODE_PARSE, + MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS, MAILIMAP_RESP_TEXT_CODE_READ_ONLY, + MAILIMAP_RESP_TEXT_CODE_READ_WRITE, MAILIMAP_RESP_TEXT_CODE_TRY_CREATE, + MAILIMAP_RESP_TEXT_CODE_UIDNEXT, MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY, + MAILIMAP_RESP_TEXT_CODE_UNSEEN or MAILIMAP_RESP_TEXT_CODE_OTHER + + - badcharset is a list of charsets if type + is MAILIMAP_RESP_TEXT_CODE_BADCHARSET, each element should be + allocated with malloc() + + - cap_data is a list of capabilities + + - perm_flags is a list of flags, this is the flags that can be changed + permanently on the messages of the mailbox. + + - uidnext is the next unique identifier of a message + + - uidvalidity is the unique identifier validity value + + - first_unseen is the number of the first message without the \Seen flag + + - atom is a keyword for an extension response code, should be allocated + with malloc() + + - atom_value is the data related with the extension response code, + should be allocated with malloc() +*/ + +struct mailimap_resp_text_code { + int rc_type; + union { + clist * rc_badcharset; /* list of astring (char *) */ + /* can be NULL */ + struct mailimap_capability_data * rc_cap_data; /* != NULL */ + clist * rc_perm_flags; /* list of (struct mailimap_flag_perm *) */ + /* can be NULL */ + uint32_t rc_uidnext; + uint32_t rc_uidvalidity; + uint32_t rc_first_unseen; + struct { + char * atom_name; /* can be NULL */ + char * atom_value; /* can be NULL */ + } rc_atom; + struct mailimap_extension_data * rc_ext_data; /* can be NULL */ + } rc_data; +}; + +LIBETPAN_EXPORT +struct mailimap_resp_text_code * +mailimap_resp_text_code_new(int rc_type, clist * rc_badcharset, + struct mailimap_capability_data * rc_cap_data, + clist * rc_perm_flags, + uint32_t rc_uidnext, uint32_t rc_uidvalidity, + uint32_t rc_first_unseen, char * rc_atom, char * rc_atom_value, + struct mailimap_extension_data * rc_ext_data); + +LIBETPAN_EXPORT +void +mailimap_resp_text_code_free(struct mailimap_resp_text_code * resp_text_code); + + +/* + mailimap_section is a MIME part section identifier + + section_spec is the MIME section identifier +*/ + +struct mailimap_section { + struct mailimap_section_spec * sec_spec; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new(struct mailimap_section_spec * sec_spec); + +LIBETPAN_EXPORT +void mailimap_section_free(struct mailimap_section * section); + + +/* this is the type of the message/rfc822 part description */ + +enum { + MAILIMAP_SECTION_MSGTEXT_HEADER, /* header fields part of the + message */ + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, /* given header fields of the + message */ + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT, /* header fields of the + message except the given */ + MAILIMAP_SECTION_MSGTEXT_TEXT /* text part */ +}; + +/* + mailimap_section_msgtext is a message/rfc822 part description + + - type is the type of the content part and the value can be + MAILIMAP_SECTION_MSGTEXT_HEADER, MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT + or MAILIMAP_SECTION_MSGTEXT_TEXT + + - header_list is the list of headers when type is + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS or + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT +*/ + +struct mailimap_section_msgtext { + int sec_type; + struct mailimap_header_list * sec_header_list; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_section_msgtext * +mailimap_section_msgtext_new(int sec_type, + struct mailimap_header_list * sec_header_list); + +LIBETPAN_EXPORT +void +mailimap_section_msgtext_free(struct mailimap_section_msgtext * msgtext); + + + +/* + mailimap_section_part is the MIME part location in a message + + - section_id is a list of number index of the sub-part in the mail structure, + each element should be allocated with malloc() + +*/ + +struct mailimap_section_part { + clist * sec_id; /* list of nz-number (uint32_t *) */ + /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_section_part * +mailimap_section_part_new(clist * sec_id); + +LIBETPAN_EXPORT +void +mailimap_section_part_free(struct mailimap_section_part * section_part); + + + +/* this is the type of section specification */ + +enum { + MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT, /* if requesting data of the root + MIME message/rfc822 part */ + MAILIMAP_SECTION_SPEC_SECTION_PART /* location of the MIME part + in the message */ +}; + +/* + mailimap_section_spec is a section specification + + - type is the type of the section specification, the value can be + MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT or + MAILIMAP_SECTION_SPEC_SECTION_PART + + - section_msgtext is a message/rfc822 part description if type is + MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT + + - section_part is a body part location in the message if type is + MAILIMAP_SECTION_SPEC_SECTION_PART + + - section_text is a body part location for a given MIME part, + this can be NULL if the body of the part is requested (and not + the MIME header). +*/ + +struct mailimap_section_spec { + int sec_type; + union { + struct mailimap_section_msgtext * sec_msgtext; /* can be NULL */ + struct mailimap_section_part * sec_part; /* can be NULL */ + } sec_data; + struct mailimap_section_text * sec_text; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_section_spec * +mailimap_section_spec_new(int sec_type, + struct mailimap_section_msgtext * sec_msgtext, + struct mailimap_section_part * sec_part, + struct mailimap_section_text * sec_text); + +LIBETPAN_EXPORT +void +mailimap_section_spec_free(struct mailimap_section_spec * section_spec); + + + +/* this is the type of body part location for a given MIME part */ + +enum { + MAILIMAP_SECTION_TEXT_ERROR, /* on parse error **/ + MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT, /* if the MIME type is + message/rfc822, headers or text + can be requested */ + MAILIMAP_SECTION_TEXT_MIME /* for all MIME types, + MIME headers can be requested */ +}; + +/* + mailimap_section_text is the body part location for a given MIME part + + - type can be MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT or + MAILIMAP_SECTION_TEXT_MIME + + - section_msgtext is the part of the MIME part when MIME type is + message/rfc822 than can be requested, when type is + MAILIMAP_TEXT_SECTION_MSGTEXT +*/ + +struct mailimap_section_text { + int sec_type; + struct mailimap_section_msgtext * sec_msgtext; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_section_text * +mailimap_section_text_new(int sec_type, + struct mailimap_section_msgtext * sec_msgtext); + +LIBETPAN_EXPORT +void +mailimap_section_text_free(struct mailimap_section_text * section_text); + + + + + + + + + + +/* ************************************************************************* */ +/* the following part concerns only the IMAP command that are sent */ + + +/* + mailimap_set_item is a message set + + - first is the first message of the set + - last is the last message of the set + + this can be message numbers of message unique identifiers +*/ + +struct mailimap_set_item { + uint32_t set_first; + uint32_t set_last; +}; + +LIBETPAN_EXPORT +struct mailimap_set_item * +mailimap_set_item_new(uint32_t set_first, uint32_t set_last); + +LIBETPAN_EXPORT +void mailimap_set_item_free(struct mailimap_set_item * set_item); + + + +/* + set is a list of message sets + + - list is a list of message sets +*/ + +struct mailimap_set { + clist * set_list; /* list of (struct mailimap_set_item *) */ +}; + +LIBETPAN_EXPORT +struct mailimap_set * mailimap_set_new(clist * list); + +LIBETPAN_EXPORT +void mailimap_set_free(struct mailimap_set * set); + + +/* + mailimap_date is a date + + - day is the day in the month (1 to 31) + + - month (1 to 12) + + - year (4 digits) +*/ + +struct mailimap_date { + int dt_day; + int dt_month; + int dt_year; +}; + +LIBETPAN_EXPORT +struct mailimap_date * +mailimap_date_new(int dt_day, int dt_month, int dt_year); + +LIBETPAN_EXPORT +void mailimap_date_free(struct mailimap_date * date); + + + + +/* this is the type of fetch attribute for a given message */ + +enum { + MAILIMAP_FETCH_ATT_ENVELOPE, /* to fetch the headers parsed by + the IMAP server */ + MAILIMAP_FETCH_ATT_FLAGS, /* to fetch the flags */ + MAILIMAP_FETCH_ATT_INTERNALDATE, /* to fetch the date of the message + kept by the server */ + MAILIMAP_FETCH_ATT_RFC822, /* to fetch the entire message */ + MAILIMAP_FETCH_ATT_RFC822_HEADER, /* to fetch the headers */ + MAILIMAP_FETCH_ATT_RFC822_SIZE, /* to fetch the size */ + MAILIMAP_FETCH_ATT_RFC822_TEXT, /* to fetch the text part */ + MAILIMAP_FETCH_ATT_BODY, /* to fetch the MIME structure */ + MAILIMAP_FETCH_ATT_BODYSTRUCTURE, /* to fetch the MIME structure with + additional information */ + MAILIMAP_FETCH_ATT_UID, /* to fetch the unique identifier */ + MAILIMAP_FETCH_ATT_BODY_SECTION, /* to fetch a given part */ + MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION, /* to fetch a given part without + marking the message as read */ + MAILIMAP_FETCH_ATT_EXTENSION +}; + + +/* + mailimap_fetch_att is the description of the fetch attribute + + - type is the type of fetch attribute, the value can be + MAILIMAP_FETCH_ATT_ENVELOPE, MAILIMAP_FETCH_ATT_FLAGS, + MAILIMAP_FETCH_ATT_INTERNALDATE, MAILIMAP_FETCH_ATT_RFC822, + MAILIMAP_FETCH_ATT_RFC822_HEADER, MAILIMAP_FETCH_ATT_RFC822_SIZE, + MAILIMAP_FETCH_ATT_RFC822_TEXT, MAILIMAP_FETCH_ATT_BODY, + MAILIMAP_FETCH_ATT_BODYSTRUCTURE, MAILIMAP_FETCH_ATT_UID, + MAILIMAP_FETCH_ATT_BODY_SECTION, MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION, + MAILIMAP_FETCH_ATT_EXTENSION + + - section is the location of the part to fetch if type is + MAILIMAP_FETCH_ATT_BODY_SECTION or MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION + + - offset is the first byte to fetch in the given part + + - size is the maximum size of the part to fetch + + - att_extension: keyword to send when MAILIMAP_FETCH_ATT_EXTENSION is used +*/ + +struct mailimap_fetch_att { + int att_type; + struct mailimap_section * att_section; + uint32_t att_offset; + uint32_t att_size; + char * att_extension; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new(int att_type, struct mailimap_section * att_section, + uint32_t att_offset, uint32_t att_size, char * att_extension); + + +LIBETPAN_EXPORT +void mailimap_fetch_att_free(struct mailimap_fetch_att * fetch_att); + + +/* this is the type of a FETCH operation */ + +enum { + MAILIMAP_FETCH_TYPE_ALL, /* equivalent to (FLAGS INTERNALDATE + RFC822.SIZE ENVELOPE) */ + MAILIMAP_FETCH_TYPE_FULL, /* equivalent to (FLAGS INTERNALDATE + RFC822.SIZE ENVELOPE BODY) */ + MAILIMAP_FETCH_TYPE_FAST, /* equivalent to (FLAGS INTERNALDATE + RFC822.SIZE) */ + MAILIMAP_FETCH_TYPE_FETCH_ATT, /* when there is only of fetch + attribute */ + MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST /* when there is a list of fetch + attributes */ +}; + +/* + mailimap_fetch_type is the description of the FETCH operation + + - type can be MAILIMAP_FETCH_TYPE_ALL, MAILIMAP_FETCH_TYPE_FULL, + MAILIMAP_FETCH_TYPE_FAST, MAILIMAP_FETCH_TYPE_FETCH_ATT or + MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST + + - fetch_att is a fetch attribute if type is MAILIMAP_FETCH_TYPE_FETCH_ATT + + - fetch_att_list is a list of fetch attributes if type is + MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST +*/ + +struct mailimap_fetch_type { + int ft_type; + union { + struct mailimap_fetch_att * ft_fetch_att; + clist * ft_fetch_att_list; /* list of (struct mailimap_fetch_att *) */ + } ft_data; +}; + +LIBETPAN_EXPORT +struct mailimap_fetch_type * +mailimap_fetch_type_new(int ft_type, + struct mailimap_fetch_att * ft_fetch_att, + clist * ft_fetch_att_list); + + +LIBETPAN_EXPORT +void mailimap_fetch_type_free(struct mailimap_fetch_type * fetch_type); + + + +/* + mailimap_store_att_flags is the description of the STORE operation + (change flags of a message) + + - sign can be 0 (set flag), +1 (add flag) or -1 (remove flag) + + - silent has a value of 1 if the flags are changed with no server + response + + - flag_list is the list of flags to change +*/ + +struct mailimap_store_att_flags { + int fl_sign; + int fl_silent; + struct mailimap_flag_list * fl_flag_list; +}; + +LIBETPAN_EXPORT +struct mailimap_store_att_flags * +mailimap_store_att_flags_new(int fl_sign, int fl_silent, + struct mailimap_flag_list * fl_flag_list); + +LIBETPAN_EXPORT +void mailimap_store_att_flags_free(struct mailimap_store_att_flags * + store_att_flags); + + + +/* this is the condition of the SEARCH operation */ + +enum { + MAILIMAP_SEARCH_KEY_ALL, /* all messages */ + MAILIMAP_SEARCH_KEY_ANSWERED, /* messages with the flag \Answered */ + MAILIMAP_SEARCH_KEY_BCC, /* messages whose Bcc field contains the + given string */ + MAILIMAP_SEARCH_KEY_BEFORE, /* messages whose internal date is earlier + than the specified date */ + MAILIMAP_SEARCH_KEY_BODY, /* message that contains the given string + (in header and text parts) */ + MAILIMAP_SEARCH_KEY_CC, /* messages whose Cc field contains the + given string */ + MAILIMAP_SEARCH_KEY_DELETED, /* messages with the flag \Deleted */ + MAILIMAP_SEARCH_KEY_FLAGGED, /* messages with the flag \Flagged */ + MAILIMAP_SEARCH_KEY_FROM, /* messages whose From field contains the + given string */ + MAILIMAP_SEARCH_KEY_KEYWORD, /* messages with the flag keyword set */ + MAILIMAP_SEARCH_KEY_NEW, /* messages with the flag \Recent and not + the \Seen flag */ + MAILIMAP_SEARCH_KEY_OLD, /* messages that do not have the + \Recent flag set */ + MAILIMAP_SEARCH_KEY_ON, /* messages whose internal date is the + specified date */ + MAILIMAP_SEARCH_KEY_RECENT, /* messages with the flag \Recent */ + MAILIMAP_SEARCH_KEY_SEEN, /* messages with the flag \Seen */ + MAILIMAP_SEARCH_KEY_SINCE, /* messages whose internal date is later + than specified date */ + MAILIMAP_SEARCH_KEY_SUBJECT, /* messages whose Subject field contains the + given string */ + MAILIMAP_SEARCH_KEY_TEXT, /* messages whose text part contains the + given string */ + MAILIMAP_SEARCH_KEY_TO, /* messages whose To field contains the + given string */ + MAILIMAP_SEARCH_KEY_UNANSWERED, /* messages with no flag \Answered */ + MAILIMAP_SEARCH_KEY_UNDELETED, /* messages with no flag \Deleted */ + MAILIMAP_SEARCH_KEY_UNFLAGGED, /* messages with no flag \Flagged */ + MAILIMAP_SEARCH_KEY_UNKEYWORD, /* messages with no flag keyword */ + MAILIMAP_SEARCH_KEY_UNSEEN, /* messages with no flag \Seen */ + MAILIMAP_SEARCH_KEY_DRAFT, /* messages with no flag \Draft */ + MAILIMAP_SEARCH_KEY_HEADER, /* messages whose given field + contains the given string */ + MAILIMAP_SEARCH_KEY_LARGER, /* messages whose size is larger then + the given size */ + MAILIMAP_SEARCH_KEY_NOT, /* not operation of the condition */ + MAILIMAP_SEARCH_KEY_OR, /* or operation between two conditions */ + MAILIMAP_SEARCH_KEY_SENTBEFORE, /* messages whose date given in Date header + is earlier than the specified date */ + MAILIMAP_SEARCH_KEY_SENTON, /* messages whose date given in Date header + is the specified date */ + MAILIMAP_SEARCH_KEY_SENTSINCE, /* messages whose date given in Date header + is later than specified date */ + MAILIMAP_SEARCH_KEY_SMALLER, /* messages whose size is smaller than + the given size */ + MAILIMAP_SEARCH_KEY_UID, /* messages whose unique identifiers are + in the given range */ + MAILIMAP_SEARCH_KEY_UNDRAFT, /* messages with no flag \Draft */ + MAILIMAP_SEARCH_KEY_SET, /* messages whose number (or unique + identifiers in case of UID SEARCH) are + in the given range */ + MAILIMAP_SEARCH_KEY_MULTIPLE, /* the boolean operator between the + conditions is AND */ + MAILIMAP_SEARCH_KEY_MODSEQ, /* mod sequence */ + MAILIMAP_SEARCH_KEY_XGMTHRID, /* Gmail thread id */ + MAILIMAP_SEARCH_KEY_XGMMSGID, /* Gmail Message id */ + MAILIMAP_SEARCH_KEY_XGMRAW /* Gmail RAW expression */ +}; + +/* + mailimap_search_key is the condition on the messages to return + + - type is the type of the condition + + - bcc is the text to search in the Bcc field when type is + MAILIMAP_SEARCH_KEY_BCC, should be allocated with malloc() + + - before is a date when type is MAILIMAP_SEARCH_KEY_BEFORE + + - body is the text to search in the message when type is + MAILIMAP_SEARCH_KEY_BODY, should be allocated with malloc() + + - cc is the text to search in the Cc field when type is + MAILIMAP_SEARCH_KEY_CC, should be allocated with malloc() + + - from is the text to search in the From field when type is + MAILIMAP_SEARCH_KEY_FROM, should be allocated with malloc() + + - keyword is the keyword flag name when type is MAILIMAP_SEARCH_KEY_KEYWORD, + should be allocated with malloc() + + - on is a date when type is MAILIMAP_SEARCH_KEY_ON + + - since is a date when type is MAILIMAP_SEARCH_KEY_SINCE + + - subject is the text to search in the Subject field when type is + MAILIMAP_SEARCH_KEY_SUBJECT, should be allocated with malloc() + + - text is the text to search in the text part of the message when + type is MAILIMAP_SEARCH_KEY_TEXT, should be allocated with malloc() + + - to is the text to search in the To field when type is + MAILIMAP_SEARCH_KEY_TO, should be allocated with malloc() + + - unkeyword is the keyword flag name when type is + MAILIMAP_SEARCH_KEY_UNKEYWORD, should be allocated with malloc() + + - header_name is the header name when type is MAILIMAP_SEARCH_KEY_HEADER, + should be allocated with malloc() + + - header_value is the text to search in the given header when type is + MAILIMAP_SEARCH_KEY_HEADER, should be allocated with malloc() + + - larger is a size when type is MAILIMAP_SEARCH_KEY_LARGER + + - not is a condition when type is MAILIMAP_SEARCH_KEY_NOT + + - or1 is a condition when type is MAILIMAP_SEARCH_KEY_OR + + - or2 is a condition when type is MAILIMAP_SEARCH_KEY_OR + + - sentbefore is a date when type is MAILIMAP_SEARCH_KEY_SENTBEFORE + + - senton is a date when type is MAILIMAP_SEARCH_KEY_SENTON + + - sentsince is a date when type is MAILIMAP_SEARCH_KEY_SENTSINCE + + - smaller is a size when type is MAILIMAP_SEARCH_KEY_SMALLER + + - uid is a set of messages when type is MAILIMAP_SEARCH_KEY_UID + + - set is a set of messages when type is MAILIMAP_SEARCH_KEY_SET + + - xgmthrid is a number of the gmail thread id when type is MAILIMAP_SEARCH_KEY_XGMTHRID + use mailimap_search_key_new_xgmthrid() for this key + + - xgmmsgid is a gmail message id expression when type is MAILIMAP_SEARCH_KEY_XGMMSGID + use mailimap_search_key_new_xgmmsgid() for this key + + - xgmraw is a raw gmail search expression when type is MAILIMAP_SEARCH_KEY_XGMRAW + use mailimap_search_key_new_xgmraw() for this key + + - multiple is a set of message when type is MAILIMAP_SEARCH_KEY_MULTIPLE +*/ + +enum { + MAILIMAP_SEARCH_KEY_MODSEQ_ENTRY_TYPE_REQ_PRIV, + MAILIMAP_SEARCH_KEY_MODSEQ_ENTRY_TYPE_REQ_SHARED, + MAILIMAP_SEARCH_KEY_MODSEQ_ENTRY_TYPE_REQ_ALL, +}; + +struct mailimap_search_key { + int sk_type; + union { + char * sk_bcc; + struct mailimap_date * sk_before; + char * sk_body; + char * sk_cc; + char * sk_from; + char * sk_keyword; + struct mailimap_date * sk_on; + struct mailimap_date * sk_since; + char * sk_subject; + char * sk_text; + char * sk_to; + char * sk_unkeyword; + struct { + char * sk_header_name; + char * sk_header_value; + } sk_header; + uint32_t sk_larger; + struct mailimap_search_key * sk_not; + struct { + struct mailimap_search_key * sk_or1; + struct mailimap_search_key * sk_or2; + } sk_or; + struct mailimap_date * sk_sentbefore; + struct mailimap_date * sk_senton; + struct mailimap_date * sk_sentsince; + uint32_t sk_smaller; + struct mailimap_set * sk_uid; + struct mailimap_set * sk_set; + uint64_t sk_xgmthrid; + uint64_t sk_xgmmsgid; + char * sk_xgmraw; + clist * sk_multiple; /* list of (struct mailimap_search_key *) */ + struct { + struct mailimap_flag * sk_entry_name; + int sk_entry_type_req; + uint64_t sk_modseq_valzer; + } sk_modseq; + } sk_data; +}; + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new(int sk_type, + char * sk_bcc, struct mailimap_date * sk_before, char * sk_body, + char * sk_cc, char * sk_from, char * sk_keyword, + struct mailimap_date * sk_on, struct mailimap_date * sk_since, + char * sk_subject, char * sk_text, char * sk_to, + char * sk_unkeyword, char * sk_header_name, + char * sk_header_value, uint32_t sk_larger, + struct mailimap_search_key * sk_not, + struct mailimap_search_key * sk_or1, + struct mailimap_search_key * sk_or2, + struct mailimap_date * sk_sentbefore, + struct mailimap_date * sk_senton, + struct mailimap_date * sk_sentsince, + uint32_t sk_smaller, struct mailimap_set * sk_uid, + struct mailimap_set * sk_set, clist * sk_multiple); + +/* + this function creates a condition structure to match messages with + the given gmail thread id +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_xgmthrid(uint64_t sk_xgmthrid); + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_xgmmsgid(uint64_t sk_xgmmsgid); + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_xgmraw(char * sk_xgmraw); + +LIBETPAN_EXPORT +void mailimap_search_key_free(struct mailimap_search_key * key); + +/* + mailimap_status_att_list is a list of mailbox STATUS request type + + - list is a list of mailbox STATUS request type + (value of elements in the list can be MAILIMAP_STATUS_ATT_MESSAGES, + MAILIMAP_STATUS_ATT_RECENT, MAILIMAP_STATUS_ATT_UIDNEXT, + MAILIMAP_STATUS_ATT_UIDVALIDITY or MAILIMAP_STATUS_ATT_UNSEEN), + each element should be allocated with malloc() +*/ + +struct mailimap_status_att_list { + clist * att_list; /* list of (uint32_t *) */ +}; + +LIBETPAN_EXPORT +struct mailimap_status_att_list * +mailimap_status_att_list_new(clist * att_list); + +LIBETPAN_EXPORT +void mailimap_status_att_list_free(struct mailimap_status_att_list * + status_att_list); + + + + +/* internal use functions */ + + +LIBETPAN_EXPORT +uint32_t * mailimap_number_alloc_new(uint32_t number); + +LIBETPAN_EXPORT +void mailimap_number_alloc_free(uint32_t * pnumber); + + +LIBETPAN_EXPORT +void mailimap_addr_host_free(char * addr_host); + +LIBETPAN_EXPORT +void mailimap_addr_mailbox_free(char * addr_mailbox); + +LIBETPAN_EXPORT +void mailimap_addr_adl_free(char * addr_adl); + +LIBETPAN_EXPORT +void mailimap_addr_name_free(char * addr_name); + +LIBETPAN_EXPORT +void mailimap_astring_free(char * astring); + +LIBETPAN_EXPORT +void mailimap_atom_free(char * atom); + +LIBETPAN_EXPORT +void mailimap_auth_type_free(char * auth_type); + +LIBETPAN_EXPORT +void mailimap_base64_free(char * base64); + +LIBETPAN_EXPORT +void mailimap_body_fld_desc_free(char * body_fld_desc); + +LIBETPAN_EXPORT +void mailimap_body_fld_id_free(char * body_fld_id); + +LIBETPAN_EXPORT +void mailimap_body_fld_md5_free(char * body_fld_md5); + +LIBETPAN_EXPORT +void mailimap_body_fld_loc_free(char * body_fld_loc); + +LIBETPAN_EXPORT +void mailimap_env_date_free(char * date); + +LIBETPAN_EXPORT +void mailimap_env_in_reply_to_free(char * in_reply_to); + +LIBETPAN_EXPORT +void mailimap_env_message_id_free(char * message_id); + +LIBETPAN_EXPORT +void mailimap_env_subject_free(char * subject); + +LIBETPAN_EXPORT +void mailimap_flag_extension_free(char * flag_extension); + +LIBETPAN_EXPORT +void mailimap_flag_keyword_free(char * flag_keyword); + +LIBETPAN_EXPORT +void +mailimap_header_fld_name_free(char * header_fld_name); + +LIBETPAN_EXPORT +void mailimap_literal_free(char * literal); + +LIBETPAN_EXPORT +void mailimap_mailbox_free(char * mailbox); + +LIBETPAN_EXPORT +void +mailimap_mailbox_data_search_free(clist * data_search); + +LIBETPAN_EXPORT +void mailimap_media_subtype_free(char * media_subtype); + +LIBETPAN_EXPORT +void mailimap_media_text_free(char * media_text); + +LIBETPAN_EXPORT +void mailimap_msg_att_envelope_free(struct mailimap_envelope * env); + +LIBETPAN_EXPORT +void +mailimap_msg_att_internaldate_free(struct mailimap_date_time * date_time); + +LIBETPAN_EXPORT +void +mailimap_msg_att_rfc822_free(char * str); + +LIBETPAN_EXPORT +void +mailimap_msg_att_rfc822_header_free(char * str); + +LIBETPAN_EXPORT +void +mailimap_msg_att_rfc822_text_free(char * str); + +LIBETPAN_EXPORT +void +mailimap_msg_att_body_free(struct mailimap_body * body); + +LIBETPAN_EXPORT +void +mailimap_msg_att_bodystructure_free(struct mailimap_body * body); + +LIBETPAN_EXPORT +void mailimap_nstring_free(char * str); + +LIBETPAN_EXPORT +void +mailimap_string_free(char * str); + +LIBETPAN_EXPORT +void mailimap_tag_free(char * tag); + +LIBETPAN_EXPORT +void mailimap_text_free(char * text); + + + + + +/* IMAP connection */ + +/* this is the state of the IMAP connection */ + +enum { + MAILIMAP_STATE_DISCONNECTED, + MAILIMAP_STATE_NON_AUTHENTICATED, + MAILIMAP_STATE_AUTHENTICATED, + MAILIMAP_STATE_SELECTED, + MAILIMAP_STATE_LOGOUT +}; + +/* + mailimap is an IMAP connection + + - response is a human readable message returned with a reponse, + must be accessed read-only + + - stream is the connection with the IMAP server + + - stream_buffer is the buffer where the data to parse are stored + + - state is the state of IMAP connection + + - tag is the current tag being used in IMAP connection + + - response_buffer is the buffer for response messages + + - connection_info is the information returned in response + for the last command about the connection + + - selection_info is the information returned in response + for the last command about the current selected mailbox + + - response_info is the other information returned in response + for the last command +*/ + +typedef void mailimap_msg_att_handler(struct mailimap_msg_att * msg_att, void * context); + +typedef bool mailimap_msg_body_handler(int msg_att_type, struct mailimap_msg_att_body_section * section, + const char * bytes, size_t length, void * context); + +typedef struct mailimap mailimap; + +struct mailimap { + char * imap_response; + + /* internals */ + mailstream * imap_stream; + + size_t imap_progr_rate; + progress_function * imap_progr_fun; + + MMAPString * imap_stream_buffer; + MMAPString * imap_response_buffer; + + int imap_state; + int imap_tag; + + struct mailimap_connection_info * imap_connection_info; + struct mailimap_selection_info * imap_selection_info; + struct mailimap_response_info * imap_response_info; + + struct { + void * sasl_conn; + const char * sasl_server_fqdn; + const char * sasl_login; + const char * sasl_auth_name; + const char * sasl_password; + const char * sasl_realm; + void * sasl_secret; + } imap_sasl; + + time_t imap_idle_timestamp; + time_t imap_idle_maxdelay; + + mailprogress_function * imap_body_progress_fun; + mailprogress_function * imap_items_progress_fun; + void * imap_progress_context; + mailimap_msg_att_handler * imap_msg_att_handler; + void * imap_msg_att_handler_context; + mailimap_msg_body_handler * imap_msg_body_handler; + void * imap_msg_body_handler_context; + + time_t imap_timeout; + + void (* imap_logger)(mailimap * session, int log_type, const char * str, size_t size, void * context); + void * imap_logger_context; + + int is_163_workaround_enabled; + int is_rambler_workaround_enabled; + int is_qip_workaround_enabled; +}; + + + +/* + mailimap_connection_info is the information about the connection + + - capability is the list of capability of the IMAP server +*/ + +struct mailimap_connection_info { + struct mailimap_capability_data * imap_capability; +}; + +LIBETPAN_EXPORT +struct mailimap_connection_info * +mailimap_connection_info_new(void); + +LIBETPAN_EXPORT +void +mailimap_connection_info_free(struct mailimap_connection_info * conn_info); + + +/* this is the type of mailbox access */ + +enum { + MAILIMAP_MAILBOX_READONLY, + MAILIMAP_MAILBOX_READWRITE +}; + +/* + mailimap_selection_info is information about the current selected mailbox + + - perm_flags is a list of flags that can be changed permanently on the + messages of the mailbox + + - perm is the access on the mailbox, value can be + MAILIMAP_MAILBOX_READONLY or MAILIMAP_MAILBOX_READWRITE + + - uidnext is the next unique identifier + + - uidvalidity is the unique identifiers validity + + - first_unseen is the number of the first unseen message + + - flags is a list of flags that can be used on the messages of + the mailbox + + - exists is the number of messages in the mailbox + + - recent is the number of recent messages in the mailbox + + - unseen is the number of unseen messages in the mailbox +*/ + +struct mailimap_selection_info { + clist * sel_perm_flags; /* list of (struct flag_perm *) */ + int sel_perm; + uint32_t sel_uidnext; + uint32_t sel_uidvalidity; + uint32_t sel_first_unseen; + struct mailimap_flag_list * sel_flags; + uint32_t sel_exists; + uint32_t sel_recent; + uint32_t sel_unseen; + uint8_t sel_has_exists:1; + uint8_t sel_has_recent:1; +}; + +LIBETPAN_EXPORT +struct mailimap_selection_info * +mailimap_selection_info_new(void); + +LIBETPAN_EXPORT +void +mailimap_selection_info_free(struct mailimap_selection_info * sel_info); + + +/* + mailimap_response_info is the other information returned in the + response for a command + + - alert is the human readable text returned with ALERT response + + - parse is the human readable text returned with PARSE response + + - badcharset is a list of charset returned with a BADCHARSET response + + - trycreate is set to 1 if a trycreate response was returned + + - mailbox_list is a list of mailboxes + + - mailbox_lsub is a list of subscribed mailboxes + + - search_result is a list of message numbers or unique identifiers + + - status is a STATUS response + + - expunged is a list of message numbers + + - fetch_list is a list of fetch response +*/ + +struct mailimap_response_info { + char * rsp_alert; + char * rsp_parse; + clist * rsp_badcharset; /* list of (char *) */ + int rsp_trycreate; + clist * rsp_mailbox_list; /* list of (struct mailimap_mailbox_list *) */ + clist * rsp_mailbox_lsub; /* list of (struct mailimap_mailbox_list *) */ + clist * rsp_search_result; /* list of (uint32_t *) */ + struct mailimap_mailbox_data_status * rsp_status; + clist * rsp_expunged; /* list of (uint32_t 32 *) */ + clist * rsp_fetch_list; /* list of (struct mailimap_msg_att *) */ + clist * rsp_extension_list; /* list of (struct mailimap_extension_data *) */ + char * rsp_atom; + char * rsp_value; +}; + +LIBETPAN_EXPORT +struct mailimap_response_info * +mailimap_response_info_new(void); + +LIBETPAN_EXPORT +void +mailimap_response_info_free(struct mailimap_response_info * resp_info); + + +/* these are the possible returned error codes */ + +enum { + MAILIMAP_NO_ERROR = 0, + MAILIMAP_NO_ERROR_AUTHENTICATED = 1, + MAILIMAP_NO_ERROR_NON_AUTHENTICATED = 2, + MAILIMAP_ERROR_BAD_STATE, + MAILIMAP_ERROR_STREAM, + MAILIMAP_ERROR_PARSE, + MAILIMAP_ERROR_CONNECTION_REFUSED, + MAILIMAP_ERROR_MEMORY, + MAILIMAP_ERROR_FATAL, + MAILIMAP_ERROR_PROTOCOL, + MAILIMAP_ERROR_DONT_ACCEPT_CONNECTION, + MAILIMAP_ERROR_APPEND, + MAILIMAP_ERROR_NOOP, + MAILIMAP_ERROR_LOGOUT, + MAILIMAP_ERROR_CAPABILITY, + MAILIMAP_ERROR_CHECK, + MAILIMAP_ERROR_CLOSE, + MAILIMAP_ERROR_EXPUNGE, + MAILIMAP_ERROR_COPY, + MAILIMAP_ERROR_UID_COPY, + MAILIMAP_ERROR_MOVE, + MAILIMAP_ERROR_UID_MOVE, + MAILIMAP_ERROR_CREATE, + MAILIMAP_ERROR_DELETE, + MAILIMAP_ERROR_EXAMINE, + MAILIMAP_ERROR_FETCH, + MAILIMAP_ERROR_UID_FETCH, + MAILIMAP_ERROR_LIST, + MAILIMAP_ERROR_LOGIN, + MAILIMAP_ERROR_LSUB, + MAILIMAP_ERROR_RENAME, + MAILIMAP_ERROR_SEARCH, + MAILIMAP_ERROR_UID_SEARCH, + MAILIMAP_ERROR_SELECT, + MAILIMAP_ERROR_STATUS, + MAILIMAP_ERROR_STORE, + MAILIMAP_ERROR_UID_STORE, + MAILIMAP_ERROR_SUBSCRIBE, + MAILIMAP_ERROR_UNSUBSCRIBE, + MAILIMAP_ERROR_STARTTLS, + MAILIMAP_ERROR_INVAL, + MAILIMAP_ERROR_EXTENSION, + MAILIMAP_ERROR_SASL, + MAILIMAP_ERROR_SSL, + MAILIMAP_ERROR_NEEDS_MORE_DATA, + MAILIMAP_ERROR_CUSTOM_COMMAND, + MAILIMAP_ERROR_CLIENTID, +}; + +/* information about parser context */ + +struct mailimap_parser_context { + int is_rambler_workaround_enabled; + int is_qip_workaround_enabled; + + mailimap_msg_body_handler * msg_body_handler; + void * msg_body_handler_context; + struct mailimap_msg_att_body_section * msg_body_section; + int msg_body_att_type; + bool msg_body_parse_in_progress; +}; + +LIBETPAN_EXPORT +struct mailimap_parser_context * +mailimap_parser_context_new(mailimap * session); + +LIBETPAN_EXPORT +void +mailimap_parser_context_free(struct mailimap_parser_context * ctx); + +LIBETPAN_EXPORT +int +mailimap_parser_context_is_rambler_workaround_enabled(struct mailimap_parser_context * parser_ctx); + +LIBETPAN_EXPORT +int +mailimap_parser_context_is_qip_workaround_enabled(struct mailimap_parser_context * parser_ctx); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Sources/libetpan/include/mailimap_types_helper.h b/Sources/libetpan/include/mailimap_types_helper.h new file mode 100644 index 00000000..9d2a2b6c --- /dev/null +++ b/Sources/libetpan/include/mailimap_types_helper.h @@ -0,0 +1,849 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_types_helper.h,v 1.12 2008/02/20 22:15:52 hoa Exp $ + */ + +#ifndef MAILIMAP_TYPES_HELPER_H + +#define MAILIMAP_TYPES_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_types.h" + +/* + IMPORTANT NOTE: + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + allocation functions will return NULL on failure +*/ + +/* + this function creates a new set item with a single message + given by indx +*/ + +LIBETPAN_EXPORT +struct mailimap_set_item * mailimap_set_item_new_single(uint32_t indx); + +/* + this function creates a new set with one set item + */ + +LIBETPAN_EXPORT +struct mailimap_set * +mailimap_set_new_single_item(struct mailimap_set_item * item); + +/* + this function creates a set with a single interval +*/ + +LIBETPAN_EXPORT +struct mailimap_set * mailimap_set_new_interval(uint32_t first, uint32_t last); + +/* + this function creates a set with a single message +*/ + +LIBETPAN_EXPORT +struct mailimap_set * mailimap_set_new_single(uint32_t indx); + +/* + this function creates an empty set of messages +*/ + +LIBETPAN_EXPORT +struct mailimap_set * mailimap_set_new_empty(void); + +/* + this function adds a set item to the set of messages + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int mailimap_set_add(struct mailimap_set * set, + struct mailimap_set_item * set_item); + +/* + this function adds an interval to the set + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int mailimap_set_add_interval(struct mailimap_set * set, + uint32_t first, uint32_t last); + +/* + this function adds a single message to the set + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int mailimap_set_add_single(struct mailimap_set * set, + uint32_t indx); + +/* + this function creates a mailimap_section structure to request + the header of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_section * mailimap_section_new_header(void); + +/* + this functions creates a mailimap_section structure to describe + a list of headers +*/ + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new_header_fields(struct mailimap_header_list * header_list); + +/* + this functions creates a mailimap_section structure to describe headers + other than those given +*/ + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new_header_fields_not(struct mailimap_header_list * header_list); + +/* + this function creates a mailimap_section structure to describe the + text of a message + */ + +LIBETPAN_EXPORT +struct mailimap_section * mailimap_section_new_text(void); + +/* + this function creates a mailimap_section structure to describe the + content of a MIME part +*/ + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new_part(struct mailimap_section_part * part); + +/* + this function creates a mailimap_section structure to describe the + MIME fields of a MIME part +*/ + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new_part_mime(struct mailimap_section_part * part); + +/* + this function creates a mailimap_section structure to describe the + headers of a MIME part if the MIME type is a message/rfc822 +*/ + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new_part_header(struct mailimap_section_part * part); + +/* + this function creates a mailimap_section structure to describe + a list of headers of a MIME part if the MIME type is a message/rfc822 +*/ + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new_part_header_fields(struct mailimap_section_part * + part, + struct mailimap_header_list * + header_list); + +/* + this function creates a mailimap_section structure to describe + headers of a MIME part other than those given if the MIME type + is a message/rfc822 +*/ + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new_part_header_fields_not(struct mailimap_section_part + * part, + struct mailimap_header_list + * header_list); + +/* + this function creates a mailimap_section structure to describe + text part of message if the MIME type is a message/rfc822 +*/ + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new_part_text(struct mailimap_section_part * part); + + +/* + this function creates a mailimap_fetch_att structure to request + envelope of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_envelope(void); + + +/* + this function creates a mailimap_fetch_att structure to request + flags of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_flags(void); + +/* + this function creates a mailimap_fetch_att structure to request + internal date of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_internaldate(void); + + +/* + this function creates a mailimap_fetch_att structure to request + text part of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822(void); + + +/* + this function creates a mailimap_fetch_att structure to request + header of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_header(void); + +/* + this function creates a mailimap_fetch_att structure to request + size of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_size(void); + +/* + this function creates a mailimap_fetch_att structure to request + envelope of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_text(void); + +/* + this function creates a mailimap_fetch_att structure to request + the MIME structure of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_body(void); + +/* + this function creates a mailimap_fetch_att structure to request + the MIME structure of a message and additional MIME information +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_bodystructure(void); + +/* + this function creates a mailimap_fetch_att structure to request + unique identifier of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_uid(void); + +/* + this function creates a mailimap_fetch_att structure to request + a given section of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_section(struct mailimap_section * section); + +/* + this function creates a mailimap_fetch_att structure to request + a given section of a message without marking it as read +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_peek_section(struct mailimap_section * section); + +/* + this function creates a mailimap_fetch_att structure to request + a part of a section of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_section_partial(struct mailimap_section * section, + uint32_t offset, uint32_t size); + +/* + this function creates a mailimap_fetch_att structure to request + a part of a section of a message without marking it as read +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_peek_section_partial(struct mailimap_section * section, + uint32_t offset, uint32_t size); + +/* + creates a mailimap_fetch_att extension +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * + mailimap_fetch_att_new_extension(char * ext_keyword); + +/* + this function creates a mailimap_fetch_type structure to request + (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE) of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_type * +mailimap_fetch_type_new_all(void); + +/* + this function creates a mailimap_fetch_type structure to request + (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE BODY) +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_type * +mailimap_fetch_type_new_full(void); + +/* + this function creates a mailimap_fetch_type structure to request + (FLAGS INTERNALDATE RFC822.SIZE) +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_type * +mailimap_fetch_type_new_fast(void); + +/* + this function creates a mailimap_fetch_type structure to request + the given fetch attribute +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att(struct mailimap_fetch_att * fetch_att); + +/* + this function creates a mailimap_fetch_type structure to request + the list of fetch attributes +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att_list(clist * fetch_att_list); + +/* + this function creates a mailimap_fetch_type structure +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att_list_empty(void); + +/* + this function adds a given fetch attribute to the mailimap_fetch + structure + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int +mailimap_fetch_type_new_fetch_att_list_add(struct mailimap_fetch_type * + fetch_type, + struct mailimap_fetch_att * + fetch_att); + +/* + this function creates a store attribute to set the given flags +*/ + +LIBETPAN_EXPORT +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_set_flags(struct mailimap_flag_list * flags); + +/* + this function creates a store attribute to silently set the given flags +*/ + +LIBETPAN_EXPORT +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_set_flags_silent(struct mailimap_flag_list * + flags); + +/* + this function creates a store attribute to add the given flags +*/ + +LIBETPAN_EXPORT +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_add_flags(struct mailimap_flag_list * flags); + +/* + this function creates a store attribute to add silently the given flags +*/ + +LIBETPAN_EXPORT +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_add_flags_silent(struct mailimap_flag_list * + flags); + +/* + this function creates a store attribute to remove the given flags +*/ + +LIBETPAN_EXPORT +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_remove_flags(struct mailimap_flag_list * flags); + +/* + this function creates a store attribute to remove silently the given flags +*/ + +LIBETPAN_EXPORT +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_remove_flags_silent(struct mailimap_flag_list * + flags); + + +/* + this function creates a condition structure to match all messages +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_all(void); + +/* + this function creates a condition structure to match messages with Bcc field + + @param bcc this is the content of Bcc to match, it should be allocated + with malloc() +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_bcc(char * sk_bcc); + +/* + this function creates a condition structure to match messages with + internal date +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_before(struct mailimap_date * sk_before); + +/* + this function creates a condition structure to match messages with + message content + + @param body this is the content of the message to match, it should + be allocated with malloc() +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_body(char * sk_body); + +/* + this function creates a condition structure to match messages with + Cc field + + + @param cc this is the content of Cc to match, it should be allocated + with malloc() +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_cc(char * sk_cc); + +/* + this function creates a condition structure to match messages with + From field + + @param from this is the content of From to match, it should be allocated + with malloc() +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_from(char * sk_from); + +/* + this function creates a condition structure to match messages with + a flag given by keyword +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_keyword(char * sk_keyword); + +/* + this function creates a condition structure to match messages with + internal date +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_on(struct mailimap_date * sk_on); + +/* + this function creates a condition structure to match messages with + internal date +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_since(struct mailimap_date * sk_since); + +/* + this function creates a condition structure to match messages with + Subject field + + @param subject this is the content of Subject to match, it should + be allocated with malloc() +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_subject(char * sk_subject); + +/* + this function creates a condition structure to match messages with + message text part + + @param text this is the message text to match, it should + be allocated with malloc() +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_text(char * sk_text); + +/* + this function creates a condition structure to match messages with + To field + + @param to this is the content of To to match, it should be allocated + with malloc() +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_to(char * sk_to); + +/* + this function creates a condition structure to match messages with + no a flag given by unkeyword +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_unkeyword(char * sk_unkeyword); + +/* + this function creates a condition structure to match messages with + the given field + + @param header_name this is the name of the field to match, it + should be allocated with malloc() + + @param header_value this is the content, it should be allocated + with malloc() +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_header(char * sk_header_name, char * sk_header_value); + +/* + this function creates a condition structure to match messages with size +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_larger(uint32_t sk_larger); + +/* + this function creates a condition structure to match messages that + do not match the given condition +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_not(struct mailimap_search_key * sk_not); + +/* + this function creates a condition structure to match messages that + match one of the given conditions +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_or(struct mailimap_search_key * sk_or1, + struct mailimap_search_key * sk_or2); + +/* + this function creates a condition structure to match messages + with Date field +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_sentbefore(struct mailimap_date * sk_sentbefore); + +/* + this function creates a condition structure to match messages + with Date field +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_senton(struct mailimap_date * sk_senton); + +/* + this function creates a condition structure to match messages + with Date field +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_sentsince(struct mailimap_date * sk_sentsince); + +/* + this function creates a condition structure to match messages with size +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_smaller(uint32_t sk_smaller); + +/* + this function creates a condition structure to match messages with unique + identifier +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_uid(struct mailimap_set * sk_uid); + +/* + this function creates a condition structure to match messages with number + or unique identifier (depending whether SEARCH or UID SEARCH is used) +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_set(struct mailimap_set * sk_set); + +/* + this function creates a condition structure to match messages that match + all the conditions given in the list +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_multiple(clist * sk_multiple); + + +/* + same as previous but the list is empty +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_multiple_empty(void); + +/* + this function adds a condition to the condition list + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int +mailimap_search_key_multiple_add(struct mailimap_search_key * keys, + struct mailimap_search_key * key_item); + + + +/* + this function creates an empty list of flags +*/ + +LIBETPAN_EXPORT +struct mailimap_flag_list * +mailimap_flag_list_new_empty(void); + +/* + this function adds a flag to the list of flags + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int mailimap_flag_list_add(struct mailimap_flag_list * flag_list, + struct mailimap_flag * f); + +/* + this function creates a \Answered flag +*/ + +LIBETPAN_EXPORT +struct mailimap_flag * mailimap_flag_new_answered(void); + +/* + this function creates a \Flagged flag +*/ + +LIBETPAN_EXPORT +struct mailimap_flag * mailimap_flag_new_flagged(void); + +/* + this function creates a \Deleted flag +*/ + +LIBETPAN_EXPORT +struct mailimap_flag * mailimap_flag_new_deleted(void); + +/* + this function creates a \Seen flag +*/ + +LIBETPAN_EXPORT +struct mailimap_flag * mailimap_flag_new_seen(void); + +/* + this function creates a \Draft flag +*/ + +LIBETPAN_EXPORT +struct mailimap_flag * mailimap_flag_new_draft(void); + +/* + this function creates a keyword flag + + @param flag_keyword this should be allocated with malloc() +*/ + +LIBETPAN_EXPORT +struct mailimap_flag * mailimap_flag_new_flag_keyword(char * flag_keyword); + + +/* + this function creates an extension flag + + @param flag_extension this should be allocated with malloc() +*/ + +LIBETPAN_EXPORT +struct mailimap_flag * mailimap_flag_new_flag_extension(char * flag_extension); + +/* + this function creates an empty list of status attributes +*/ + +LIBETPAN_EXPORT +struct mailimap_status_att_list * mailimap_status_att_list_new_empty(void); + +/* + this function adds status attributes to the list + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int +mailimap_status_att_list_add(struct mailimap_status_att_list * sa_list, + int status_att); + +/* return mailimap_section_part from a given mailimap_body */ + +LIBETPAN_EXPORT +int mailimap_get_section_part_from_body(struct mailimap_body * root_part, + struct mailimap_body * part, + struct mailimap_section_part ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailimf.h b/Sources/libetpan/include/mailimf.h new file mode 100644 index 00000000..e3ca4cf3 --- /dev/null +++ b/Sources/libetpan/include/mailimf.h @@ -0,0 +1,368 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf.h,v 1.28 2008/05/27 10:07:55 hoa Exp $ + */ + +#ifndef MAILIMF_H + +#define MAILIMF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimf_types.h" +#include "mailimf_write_generic.h" +#include "mailimf_write_file.h" +#include "mailimf_write_mem.h" +#include "mailimf_types_helper.h" + +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +/* + mailimf_message_parse will parse the given message + + @param message this is a string containing the message content + @param length this is the size of the given string + @param indx this is a pointer to the start of the message in + the given string, (* indx) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int mailimf_message_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_message ** result); + +/* + mailimf_body_parse will parse the given text part of a message + + @param message this is a string containing the message text part + @param length this is the size of the given string + @param indx this is a pointer to the start of the message text part in + the given string, (* indx) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int mailimf_body_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_body ** result); + +/* + mailimf_fields_parse will parse the given header fields + + @param message this is a string containing the header fields + @param length this is the size of the given string + @param indx this is a pointer to the start of the header fields in + the given string, (* indx) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int mailimf_fields_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_fields ** result); + +/* + mailimf_mailbox_list_parse will parse the given mailbox list + + @param message this is a string containing the mailbox list + @param length this is the size of the given string + @param indx this is a pointer to the start of the mailbox list in + the given string, (* indx) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int +mailimf_mailbox_list_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_mailbox_list ** result); + +/* + mailimf_address_list_parse will parse the given address list + + @param message this is a string containing the address list + @param length this is the size of the given string + @param indx this is a pointer to the start of the address list in + the given string, (* indx) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int +mailimf_address_list_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_address_list ** result); + +/* + mailimf_address_parse will parse the given address + + @param message this is a string containing the address + @param length this is the size of the given string + @param indx this is a pointer to the start of the address in + the given string, (* indx) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int mailimf_address_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_address ** result); + +/* + mailimf_mailbox_parse will parse the given address + + @param message this is a string containing the mailbox + @param length this is the size of the given string + @param indx this is a pointer to the start of the mailbox in + the given string, (* indx) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int mailimf_mailbox_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_mailbox ** result); + +/* + mailimf_date_time_parse will parse the given RFC 2822 date + + @param message this is a string containing the date + @param length this is the size of the given string + @param indx this is a pointer to the start of the date in + the given string, (* indx) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int mailimf_date_time_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_date_time ** result); + +/* + mailimf_envelope_fields_parse will parse the given fields (Date, + From, Sender, Reply-To, To, Cc, Bcc, Message-ID, In-Reply-To, + References and Subject) + + @param message this is a string containing the header fields + @param length this is the size of the given string + @param indx this is a pointer to the start of the header fields in + the given string, (* indx) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int mailimf_envelope_fields_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_fields ** result); + +/* + mailimf_ignore_field_parse will skip the given field + + @param message this is a string containing the header field + @param length this is the size of the given string + @param indx this is a pointer to the start of the header field in + the given string, (* indx) is modified to point at the end + of the parsed data + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +LIBETPAN_EXPORT +int mailimf_ignore_field_parse(const char * message, size_t length, + size_t * indx); + +/* + mailimf_envelope_fields will parse the given fields (Date, + From, Sender, Reply-To, To, Cc, Bcc, Message-ID, In-Reply-To, + References and Subject), other fields will be added as optional + fields. + + @param message this is a string containing the header fields + @param length this is the size of the given string + @param indx this is a pointer to the start of the header fields in + the given string, (* indx) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +LIBETPAN_EXPORT +int +mailimf_envelope_and_optional_fields_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_fields ** result); + +/* + mailimf_envelope_fields will parse the given fields as optional + fields. + + @param message this is a string containing the header fields + @param length this is the size of the given string + @param indx this is a pointer to the start of the header fields in + the given string, (* indx) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int +mailimf_optional_fields_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_fields ** result); + + +/* internal use, exported for MIME */ + +LIBETPAN_EXPORT +int mailimf_fws_parse(const char * message, size_t length, size_t * indx); + +LIBETPAN_EXPORT +int mailimf_cfws_parse(const char * message, size_t length, + size_t * indx); + +LIBETPAN_EXPORT +int mailimf_char_parse(const char * message, size_t length, + size_t * indx, char token); + +LIBETPAN_EXPORT +int mailimf_unstrict_char_parse(const char * message, size_t length, + size_t * indx, char token); + +LIBETPAN_EXPORT +int mailimf_crlf_parse(const char * message, size_t length, size_t * indx); + +LIBETPAN_EXPORT +int +mailimf_custom_string_parse(const char * message, size_t length, + size_t * indx, char ** result, + int (* is_custom_char)(char)); + +LIBETPAN_EXPORT +int +mailimf_token_case_insensitive_len_parse(const char * message, size_t length, + size_t * indx, char * token, + size_t token_length); + +#define mailimf_token_case_insensitive_parse(message, length, indx, token) \ + mailimf_token_case_insensitive_len_parse(message, length, indx, token, \ + strlen(token)) + +LIBETPAN_EXPORT +int mailimf_quoted_string_parse(const char * message, size_t length, + size_t * indx, char ** result); + +LIBETPAN_EXPORT +int +mailimf_number_parse(const char * message, size_t length, + size_t * indx, uint32_t * result); + +LIBETPAN_EXPORT +int mailimf_msg_id_parse(const char * message, size_t length, + size_t * indx, + char ** result); + +LIBETPAN_EXPORT +int mailimf_msg_id_list_parse(const char * message, size_t length, + size_t * indx, clist ** result); + +LIBETPAN_EXPORT +int mailimf_word_parse(const char * message, size_t length, + size_t * indx, char ** result); + +LIBETPAN_EXPORT +int mailimf_atom_parse(const char * message, size_t length, + size_t * indx, char ** result); + +LIBETPAN_EXPORT +int mailimf_fws_atom_parse(const char * message, size_t length, + size_t * indx, char ** result); + +LIBETPAN_EXPORT +int mailimf_fws_word_parse(const char * message, size_t length, + size_t * indx, char ** result, int * p_missing_closing_quote); + +LIBETPAN_EXPORT +int mailimf_fws_quoted_string_parse(const char * message, size_t length, + size_t * indx, char ** result); + +/* exported for IMAP */ + +LIBETPAN_EXPORT +int mailimf_references_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_references ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailimf_types.h b/Sources/libetpan/include/mailimf_types.h new file mode 100644 index 00000000..0d8255a2 --- /dev/null +++ b/Sources/libetpan/include/mailimf_types.h @@ -0,0 +1,864 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +/* + * $Id: mailimf_types.h,v 1.34 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifndef MAILIMF_TYPES_H + +#define MAILIMF_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "libetpan-config.h" +#include "clist.h" +#include "sys/types.h" + +/* + IMPORTANT NOTE: + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + allocation functions will return NULL on failure +*/ + +/* + mailimf_date_time is a date + + - day is the day of month (1 to 31) + + - month (1 to 12) + + - year (4 digits) + + - hour (0 to 23) + + - min (0 to 59) + + - sec (0 to 59) + + - zone (this is the decimal value that we can read, for example: + for "-0200", the value is -200) +*/ + +struct mailimf_date_time { + int dt_day; + int dt_month; + int dt_year; + int dt_hour; + int dt_min; + int dt_sec; + int dt_zone; +}; + +LIBETPAN_EXPORT +struct mailimf_date_time * +mailimf_date_time_new(int dt_day, int dt_month, int dt_year, + int dt_hour, int dt_min, int dt_sec, int dt_zone); + +LIBETPAN_EXPORT +void mailimf_date_time_free(struct mailimf_date_time * date_time); + + + +/* this is the type of address */ + +enum { + MAILIMF_ADDRESS_ERROR, /* on parse error */ + MAILIMF_ADDRESS_MAILBOX, /* if this is a mailbox (mailbox@domain) */ + MAILIMF_ADDRESS_GROUP /* if this is a group + (group_name: address1@domain1, + address2@domain2; ) */ +}; + +/* + mailimf_address is an address + + - type can be MAILIMF_ADDRESS_MAILBOX or MAILIMF_ADDRESS_GROUP + + - mailbox is a mailbox if type is MAILIMF_ADDRESS_MAILBOX + + - group is a group if type is MAILIMF_ADDRESS_GROUP +*/ + +struct mailimf_address { + int ad_type; + union { + struct mailimf_mailbox * ad_mailbox; /* can be NULL */ + struct mailimf_group * ad_group; /* can be NULL */ + } ad_data; +}; + +LIBETPAN_EXPORT +struct mailimf_address * +mailimf_address_new(int ad_type, struct mailimf_mailbox * ad_mailbox, + struct mailimf_group * ad_group); + +LIBETPAN_EXPORT +void mailimf_address_free(struct mailimf_address * address); + + + +/* + mailimf_mailbox is a mailbox + + - display_name is the name that will be displayed for this mailbox, + for example 'name' in '"name" , + should be allocated with malloc() + + - addr_spec is the mailbox, for example 'mailbox@domain' + in '"name" , should be allocated with malloc() +*/ + +struct mailimf_mailbox { + char * mb_display_name; /* can be NULL */ + char * mb_addr_spec; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_mailbox * +mailimf_mailbox_new(char * mb_display_name, char * mb_addr_spec); + +LIBETPAN_EXPORT +void mailimf_mailbox_free(struct mailimf_mailbox * mailbox); + + + +/* + mailimf_group is a group + + - display_name is the name that will be displayed for this group, + for example 'group_name' in + 'group_name: address1@domain1, address2@domain2;', should be allocated + with malloc() + + - mb_list is a list of mailboxes +*/ + +struct mailimf_group { + char * grp_display_name; /* != NULL */ + struct mailimf_mailbox_list * grp_mb_list; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_group * +mailimf_group_new(char * grp_display_name, + struct mailimf_mailbox_list * grp_mb_list); + +LIBETPAN_EXPORT +void mailimf_group_free(struct mailimf_group * group); + + + +/* + mailimf_mailbox_list is a list of mailboxes + + - list is a list of mailboxes +*/ + +struct mailimf_mailbox_list { + clist * mb_list; /* list of (struct mailimf_mailbox *), != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_mailbox_list * +mailimf_mailbox_list_new(clist * mb_list); + +LIBETPAN_EXPORT +void mailimf_mailbox_list_free(struct mailimf_mailbox_list * mb_list); + + + +/* + mailimf_address_list is a list of addresses + + - list is a list of addresses +*/ + +struct mailimf_address_list { + clist * ad_list; /* list of (struct mailimf_address *), != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_address_list * +mailimf_address_list_new(clist * ad_list); + +LIBETPAN_EXPORT +void mailimf_address_list_free(struct mailimf_address_list * addr_list); + + + + + +/* + mailimf_body is the text part of a message + + - text is the beginning of the text part, it is a substring + of an other string + + - size is the size of the text part +*/ + +struct mailimf_body { + const char * bd_text; /* != NULL */ + size_t bd_size; +}; + +LIBETPAN_EXPORT +struct mailimf_body * mailimf_body_new(const char * bd_text, size_t bd_size); + +LIBETPAN_EXPORT +void mailimf_body_free(struct mailimf_body * body); + + + + +/* + mailimf_message is the content of the message + + - msg_fields is the header fields of the message + + - msg_body is the text part of the message +*/ + +struct mailimf_message { + struct mailimf_fields * msg_fields; /* != NULL */ + struct mailimf_body * msg_body; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_message * +mailimf_message_new(struct mailimf_fields * msg_fields, + struct mailimf_body * msg_body); + +LIBETPAN_EXPORT +void mailimf_message_free(struct mailimf_message * message); + + + + +/* + mailimf_fields is a list of header fields + + - fld_list is a list of header fields +*/ + +struct mailimf_fields { + clist * fld_list; /* list of (struct mailimf_field *), != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_fields * mailimf_fields_new(clist * fld_list); + +LIBETPAN_EXPORT +void mailimf_fields_free(struct mailimf_fields * fields); + + + +/* this is a type of field */ + +enum { + MAILIMF_FIELD_NONE, /* on parse error */ + MAILIMF_FIELD_RETURN_PATH, /* Return-Path */ + MAILIMF_FIELD_RESENT_DATE, /* Resent-Date */ + MAILIMF_FIELD_RESENT_FROM, /* Resent-From */ + MAILIMF_FIELD_RESENT_SENDER, /* Resent-Sender */ + MAILIMF_FIELD_RESENT_TO, /* Resent-To */ + MAILIMF_FIELD_RESENT_CC, /* Resent-Cc */ + MAILIMF_FIELD_RESENT_BCC, /* Resent-Bcc */ + MAILIMF_FIELD_RESENT_MSG_ID, /* Resent-Message-ID */ + MAILIMF_FIELD_ORIG_DATE, /* Date */ + MAILIMF_FIELD_FROM, /* From */ + MAILIMF_FIELD_SENDER, /* Sender */ + MAILIMF_FIELD_REPLY_TO, /* Reply-To */ + MAILIMF_FIELD_TO, /* To */ + MAILIMF_FIELD_CC, /* Cc */ + MAILIMF_FIELD_BCC, /* Bcc */ + MAILIMF_FIELD_MESSAGE_ID, /* Message-ID */ + MAILIMF_FIELD_IN_REPLY_TO, /* In-Reply-To */ + MAILIMF_FIELD_REFERENCES, /* References */ + MAILIMF_FIELD_SUBJECT, /* Subject */ + MAILIMF_FIELD_COMMENTS, /* Comments */ + MAILIMF_FIELD_KEYWORDS, /* Keywords */ + MAILIMF_FIELD_OPTIONAL_FIELD /* other field */ +}; + +/* + mailimf_field is a field + + - fld_type is the type of the field + + - fld_data.fld_return_path is the parsed content of the Return-Path + field if type is MAILIMF_FIELD_RETURN_PATH + + - fld_data.fld_resent_date is the parsed content of the Resent-Date field + if type is MAILIMF_FIELD_RESENT_DATE + + - fld_data.fld_resent_from is the parsed content of the Resent-From field + + - fld_data.fld_resent_sender is the parsed content of the Resent-Sender field + + - fld_data.fld_resent_to is the parsed content of the Resent-To field + + - fld_data.fld_resent_cc is the parsed content of the Resent-Cc field + + - fld_data.fld_resent_bcc is the parsed content of the Resent-Bcc field + + - fld_data.fld_resent_msg_id is the parsed content of the Resent-Message-ID + field + + - fld_data.fld_orig_date is the parsed content of the Date field + + - fld_data.fld_from is the parsed content of the From field + + - fld_data.fld_sender is the parsed content of the Sender field + + - fld_data.fld_reply_to is the parsed content of the Reply-To field + + - fld_data.fld_to is the parsed content of the To field + + - fld_data.fld_cc is the parsed content of the Cc field + + - fld_data.fld_bcc is the parsed content of the Bcc field + + - fld_data.fld_message_id is the parsed content of the Message-ID field + + - fld_data.fld_in_reply_to is the parsed content of the In-Reply-To field + + - fld_data.fld_references is the parsed content of the References field + + - fld_data.fld_subject is the content of the Subject field + + - fld_data.fld_comments is the content of the Comments field + + - fld_data.fld_keywords is the parsed content of the Keywords field + + - fld_data.fld_optional_field is an other field and is not parsed +*/ + +#define LIBETPAN_MAILIMF_FIELD_UNION + +struct mailimf_field { + int fld_type; + union { + struct mailimf_return * fld_return_path; /* can be NULL */ + struct mailimf_orig_date * fld_resent_date; /* can be NULL */ + struct mailimf_from * fld_resent_from; /* can be NULL */ + struct mailimf_sender * fld_resent_sender; /* can be NULL */ + struct mailimf_to * fld_resent_to; /* can be NULL */ + struct mailimf_cc * fld_resent_cc; /* can be NULL */ + struct mailimf_bcc * fld_resent_bcc; /* can be NULL */ + struct mailimf_message_id * fld_resent_msg_id; /* can be NULL */ + struct mailimf_orig_date * fld_orig_date; /* can be NULL */ + struct mailimf_from * fld_from; /* can be NULL */ + struct mailimf_sender * fld_sender; /* can be NULL */ + struct mailimf_reply_to * fld_reply_to; /* can be NULL */ + struct mailimf_to * fld_to; /* can be NULL */ + struct mailimf_cc * fld_cc; /* can be NULL */ + struct mailimf_bcc * fld_bcc; /* can be NULL */ + struct mailimf_message_id * fld_message_id; /* can be NULL */ + struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */ + struct mailimf_references * fld_references; /* can be NULL */ + struct mailimf_subject * fld_subject; /* can be NULL */ + struct mailimf_comments * fld_comments; /* can be NULL */ + struct mailimf_keywords * fld_keywords; /* can be NULL */ + struct mailimf_optional_field * fld_optional_field; /* can be NULL */ + } fld_data; +}; + +LIBETPAN_EXPORT +struct mailimf_field * +mailimf_field_new(int fld_type, + struct mailimf_return * fld_return_path, + struct mailimf_orig_date * fld_resent_date, + struct mailimf_from * fld_resent_from, + struct mailimf_sender * fld_resent_sender, + struct mailimf_to * fld_resent_to, + struct mailimf_cc * fld_resent_cc, + struct mailimf_bcc * fld_resent_bcc, + struct mailimf_message_id * fld_resent_msg_id, + struct mailimf_orig_date * fld_orig_date, + struct mailimf_from * fld_from, + struct mailimf_sender * fld_sender, + struct mailimf_reply_to * fld_reply_to, + struct mailimf_to * fld_to, + struct mailimf_cc * fld_cc, + struct mailimf_bcc * fld_bcc, + struct mailimf_message_id * fld_message_id, + struct mailimf_in_reply_to * fld_in_reply_to, + struct mailimf_references * fld_references, + struct mailimf_subject * fld_subject, + struct mailimf_comments * fld_comments, + struct mailimf_keywords * fld_keywords, + struct mailimf_optional_field * fld_optional_field); + +LIBETPAN_EXPORT +void mailimf_field_free(struct mailimf_field * field); + + + +/* + mailimf_orig_date is the parsed Date field + + - date_time is the parsed date +*/ + +struct mailimf_orig_date { + struct mailimf_date_time * dt_date_time; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_orig_date * mailimf_orig_date_new(struct mailimf_date_time * + dt_date_time); + +LIBETPAN_EXPORT +void mailimf_orig_date_free(struct mailimf_orig_date * orig_date); + + + + +/* + mailimf_from is the parsed From field + + - mb_list is the parsed mailbox list +*/ + +struct mailimf_from { + struct mailimf_mailbox_list * frm_mb_list; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_from * +mailimf_from_new(struct mailimf_mailbox_list * frm_mb_list); + +LIBETPAN_EXPORT +void mailimf_from_free(struct mailimf_from * from); + + + +/* + mailimf_sender is the parsed Sender field + + - snd_mb is the parsed mailbox +*/ + +struct mailimf_sender { + struct mailimf_mailbox * snd_mb; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_sender * mailimf_sender_new(struct mailimf_mailbox * snd_mb); + +LIBETPAN_EXPORT +void mailimf_sender_free(struct mailimf_sender * sender); + + + + +/* + mailimf_reply_to is the parsed Reply-To field + + - rt_addr_list is the parsed address list + */ + +struct mailimf_reply_to { + struct mailimf_address_list * rt_addr_list; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_reply_to * +mailimf_reply_to_new(struct mailimf_address_list * rt_addr_list); + +LIBETPAN_EXPORT +void mailimf_reply_to_free(struct mailimf_reply_to * reply_to); + + + + +/* + mailimf_to is the parsed To field + + - to_addr_list is the parsed address list +*/ + +struct mailimf_to { + struct mailimf_address_list * to_addr_list; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_to * mailimf_to_new(struct mailimf_address_list * to_addr_list); + +LIBETPAN_EXPORT +void mailimf_to_free(struct mailimf_to * to); + + + + +/* + mailimf_cc is the parsed Cc field + + - cc_addr_list is the parsed addres list +*/ + +struct mailimf_cc { + struct mailimf_address_list * cc_addr_list; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_cc * mailimf_cc_new(struct mailimf_address_list * cc_addr_list); + +LIBETPAN_EXPORT +void mailimf_cc_free(struct mailimf_cc * cc); + + + + +/* + mailimf_bcc is the parsed Bcc field + + - bcc_addr_list is the parsed addres list +*/ + +struct mailimf_bcc { + struct mailimf_address_list * bcc_addr_list; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_bcc * +mailimf_bcc_new(struct mailimf_address_list * bcc_addr_list); + +LIBETPAN_EXPORT +void mailimf_bcc_free(struct mailimf_bcc * bcc); + + + +/* + mailimf_message_id is the parsed Message-ID field + + - mid_value is the message identifier +*/ + +struct mailimf_message_id { + char * mid_value; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_message_id * mailimf_message_id_new(char * mid_value); + +LIBETPAN_EXPORT +void mailimf_message_id_free(struct mailimf_message_id * message_id); + + + + +/* + mailimf_in_reply_to is the parsed In-Reply-To field + + - mid_list is the list of message identifers +*/ + +struct mailimf_in_reply_to { + clist * mid_list; /* list of (char *), != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_in_reply_to * mailimf_in_reply_to_new(clist * mid_list); + +LIBETPAN_EXPORT +void mailimf_in_reply_to_free(struct mailimf_in_reply_to * in_reply_to); + + + +/* + mailimf_references is the parsed References field + + - msg_id_list is the list of message identifiers + */ + +struct mailimf_references { + clist * mid_list; /* list of (char *) */ + /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_references * mailimf_references_new(clist * mid_list); + +LIBETPAN_EXPORT +void mailimf_references_free(struct mailimf_references * references); + + + +/* + mailimf_subject is the parsed Subject field + + - sbj_value is the value of the field +*/ + +struct mailimf_subject { + char * sbj_value; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_subject * mailimf_subject_new(char * sbj_value); + +LIBETPAN_EXPORT +void mailimf_subject_free(struct mailimf_subject * subject); + + +/* + mailimf_comments is the parsed Comments field + + - cm_value is the value of the field +*/ + +struct mailimf_comments { + char * cm_value; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_comments * mailimf_comments_new(char * cm_value); + +LIBETPAN_EXPORT +void mailimf_comments_free(struct mailimf_comments * comments); + + +/* + mailimf_keywords is the parsed Keywords field + + - kw_list is the list of keywords +*/ + +struct mailimf_keywords { + clist * kw_list; /* list of (char *), != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_keywords * mailimf_keywords_new(clist * kw_list); + +LIBETPAN_EXPORT +void mailimf_keywords_free(struct mailimf_keywords * keywords); + + +/* + mailimf_return is the parsed Return-Path field + + - ret_path is the parsed value of Return-Path +*/ + +struct mailimf_return { + struct mailimf_path * ret_path; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_return * +mailimf_return_new(struct mailimf_path * ret_path); + +LIBETPAN_EXPORT +void mailimf_return_free(struct mailimf_return * return_path); + + +/* + mailimf_path is the parsed value of Return-Path + + - pt_addr_spec is a mailbox +*/ + +struct mailimf_path { + char * pt_addr_spec; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_path * mailimf_path_new(char * pt_addr_spec); + +LIBETPAN_EXPORT +void mailimf_path_free(struct mailimf_path * path); + + +/* + mailimf_optional_field is a non-parsed field + + - fld_name is the name of the field + + - fld_value is the value of the field +*/ + +struct mailimf_optional_field { + char * fld_name; /* != NULL */ + char * fld_value; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_optional_field * +mailimf_optional_field_new(char * fld_name, char * fld_value); + +LIBETPAN_EXPORT +void mailimf_optional_field_free(struct mailimf_optional_field * opt_field); + + +/* + mailimf_fields is the native structure that IMF module will use, + this module will provide an easier structure to use when parsing fields. + + mailimf_single_fields is an easier structure to get parsed fields, + rather than iteration over the list of fields + + - fld_orig_date is the parsed "Date" field + + - fld_from is the parsed "From" field + + - fld_sender is the parsed "Sender "field + + - fld_reply_to is the parsed "Reply-To" field + + - fld_to is the parsed "To" field + + - fld_cc is the parsed "Cc" field + + - fld_bcc is the parsed "Bcc" field + + - fld_message_id is the parsed "Message-ID" field + + - fld_in_reply_to is the parsed "In-Reply-To" field + + - fld_references is the parsed "References" field + + - fld_subject is the parsed "Subject" field + + - fld_comments is the parsed "Comments" field + + - fld_keywords is the parsed "Keywords" field +*/ + +struct mailimf_single_fields { + struct mailimf_orig_date * fld_orig_date; /* can be NULL */ + struct mailimf_from * fld_from; /* can be NULL */ + struct mailimf_sender * fld_sender; /* can be NULL */ + struct mailimf_reply_to * fld_reply_to; /* can be NULL */ + struct mailimf_to * fld_to; /* can be NULL */ + struct mailimf_cc * fld_cc; /* can be NULL */ + struct mailimf_bcc * fld_bcc; /* can be NULL */ + struct mailimf_message_id * fld_message_id; /* can be NULL */ + struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */ + struct mailimf_references * fld_references; /* can be NULL */ + struct mailimf_subject * fld_subject; /* can be NULL */ + struct mailimf_comments * fld_comments; /* can be NULL */ + struct mailimf_keywords * fld_keywords; /* can be NULL */ +}; + + + + + + +/* internal use */ + +LIBETPAN_EXPORT +void mailimf_atom_free(char * atom); + +LIBETPAN_EXPORT +void mailimf_dot_atom_free(char * dot_atom); + +LIBETPAN_EXPORT +void mailimf_dot_atom_text_free(char * dot_atom); + +LIBETPAN_EXPORT +void mailimf_quoted_string_free(char * quoted_string); + +LIBETPAN_EXPORT +void mailimf_word_free(char * word); + +LIBETPAN_EXPORT +void mailimf_phrase_free(char * phrase); + +LIBETPAN_EXPORT +void mailimf_unstructured_free(char * unstructured); + +LIBETPAN_EXPORT +void mailimf_angle_addr_free(char * angle_addr); + +LIBETPAN_EXPORT +void mailimf_display_name_free(char * display_name); + +LIBETPAN_EXPORT +void mailimf_addr_spec_free(char * addr_spec); + +LIBETPAN_EXPORT +void mailimf_local_part_free(char * local_part); + +LIBETPAN_EXPORT +void mailimf_domain_free(char * domain); + +LIBETPAN_EXPORT +void mailimf_domain_literal_free(char * domain); + +LIBETPAN_EXPORT +void mailimf_msg_id_free(char * msg_id); + +LIBETPAN_EXPORT +void mailimf_id_left_free(char * id_left); + +LIBETPAN_EXPORT +void mailimf_id_right_free(char * id_right); + +LIBETPAN_EXPORT +void mailimf_no_fold_quote_free(char * nfq); + +LIBETPAN_EXPORT +void mailimf_no_fold_literal_free(char * nfl); + +LIBETPAN_EXPORT +void mailimf_field_name_free(char * field_name); + + + +/* these are the possible returned error codes */ + +enum { + MAILIMF_NO_ERROR = 0, + MAILIMF_ERROR_PARSE, + MAILIMF_ERROR_MEMORY, + MAILIMF_ERROR_INVAL, + MAILIMF_ERROR_FILE +}; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailimf_types_helper.h b/Sources/libetpan/include/mailimf_types_helper.h new file mode 100644 index 00000000..724364ad --- /dev/null +++ b/Sources/libetpan/include/mailimf_types_helper.h @@ -0,0 +1,394 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf_types_helper.h,v 1.15 2007/12/10 21:32:59 hoa Exp $ + */ + +#ifndef MAILIMF_TYPES_HELPER + +#define MAILIMF_TYPES_HELPER + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimf_types.h" + +/* + IMPORTANT NOTE: + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + allocation functions will return NULL on failure +*/ + +/* + mailimf_mailbox_list_new_empty creates an empty list of mailboxes +*/ + +LIBETPAN_EXPORT +struct mailimf_mailbox_list * +mailimf_mailbox_list_new_empty(void); + +/* + mailimf_mailbox_list_add adds a mailbox to the list of mailboxes + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int mailimf_mailbox_list_add(struct mailimf_mailbox_list * mailbox_list, + struct mailimf_mailbox * mb); + +/* + mailimf_mailbox_list_add_parse parse the given string + into a mailimf_mailbox structure and adds it to the list of mailboxes + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int mailimf_mailbox_list_add_parse(struct mailimf_mailbox_list * mailbox_list, + char * mb_str); + +/* + mailimf_mailbox creates a mailimf_mailbox structure with the given + arguments and adds it to the list of mailboxes + + - display_name is the name that will be displayed for this mailbox, + for example 'name' in '"name" , + should be allocated with malloc() + + - address is the mailbox, for example 'mailbox@domain' + in '"name" , should be allocated with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int mailimf_mailbox_list_add_mb(struct mailimf_mailbox_list * mailbox_list, + char * display_name, char * address); + +/* + mailimf_address_list_new_empty creates an empty list of addresses +*/ + +LIBETPAN_EXPORT +struct mailimf_address_list * +mailimf_address_list_new_empty(void); + +/* + mailimf_address_list_add adds a mailbox to the list of addresses + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int mailimf_address_list_add(struct mailimf_address_list * address_list, + struct mailimf_address * addr); + +/* + mailimf_address_list_add_parse parse the given string + into a mailimf_address structure and adds it to the list of addresses + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int mailimf_address_list_add_parse(struct mailimf_address_list * address_list, + char * addr_str); + +/* + mailimf_address_list_add_mb creates a mailbox mailimf_address + with the given arguments and adds it to the list of addresses + + - display_name is the name that will be displayed for this mailbox, + for example 'name' in '"name" , + should be allocated with malloc() + + - address is the mailbox, for example 'mailbox@domain' + in '"name" , should be allocated with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int mailimf_address_list_add_mb(struct mailimf_address_list * address_list, + char * display_name, char * address); + +/* + mailimf_resent_fields_add_data adds a set of resent fields in the + given mailimf_fields structure. + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param resent_msg_id sould be allocated with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int +mailimf_resent_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * resent_date, + struct mailimf_mailbox_list * resent_from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc, + char * resent_msg_id); + +/* + mailimf_resent_fields_new_with_data_all creates a new mailimf_fields + structure with a set of resent fields + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param resent_msg_id sould be allocated with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +struct mailimf_fields * +mailimf_resent_fields_new_with_data_all(struct mailimf_date_time * + resent_date, struct mailimf_mailbox_list * resent_from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc, + char * resent_msg_id); + +/* + mailimf_resent_fields_new_with_data_all creates a new mailimf_fields + structure with a set of resent fields. + Resent-Date and Resent-Message-ID fields will be generated for you. + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +struct mailimf_fields * +mailimf_resent_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc); + +/* + this function creates a new mailimf_fields structure with no fields +*/ + +LIBETPAN_EXPORT +struct mailimf_fields * +mailimf_fields_new_empty(void); + + +/* + this function adds a field to the mailimf_fields structure + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int mailimf_fields_add(struct mailimf_fields * fields, + struct mailimf_field * field); + + +/* + mailimf_fields_add_data adds a set of fields in the + given mailimf_fields structure. + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param msg_id sould be allocated with malloc() + @param subject should be allocated with malloc() + @param in_reply_to each elements of this list should be allocated + with malloc() + @param references each elements of this list should be allocated + with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int mailimf_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * msg_id, + clist * in_reply_to, + clist * references, + char * subject); + +/* + mailimf_fields_new_with_data_all creates a new mailimf_fields + structure with a set of fields + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param message_id sould be allocated with malloc() + @param subject should be allocated with malloc() + @param in_reply_to each elements of this list should be allocated + with malloc() + @param references each elements of this list should be allocated + with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +struct mailimf_fields * +mailimf_fields_new_with_data_all(struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * message_id, + clist * in_reply_to, + clist * references, + char * subject); + +/* + mailimf_fields_new_with_data creates a new mailimf_fields + structure with a set of fields + Date and Message-ID fields will be generated for you. + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param subject should be allocated with malloc() + @param in_reply_to each elements of this list should be allocated + with malloc() + @param references each elements of this list should be allocated + with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +struct mailimf_fields * +mailimf_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + clist * in_reply_to, + clist * references, + char * subject); + +/* + this function returns an allocated message identifier to + use in a Message-ID or Resent-Message-ID field +*/ + +LIBETPAN_EXPORT +char * mailimf_get_message_id(void); + +/* + this function returns a mailimf_date_time structure to + use in a Date or Resent-Date field +*/ + +LIBETPAN_EXPORT +struct mailimf_date_time * mailimf_get_current_date(void); + +LIBETPAN_EXPORT +struct mailimf_date_time * mailimf_get_date(time_t time); + +/* + mailimf_single_fields_init fills a mailimf_single_fields structure + with the content of a mailimf_fields structure +*/ + +LIBETPAN_EXPORT +void mailimf_single_fields_init(struct mailimf_single_fields * single_fields, + struct mailimf_fields * fields); + +/* + mailimf_single_fields_new creates a new mailimf_single_fields and + fills the structure with mailimf_fields +*/ + +LIBETPAN_EXPORT +struct mailimf_single_fields * +mailimf_single_fields_new(struct mailimf_fields * fields); + +LIBETPAN_EXPORT +void mailimf_single_fields_free(struct mailimf_single_fields * + single_fields); + +/* + mailimf_field_new_custom creates a new field of type optional + + @param name should be allocated with malloc() + @param value should be allocated with malloc() +*/ + +LIBETPAN_EXPORT +struct mailimf_field * mailimf_field_new_custom(char * name, char * value); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailimf_write.h b/Sources/libetpan/include/mailimf_write.h new file mode 100644 index 00000000..b42ca7c9 --- /dev/null +++ b/Sources/libetpan/include/mailimf_write.h @@ -0,0 +1,134 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf_write.h,v 1.13 2004/11/21 21:53:37 hoa Exp $ + */ + +#ifndef MAILIMF_WRITE_H + +#define MAILIMF_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "mailimf_types.h" + +/* + mailimf_string_write writes a string to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +int mailimf_string_write(FILE * f, int * col, + const char * str, size_t length); + + +/* + mailimf_fields_write writes the fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +int mailimf_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_envelope_fields_write writes only some fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +int mailimf_envelope_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_field_write writes a field to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param field is the field to write +*/ + +int mailimf_field_write(FILE * f, int * col, + struct mailimf_field * field); + +/* + mailimf_quoted_string_write writes a string that is quoted + to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param string is the string to quote and write +*/ + +int mailimf_quoted_string_write(FILE * f, int * col, + const char * string, size_t len); + +int mailimf_address_list_write(FILE * f, int * col, + struct mailimf_address_list * addr_list); + +int mailimf_mailbox_list_write(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list); + +/* + mailimf_header_string_write writes a header value and fold the header + if needed. + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +int mailimf_header_string_write(FILE * f, int * col, + const char * str, size_t length); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailimf_write_file.h b/Sources/libetpan/include/mailimf_write_file.h new file mode 100644 index 00000000..6760fce5 --- /dev/null +++ b/Sources/libetpan/include/mailimf_write_file.h @@ -0,0 +1,180 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf_write_file.h,v 1.3 2005/06/01 12:22:18 smarinier Exp $ + */ + +#ifndef MAILIMF_WRITE_H + +#define MAILIMF_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stdio.h" +#include "mailimf_types.h" + +#define MAILIMF_WRITE_COMPATIBILITY + +/* + mailimf_string_write_file writes a string to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ +LIBETPAN_EXPORT +int mailimf_string_write_file(FILE * f, int * col, + const char * str, size_t length); + + +/* + mailimf_fields_write_file writes the fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ +LIBETPAN_EXPORT +int mailimf_fields_write_file(FILE * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_envelope_fields_write_file writes only some fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ +LIBETPAN_EXPORT +int mailimf_envelope_fields_write_file(FILE * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_field_write_file writes a field to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param field is the field to write +*/ +LIBETPAN_EXPORT +int mailimf_field_write_file(FILE * f, int * col, + struct mailimf_field * field); + +/* + mailimf_quoted_string_write_file writes a string that is quoted + to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param string is the string to quote and write +*/ +LIBETPAN_EXPORT +int mailimf_quoted_string_write_file(FILE * f, int * col, + const char * string, size_t len); + +LIBETPAN_EXPORT +int mailimf_address_list_write_file(FILE * f, int * col, + struct mailimf_address_list * addr_list); + +LIBETPAN_EXPORT +int mailimf_mailbox_list_write_file(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list); + +/* + mailimf_header_string_write_file writes a header value and fold the header + if needed. + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +LIBETPAN_EXPORT +int mailimf_header_string_write_file(FILE * f, int * col, + const char * str, size_t length); + + + +/* binary compatibility with 0.34 - begin */ + +#ifdef MAILIMF_WRITE_COMPATIBILITY +LIBETPAN_EXPORT +int mailimf_string_write(FILE * f, int * col, + const char * str, size_t length); + +LIBETPAN_EXPORT +int mailimf_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + +LIBETPAN_EXPORT +int mailimf_envelope_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + +LIBETPAN_EXPORT +int mailimf_field_write(FILE * f, int * col, + struct mailimf_field * field); + +LIBETPAN_EXPORT +int mailimf_quoted_string_write(FILE * f, int * col, + const char * string, size_t len); + +LIBETPAN_EXPORT +int mailimf_address_list_write(FILE * f, int * col, + struct mailimf_address_list * addr_list); + +LIBETPAN_EXPORT +int mailimf_mailbox_list_write(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list); + +LIBETPAN_EXPORT +int mailimf_header_string_write(FILE * f, int * col, + const char * str, size_t length); +#endif + +/* binary compatibility with 0.34 - end */ + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailimf_write_generic.h b/Sources/libetpan/include/mailimf_write_generic.h new file mode 100644 index 00000000..99322065 --- /dev/null +++ b/Sources/libetpan/include/mailimf_write_generic.h @@ -0,0 +1,150 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf_write_generic.h,v 1.3 2007/12/10 21:32:59 hoa Exp $ + */ + +#ifndef MAILIMF_WRITE_GENERIC_H + +#define MAILIMF_WRITE_GENERIC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stdio.h" +#include "mailimf_types.h" + +/* + mailimf_string_write writes a string to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +LIBETPAN_EXPORT +int mailimf_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + const char * str, size_t length); + + +/* + mailimf_fields_write writes the fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +LIBETPAN_EXPORT +int mailimf_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + struct mailimf_fields * fields); + + +/* + mailimf_envelope_fields_write writes only some fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +LIBETPAN_EXPORT +int mailimf_envelope_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + struct mailimf_fields * fields); + + +/* + mailimf_field_write writes a field to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param field is the field to write +*/ + +LIBETPAN_EXPORT +int mailimf_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + struct mailimf_field * field); + +/* + mailimf_quoted_string_write writes a string that is quoted + to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param string is the string to quote and write +*/ + +LIBETPAN_EXPORT +int mailimf_quoted_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + const char * string, size_t len); + +LIBETPAN_EXPORT +int mailimf_address_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + struct mailimf_address_list * addr_list); + +LIBETPAN_EXPORT +int mailimf_mailbox_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + struct mailimf_mailbox_list * mb_list); + +/* + mailimf_header_string_write writes a header value and fold the header + if needed. + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +LIBETPAN_EXPORT +int mailimf_header_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + const char * str, size_t length); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailimf_write_mem.h b/Sources/libetpan/include/mailimf_write_mem.h new file mode 100644 index 00000000..30e1825f --- /dev/null +++ b/Sources/libetpan/include/mailimf_write_mem.h @@ -0,0 +1,143 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf_write_mem.h,v 1.2 2004/11/21 21:53:37 hoa Exp $ + */ + +#ifndef MAILIMF_WRITE_MEM_H + +#define MAILIMF_WRITE_MEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stdio.h" +#include "mailimf_types.h" +#include "mmapstring.h" + +/* + mailimf_string_write_mem appends a string to a given string + + @param f is the string + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +LIBETPAN_EXPORT +int mailimf_string_write_mem(MMAPString * f, int * col, + const char * str, size_t length); + + +/* + mailimf_fields_write_mem appends the fields to a given string + + @param f is the string + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +LIBETPAN_EXPORT +int mailimf_fields_write_mem(MMAPString * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_envelope_fields_write_mem appends some fields to a given string + + @param f is the string + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +LIBETPAN_EXPORT +int mailimf_envelope_fields_write_mem(MMAPString * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_field_write_mem appends a field to a given string + + @param f is the string + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param field is the field to write +*/ + +LIBETPAN_EXPORT +int mailimf_field_write_mem(MMAPString * f, int * col, + struct mailimf_field * field); + +/* + mailimf_quoted_string_write_mem appends a string that is quoted + to a given string + + @param f is the string + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param string is the string to quote and write +*/ + +LIBETPAN_EXPORT +int mailimf_quoted_string_write_mem(MMAPString * f, int * col, + const char * string, size_t len); + +LIBETPAN_EXPORT +int mailimf_address_list_write_mem(MMAPString * f, int * col, + struct mailimf_address_list * addr_list); + +LIBETPAN_EXPORT +int mailimf_mailbox_list_write_mem(MMAPString * f, int * col, + struct mailimf_mailbox_list * mb_list); + +/* + mailimf_header_string_write_mem appends a header value and fold the header + if needed. + + @param f is the string + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +LIBETPAN_EXPORT +int mailimf_header_string_write_mem(MMAPString * f, int * col, + const char * str, size_t length); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/maillock.h b/Sources/libetpan/include/maillock.h new file mode 100644 index 00000000..c4d2a794 --- /dev/null +++ b/Sources/libetpan/include/maillock.h @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maillock.h,v 1.5 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef MAILLOCK_H + +#define MAILLOCK_H + +#ifdef __cplusplus +extern "C" { +#endif + +int maillock_read_lock(const char * filename, int fd); +int maillock_read_unlock(const char * filename, int fd); +int maillock_write_lock(const char * filename, int fd); +int maillock_write_unlock(const char * filename, int fd); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailmbox.h b/Sources/libetpan/include/mailmbox.h new file mode 100644 index 00000000..817880cc --- /dev/null +++ b/Sources/libetpan/include/mailmbox.h @@ -0,0 +1,144 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmbox.h,v 1.19 2004/11/21 21:53:38 hoa Exp $ + */ + +#ifndef MAILMBOX_H + +#define MAILMBOX_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailmbox_types.h" + +int +mailmbox_append_message_list(struct mailmbox_folder * folder, + carray * append_tab); + +int +mailmbox_append_message(struct mailmbox_folder * folder, + const char * data, size_t len); + +int +mailmbox_append_message_uid(struct mailmbox_folder * folder, + const char * data, size_t len, unsigned int * puid); + +int mailmbox_fetch_msg(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len); + +int mailmbox_fetch_msg_headers(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len); + +void mailmbox_fetch_result_free(char * msg); + +int mailmbox_copy_msg_list(struct mailmbox_folder * dest_folder, + struct mailmbox_folder * src_folder, + carray * tab); + +int mailmbox_copy_msg(struct mailmbox_folder * dest_folder, + struct mailmbox_folder * src_folder, + uint32_t uid); + +int mailmbox_expunge(struct mailmbox_folder * folder); + +int mailmbox_delete_msg(struct mailmbox_folder * folder, uint32_t uid); + +int mailmbox_init(const char * filename, + int force_readonly, + int force_no_uid, + uint32_t default_written_uid, + struct mailmbox_folder ** result_folder); + +void mailmbox_done(struct mailmbox_folder * folder); + +/* low-level access primitives */ + +int mailmbox_write_lock(struct mailmbox_folder * folder); + +int mailmbox_write_unlock(struct mailmbox_folder * folder); + +int mailmbox_read_lock(struct mailmbox_folder * folder); + +int mailmbox_read_unlock(struct mailmbox_folder * folder); + + +/* memory map */ + +int mailmbox_map(struct mailmbox_folder * folder); + +void mailmbox_unmap(struct mailmbox_folder * folder); + +void mailmbox_sync(struct mailmbox_folder * folder); + + +/* open & close file */ + +int mailmbox_open(struct mailmbox_folder * folder); + +void mailmbox_close(struct mailmbox_folder * folder); + + +/* validate cache */ + +int mailmbox_validate_write_lock(struct mailmbox_folder * folder); + +int mailmbox_validate_read_lock(struct mailmbox_folder * folder); + + +/* fetch message */ + +int mailmbox_fetch_msg_no_lock(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len); + +int mailmbox_fetch_msg_headers_no_lock(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len); + +/* append message */ + +int +mailmbox_append_message_list_no_lock(struct mailmbox_folder * folder, + carray * append_tab); + +int mailmbox_expunge_no_lock(struct mailmbox_folder * folder); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailmbox_parse.h b/Sources/libetpan/include/mailmbox_parse.h new file mode 100644 index 00000000..a7887503 --- /dev/null +++ b/Sources/libetpan/include/mailmbox_parse.h @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmbox_parse.h,v 1.4 2008/02/20 22:15:52 hoa Exp $ + */ + +#ifndef MAILMBOX_PARSE_H + +#define MAILMBOX_PARSE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailmbox_types.h" + +int mailmbox_parse(struct mailmbox_folder * folder); + +int +mailmbox_parse_additionnal(struct mailmbox_folder * folder, + size_t * indx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailmbox_types.h b/Sources/libetpan/include/mailmbox_types.h new file mode 100644 index 00000000..24bc6b02 --- /dev/null +++ b/Sources/libetpan/include/mailmbox_types.h @@ -0,0 +1,143 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmbox_types.h,v 1.27 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifndef MAILMBOX_TYPES_H + +#define MAILMBOX_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "sys/types.h" + +#include "libetpan-config.h" + +#include "mailimf.h" +#include "carray.h" +#include "chash.h" + +enum { + MAILMBOX_NO_ERROR = 0, + MAILMBOX_ERROR_PARSE, + MAILMBOX_ERROR_INVAL, + MAILMBOX_ERROR_FILE_NOT_FOUND, + MAILMBOX_ERROR_MEMORY, + MAILMBOX_ERROR_TEMPORARY_FILE, + MAILMBOX_ERROR_FILE, + MAILMBOX_ERROR_MSG_NOT_FOUND, + MAILMBOX_ERROR_READONLY +}; + + +struct mailmbox_folder { + char mb_filename[PATH_MAX]; + + time_t mb_mtime; + + int mb_fd; + int mb_read_only; + int mb_no_uid; + + int mb_changed; + unsigned int mb_deleted_count; + + char * mb_mapping; + size_t mb_mapping_size; + + uint32_t mb_written_uid; + uint32_t mb_max_uid; + + chash * mb_hash; + carray * mb_tab; +}; + +struct mailmbox_folder * mailmbox_folder_new(const char * mb_filename); +void mailmbox_folder_free(struct mailmbox_folder * folder); + + +struct mailmbox_msg_info { + unsigned int msg_index; + uint32_t msg_uid; + int msg_written_uid; + int msg_deleted; + + size_t msg_start; + size_t msg_start_len; + + size_t msg_headers; + size_t msg_headers_len; + + size_t msg_body; + size_t msg_body_len; + + size_t msg_size; + + size_t msg_padding; +}; + + +int mailmbox_msg_info_update(struct mailmbox_folder * folder, + size_t msg_start, size_t msg_start_len, + size_t msg_headers, size_t msg_headers_len, + size_t msg_body, size_t msg_body_len, + size_t msg_size, size_t msg_padding, + uint32_t msg_uid); + +struct mailmbox_msg_info * +mailmbox_msg_info_new(size_t msg_start, size_t msg_start_len, + size_t msg_headers, size_t msg_headers_len, + size_t msg_body, size_t msg_body_len, + size_t msg_size, size_t msg_padding, + uint32_t msg_uid); + +void mailmbox_msg_info_free(struct mailmbox_msg_info * info); + +struct mailmbox_append_info { + const char * ai_message; + size_t ai_size; + unsigned int ai_uid; +}; + +struct mailmbox_append_info * +mailmbox_append_info_new(const char * ai_message, size_t ai_size); + +void mailmbox_append_info_free(struct mailmbox_append_info * info); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailmessage.h b/Sources/libetpan/include/mailmessage.h new file mode 100644 index 00000000..0663ebad --- /dev/null +++ b/Sources/libetpan/include/mailmessage.h @@ -0,0 +1,379 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmessage.h,v 1.17 2008/02/20 22:15:51 hoa Exp $ + */ + +#include "mailmessage_types.h" + +#ifndef MAILMESSAGE_H + +#define MAILMESSAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mailmessage_new + + This function will initializes a new empty message. + + @return a new empty message will be returned. +*/ +LIBETPAN_EXPORT +mailmessage * mailmessage_new(void); + +/* + mailmessage_free + + This function will release the memory used by this message. +*/ +LIBETPAN_EXPORT +void mailmessage_free(mailmessage * info); + +/* + mailmessage_init + + This function will initializes a mailmessage structure + with a message from a given session. + + @param msg_info This is the message to initialize. + + @param session This is the source session of the message. It + can be NULL if the message does not get the information + through the session. + + @param driver This is the driver to use for the message. + + @param indx This is the message number in the session. 0 can + be given if the message is not attached to a session. + + @param size is an optional parameter, 0 can be given. + This is informational. This is the size of message content. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ +LIBETPAN_EXPORT +int mailmessage_init(mailmessage * msg_info, + mailsession * session, + mailmessage_driver * driver, + uint32_t indx, size_t size); + +/* + mailmessage_flush + + This function will release all the temporary resources that are not + necessary to use the mailmessage structure from memory. These + resources are for example cached information, such as the MIME + structure. + + @param info is the message to clean. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. We can assume that MAIL_NO_ERROR is always returned. +*/ +LIBETPAN_EXPORT +int mailmessage_flush(mailmessage * info); + +/* + mailmessage_check + + This function will notify the new value of the flags to the session, + it must be called before mailsession_check_folder() in case the flags have + been changed. + + @param info is the message to checkpoint. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. We can assume that MAIL_NO_ERROR is always returned. +*/ +LIBETPAN_EXPORT +int mailmessage_check(mailmessage * info); + +/* + mailmessage_fetch_result_free + + This function releases the memory used by a message returned + by any of the fetch function that returns a (char *). + + @param msg_info is the message which the given buffer is from. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. We can assume that MAIL_NO_ERROR is always returned. +*/ +LIBETPAN_EXPORT +int mailmessage_fetch_result_free(mailmessage * msg_info, + char * msg); + +/* + mailmessage_fetch + + This function returns the content of the message (headers and text). + + @param msg_info is the message from which we want to fetch information. + + @param result The content of the message is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +int mailmessage_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len); + +/* + mailmessage_fetch_header + + This function returns the header of the message as a string. + + @param msg_info is the message from which we want to fetch information. + + @param result The header of the message is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +int mailmessage_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +/* + mailmessage_fetch_body + + This function returns the content of the message (without headers). + + @param msg_info is the message from which we want to fetch information. + @param result The message text (without headers) is returned + in (* result) + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +int mailmessage_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len); + +/* + mailmessage_fetch_size + + This function returns the size of the message content. + + @param msg_info is the message from which we want to fetch information. + + @param result The length of the message content is stored in (* result). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +int mailmessage_fetch_size(mailmessage * msg_info, + size_t * result); + +/* + mailmessage_get_bodystructure + + This functions returns the MIME structure of the message. + The returned information MUST not be freed by hand. It is freed by + mailmessage_flush() or mailmessage_free(). + + @param msg_info is the message from which we want to fetch information. + + @param result The MIME structure is stored in (* result). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +int mailmessage_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result); + +/* + mailmessage_fetch_section + + This function returns the content of a MIME part. + + @param msg_info is the message from which we want to fetch information. + + @param mime is the MIME part identifier. + + @param result The content is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. + */ +LIBETPAN_EXPORT +int mailmessage_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + +/* + mailmessage_fetch_section_header + + This function returns the header of the message contained + in the given MIME part. + + @param msg_info is the message from which we want to fetch information. + + @param mime is the MIME part identifier. + + @param result The header is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +int mailmessage_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +/* + mailmessage_fetch_section_mime + + This function returns the MIME header of the given MIME part. + + @param msg_info is the message from which we want to fetch information. + + @param mime is the MIME part identifier. + + @param result The MIME header is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +int mailmessage_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +/* + mailmessage_fetch_section_body + + This function returns the text part of the message contained + in the given MIME part. + + @param msg_info is the message from which we want to fetch information. + + @param mime is the MIME part identifier. + + @param result The message text is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. + */ +LIBETPAN_EXPORT +int mailmessage_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +/* + mailmessage_fetch_envelope + + This function returns a list of parsed fields of the message, + chosen by the driver. + The returned structure must be freed with mailimf_fields_free(). + + @param msg_info is the message from which we want to fetch information. + + @param result The headers list is returned in (* result) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. + */ +LIBETPAN_EXPORT +int mailmessage_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result); + + +/* + mailmessage_get_flags + + This function returns the flags related to the message. + The returned information MUST not be freed by hand. It is freed by + mailmessage_free(). + + @param msg_info is the message from which we want to fetch information. + + @param result The flags are stored in (* result). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +int mailmessage_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +/* + mailmessage_resolve_single_fields + + This function will use the fields information to fill the single_fields + structure in the mailmessage structure. + + @param msg_info This is the msg_info to process. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +void mailmessage_resolve_single_fields(mailmessage * msg_info); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailmessage_tools.h b/Sources/libetpan/include/mailmessage_tools.h new file mode 100644 index 00000000..bfe29ebb --- /dev/null +++ b/Sources/libetpan/include/mailmessage_tools.h @@ -0,0 +1,103 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmessage_tools.h,v 1.7 2004/11/21 21:53:35 hoa Exp $ + */ + +#ifndef MAILMESSAGE_TOOLS_H + +#define MAILMESSAGE_TOOLS_H + +#include "mailmessage_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int +mailmessage_generic_initialize(mailmessage * + msg_info); + +void mailmessage_generic_uninitialize(mailmessage * + msg_info); + +void mailmessage_generic_flush(mailmessage * msg_info); + +void mailmessage_generic_fetch_result_free(mailmessage * msg_info, + char * msg); + +int mailmessage_generic_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len); + +int mailmessage_generic_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +int mailmessage_generic_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len); + +int mailmessage_generic_get_bodystructure(mailmessage * + msg_info, + struct mailmime ** result); + +int +mailmessage_generic_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + +int +mailmessage_generic_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +int +mailmessage_generic_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +int +mailmessage_generic_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +int mailmessage_generic_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailmessage_types.h b/Sources/libetpan/include/mailmessage_types.h new file mode 100644 index 00000000..f4e80f34 --- /dev/null +++ b/Sources/libetpan/include/mailmessage_types.h @@ -0,0 +1,50 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmessage_types.h,v 1.9 2004/11/21 21:53:35 hoa Exp $ + */ + +#ifndef MAILMESSAGE_TYPES_H + +#define MAILMESSAGE_TYPES_H + +#include "maildriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailmh.h b/Sources/libetpan/include/mailmh.h new file mode 100644 index 00000000..81958a5c --- /dev/null +++ b/Sources/libetpan/include/mailmh.h @@ -0,0 +1,147 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmh.h,v 1.27 2008/02/20 22:15:52 hoa Exp $ + */ + +#ifndef MAILMH_H + +#define MAILMH_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "sys/types.h" + +#include "libetpan-config.h" +#include "carray.h" +#include "chash.h" + +enum { + MAILMH_NO_ERROR = 0, + MAILMH_ERROR_FOLDER, + MAILMH_ERROR_MEMORY, + MAILMH_ERROR_FILE, + MAILMH_ERROR_COULD_NOT_ALLOC_MSG, + MAILMH_ERROR_RENAME, + MAILMH_ERROR_MSG_NOT_FOUND +}; + +struct mailmh { + struct mailmh_folder * mh_main; +}; + +struct mailmh_msg_info { + unsigned int msg_array_index; + uint32_t msg_index; + size_t msg_size; + time_t msg_mtime; +}; + +struct mailmh_folder { + char * fl_filename; + unsigned int fl_array_index; + + char * fl_name; + time_t fl_mtime; + struct mailmh_folder * fl_parent; + uint32_t fl_max_index; + + carray * fl_msgs_tab; + chash * fl_msgs_hash; + + carray * fl_subfolders_tab; + chash * fl_subfolders_hash; +}; + +struct mailmh * mailmh_new(const char * foldername); +void mailmh_free(struct mailmh * f); + +struct mailmh_msg_info * +mailmh_msg_info_new(uint32_t indx, size_t size, time_t mtime); +void mailmh_msg_info_free(struct mailmh_msg_info * msg_info); + +struct mailmh_folder * mailmh_folder_new(struct mailmh_folder * parent, + const char * name); +void mailmh_folder_free(struct mailmh_folder * folder); + +int mailmh_folder_add_subfolder(struct mailmh_folder * parent, + const char * name); + +struct mailmh_folder * mailmh_folder_find(struct mailmh_folder * root, + const char * filename); + +int mailmh_folder_remove_subfolder(struct mailmh_folder * folder); + +int mailmh_folder_rename_subfolder(struct mailmh_folder * src_folder, + struct mailmh_folder * dst_folder, + const char * new_name); + +int mailmh_folder_get_message_filename(struct mailmh_folder * folder, + uint32_t indx, char ** result); + +int mailmh_folder_get_message_fd(struct mailmh_folder * folder, + uint32_t indx, int flags, int * result); + +int mailmh_folder_get_message_size(struct mailmh_folder * folder, + uint32_t indx, size_t * result); + +int mailmh_folder_add_message_uid(struct mailmh_folder * folder, + const char * message, size_t size, + uint32_t * pindex); + +int mailmh_folder_add_message(struct mailmh_folder * folder, + const char * message, size_t size); + +int mailmh_folder_add_message_file_uid(struct mailmh_folder * folder, + int fd, uint32_t * pindex); + +int mailmh_folder_add_message_file(struct mailmh_folder * folder, + int fd); + +int mailmh_folder_remove_message(struct mailmh_folder * folder, + uint32_t indx); + +int mailmh_folder_move_message(struct mailmh_folder * dest_folder, + struct mailmh_folder * src_folder, + uint32_t indx); + +int mailmh_folder_update(struct mailmh_folder * folder); + +unsigned int mailmh_folder_get_message_number(struct mailmh_folder * folder); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailmime.h b/Sources/libetpan/include/mailmime.h new file mode 100644 index 00000000..76c72b03 --- /dev/null +++ b/Sources/libetpan/include/mailmime.h @@ -0,0 +1,118 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime.h,v 1.18 2011/01/06 00:09:52 hoa Exp $ + */ + +#ifndef MAILMIME_H + +#define MAILMIME_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimf.h" +#include "mailmime_types.h" +#include "mailmime_types_helper.h" +#include "mailmime_content.h" +#include "mailmime_decode.h" +#include "mailmime_disposition.h" +#include "mailmime_write_file.h" +#include "mailmime_write_mem.h" +#include "mailmime_write_generic.h" + +LIBETPAN_EXPORT +int mailmime_content_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_content ** result); + +LIBETPAN_EXPORT +int mailmime_description_parse(const char * message, size_t length, + size_t * indx, + char ** result); + +LIBETPAN_EXPORT +int mailmime_location_parse(const char * message, size_t length, + size_t * indx, + char ** result); + +LIBETPAN_EXPORT +int mailmime_encoding_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_mechanism ** result); + +LIBETPAN_EXPORT +int +mailmime_field_parse(struct mailimf_optional_field * field, + struct mailmime_field ** result); + +LIBETPAN_EXPORT +int mailmime_id_parse(const char * message, size_t length, + size_t * indx, char ** result); + +LIBETPAN_EXPORT +int +mailmime_fields_parse(struct mailimf_fields * + fields, + struct mailmime_fields ** + result); + +LIBETPAN_EXPORT +int mailmime_version_parse(const char * message, size_t length, + size_t * indx, + uint32_t * result); + +LIBETPAN_EXPORT +int +mailmime_extension_token_parse(const char * message, size_t length, + size_t * indx, char ** result); + +LIBETPAN_EXPORT +int mailmime_parameter_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_parameter ** result); + +LIBETPAN_EXPORT +int mailmime_value_parse(const char * message, size_t length, + size_t * indx, char ** result); + +LIBETPAN_EXPORT +int mailmime_language_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_language ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailmime_content.h b/Sources/libetpan/include/mailmime_content.h new file mode 100644 index 00000000..e702237d --- /dev/null +++ b/Sources/libetpan/include/mailmime_content.h @@ -0,0 +1,173 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_content.h,v 1.16 2008/02/20 22:15:52 hoa Exp $ + */ + +#ifndef MAILMIME_CONTENT_H + +#define MAILMIME_CONTENT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailmime_types.h" + +LIBETPAN_EXPORT +char * mailmime_content_charset_get(struct mailmime_content * content); + +LIBETPAN_EXPORT +char * mailmime_content_param_get(struct mailmime_content * content, + char * name); + +LIBETPAN_EXPORT +int mailmime_parse(const char * message, size_t length, + size_t * indx, struct mailmime ** result); + +LIBETPAN_EXPORT +int mailmime_get_section(struct mailmime * mime, + struct mailmime_section * section, + struct mailmime ** result); + + +LIBETPAN_EXPORT +char * mailmime_extract_boundary(struct mailmime_content * content_type); + + +/* decode */ + +LIBETPAN_EXPORT +int mailmime_base64_body_parse(const char * message, size_t length, + size_t * indx, char ** result, + size_t * result_len); + +LIBETPAN_EXPORT +int mailmime_quoted_printable_body_parse(const char * message, size_t length, + size_t * indx, char ** result, + size_t * result_len, int in_header); + + +LIBETPAN_EXPORT +int mailmime_binary_body_parse(const char * message, size_t length, + size_t * indx, char ** result, + size_t * result_len); + +/* + mailmime_part_parse() + + This function gets full MIME part for parsing at once. + It is not suitable, if we want parse incomplete message in a stream mode. + + @return the return code is one of MAILIMF_ERROR_XXX or + MAILIMF_NO_ERROR codes + */ +LIBETPAN_EXPORT +int mailmime_part_parse(const char * message, size_t length, + size_t * indx, + int encoding, char ** result, size_t * result_len); + + +/* + mailmime_part_parse_partial() + + This function may parse incomplete MIME part (i.e. in streaming mode). + It stops when detect incomplete encoding unit at the end of data. + Position of the first unparsed byte will be returned in (*indx) value. + + For parsing last portion of data must be used mailmime_part_parse() version. + + @param message Message for unparsed data. + @param length Length of the unparsed data. + @param INOUT indx Index of first unparsed symbol in the message. + @param encoding Encoding of the input data. + @param result Parsed MIME part content. Must be freed with mmap_string_unref(). + @param result_len Length of parsed data. + + @return the return code is one of MAILIMF_ERROR_XXX or + MAILIMF_NO_ERROR codes + + Example Usage: + @code + uint32_t received = 0; + uint32_t partLength = bodystructure[partId]->length; + for (;;) { + bool isThisRangeLast; + struct imap_range_t range = { received, 1024*1024 }; + char *result; + size_t result_len; + int error = imap_fetch_part_range(uid, partId, range, &result, &result_len); + if (error != NoError) { + // handle network error + break; + } + + if (result_len == 0) { + // requested range is empty. part is completely fetched + break; + } + + isThisRangeLast = (received + result_len >= partLength); // determine that the received data is the last, + // may be more difficult (in case of invalid metadata on the server). + + char *decoded; + size_t decoded_len; + if (isThisRangeLast) { + uint32_t index = 0; + mailmime_part_parse(result, result_len, encoding, &index, &decoded, &decoded_len); + break; + } + else { + uint32_t index = 0; + mailmime_part_parse_partial(result, result_len, encoding, &index, &decoded, &decoded_len); + // we may have some non-decoded bytes at the end of chunk. + // in this case we just request it in the next chunk + received += index; + } + } + @endcode + */ +LIBETPAN_EXPORT +int mailmime_part_parse_partial(const char * message, size_t length, + size_t * indx, + int encoding, char ** result, size_t * result_len); + + +LIBETPAN_EXPORT +int mailmime_get_section_id(struct mailmime * mime, + struct mailmime_section ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailmime_decode.h b/Sources/libetpan/include/mailmime_decode.h new file mode 100644 index 00000000..907f269d --- /dev/null +++ b/Sources/libetpan/include/mailmime_decode.h @@ -0,0 +1,62 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_decode.h,v 1.14 2008/02/20 22:15:52 hoa Exp $ + */ + +#ifndef MAILMIME_DECODE_H + +#define MAILMIME_DECODE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailmime_types.h" + +LIBETPAN_EXPORT +int mailmime_encoded_phrase_parse(const char * default_fromcode, + const char * message, size_t length, + size_t * indx, const char * tocode, + char ** result); + +int +mailmime_encoded_word_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_encoded_word ** result, + int * p_has_fwd, int * p_missing_closing_quote); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailmime_disposition.h b/Sources/libetpan/include/mailmime_disposition.h new file mode 100644 index 00000000..1ac544ab --- /dev/null +++ b/Sources/libetpan/include/mailmime_disposition.h @@ -0,0 +1,62 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_disposition.h,v 1.11 2008/02/20 22:15:52 hoa Exp $ + */ + +#ifndef MAILMIME_DISPOSITION_H + +#define MAILMIME_DISPOSITION_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailmime_types.h" + +int mailmime_disposition_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_disposition ** result); + +int +mailmime_disposition_type_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_disposition_type ** result); + +int mailmime_disposition_guess_type(const char * message, size_t length, + size_t indx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailmime_types.h b/Sources/libetpan/include/mailmime_types.h new file mode 100644 index 00000000..efac6ded --- /dev/null +++ b/Sources/libetpan/include/mailmime_types.h @@ -0,0 +1,503 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_types.h,v 1.33 2011/01/06 00:09:52 hoa Exp $ + */ + +#ifndef MAILMIME_TYPES_H + +#define MAILMIME_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef LIBETPAN_CONFIG_H +# include "libetpan-config.h" +#endif + +#ifdef HAVE_INTTYPES_H +# include +#endif +#include "mailimf.h" +#include "clist.h" + +enum { + MAILMIME_COMPOSITE_TYPE_ERROR, + MAILMIME_COMPOSITE_TYPE_MESSAGE, + MAILMIME_COMPOSITE_TYPE_MULTIPART, + MAILMIME_COMPOSITE_TYPE_EXTENSION +}; + +struct mailmime_composite_type { + int ct_type; + char * ct_token; +}; + + +struct mailmime_content { + struct mailmime_type * ct_type; + char * ct_subtype; + clist * ct_parameters; /* elements are (struct mailmime_parameter *) */ +}; + + +enum { + MAILMIME_DISCRETE_TYPE_ERROR, + MAILMIME_DISCRETE_TYPE_TEXT, + MAILMIME_DISCRETE_TYPE_IMAGE, + MAILMIME_DISCRETE_TYPE_AUDIO, + MAILMIME_DISCRETE_TYPE_VIDEO, + MAILMIME_DISCRETE_TYPE_APPLICATION, + MAILMIME_DISCRETE_TYPE_EXTENSION +}; + +struct mailmime_discrete_type { + int dt_type; + char * dt_extension; +}; + +enum { + MAILMIME_FIELD_NONE, + MAILMIME_FIELD_TYPE, + MAILMIME_FIELD_TRANSFER_ENCODING, + MAILMIME_FIELD_ID, + MAILMIME_FIELD_DESCRIPTION, + MAILMIME_FIELD_VERSION, + MAILMIME_FIELD_DISPOSITION, + MAILMIME_FIELD_LANGUAGE, + MAILMIME_FIELD_LOCATION +}; + +struct mailmime_field { + int fld_type; + union { + struct mailmime_content * fld_content; + struct mailmime_mechanism * fld_encoding; + char * fld_id; + char * fld_description; + uint32_t fld_version; + struct mailmime_disposition * fld_disposition; + struct mailmime_language * fld_language; + char * fld_location; + } fld_data; +}; + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +struct mailmime_mechanism { + int enc_type; + char * enc_token; +}; + + +struct mailmime_fields { + clist * fld_list; /* list of (struct mailmime_field *) */ +}; + + +struct mailmime_parameter { + char * pa_name; + char * pa_value; +}; + +enum { + MAILMIME_TYPE_ERROR, + MAILMIME_TYPE_DISCRETE_TYPE, + MAILMIME_TYPE_COMPOSITE_TYPE +}; + +struct mailmime_type { + int tp_type; + union { + struct mailmime_discrete_type * tp_discrete_type; + struct mailmime_composite_type * tp_composite_type; + } tp_data; +}; + +LIBETPAN_EXPORT +void mailmime_attribute_free(char * attribute); + +LIBETPAN_EXPORT +struct mailmime_composite_type * +mailmime_composite_type_new(int ct_type, char * ct_token); + +LIBETPAN_EXPORT +void mailmime_composite_type_free(struct mailmime_composite_type * ct); + +LIBETPAN_EXPORT +struct mailmime_content * +mailmime_content_new(struct mailmime_type * ct_type, + char * ct_subtype, + clist * ct_parameters); + +LIBETPAN_EXPORT +void mailmime_content_free(struct mailmime_content * content); + +LIBETPAN_EXPORT +void mailmime_description_free(char * description); + +LIBETPAN_EXPORT +void mailmime_location_free(char * location); + +LIBETPAN_EXPORT +struct mailmime_discrete_type * +mailmime_discrete_type_new(int dt_type, char * dt_extension); + +LIBETPAN_EXPORT +void mailmime_discrete_type_free(struct mailmime_discrete_type * + discrete_type); + +LIBETPAN_EXPORT +void mailmime_encoding_free(struct mailmime_mechanism * encoding); + +LIBETPAN_EXPORT +void mailmime_extension_token_free(char * extension); + +LIBETPAN_EXPORT +void mailmime_id_free(char * id); + +LIBETPAN_EXPORT +struct mailmime_mechanism * mailmime_mechanism_new(int enc_type, char * enc_token); + +LIBETPAN_EXPORT +void mailmime_mechanism_free(struct mailmime_mechanism * mechanism); + +LIBETPAN_EXPORT +struct mailmime_parameter * +mailmime_parameter_new(char * pa_name, char * pa_value); + +LIBETPAN_EXPORT +void mailmime_parameter_free(struct mailmime_parameter * parameter); + +LIBETPAN_EXPORT +void mailmime_subtype_free(char * subtype); + +LIBETPAN_EXPORT +void mailmime_token_free(char * token); + +LIBETPAN_EXPORT +struct mailmime_type * +mailmime_type_new(int tp_type, + struct mailmime_discrete_type * tp_discrete_type, + struct mailmime_composite_type * tp_composite_type); + +LIBETPAN_EXPORT +void mailmime_type_free(struct mailmime_type * type); + +LIBETPAN_EXPORT +void mailmime_value_free(char * value); + + + +struct mailmime_language { + clist * lg_list; /* atom (char *) */ +}; + +LIBETPAN_EXPORT +struct mailmime_language * mailmime_language_new(clist * lg_list); + +LIBETPAN_EXPORT +void mailmime_language_free(struct mailmime_language * lang); + + +/* +void mailmime_x_token_free(gchar * x_token); +*/ + +LIBETPAN_EXPORT +struct mailmime_field * +mailmime_field_new(int fld_type, + struct mailmime_content * fld_content, + struct mailmime_mechanism * fld_encoding, + char * fld_id, + char * fld_description, + uint32_t fld_version, + struct mailmime_disposition * fld_disposition, + struct mailmime_language * fld_language, + char * fld_location); + +LIBETPAN_EXPORT +void mailmime_field_free(struct mailmime_field * field); + +LIBETPAN_EXPORT +struct mailmime_fields * mailmime_fields_new(clist * fld_list); + +LIBETPAN_EXPORT +void mailmime_fields_free(struct mailmime_fields * fields); + + +struct mailmime_multipart_body { + clist * bd_list; +}; + +LIBETPAN_EXPORT +struct mailmime_multipart_body * +mailmime_multipart_body_new(clist * bd_list); + +LIBETPAN_EXPORT +void mailmime_multipart_body_free(struct mailmime_multipart_body * mp_body); + + +enum { + MAILMIME_DATA_TEXT, + MAILMIME_DATA_FILE +}; + +struct mailmime_data { + int dt_type; + int dt_encoding; + int dt_encoded; + union { + struct { + const char * dt_data; + size_t dt_length; + } dt_text; + char * dt_filename; + } dt_data; +}; + +LIBETPAN_EXPORT +struct mailmime_data * mailmime_data_new(int dt_type, int dt_encoding, + int dt_encoded, const char * dt_data, size_t dt_length, + char * dt_filename); + +LIBETPAN_EXPORT +void mailmime_data_free(struct mailmime_data * mime_data); + + +enum { + MAILMIME_NONE, + MAILMIME_SINGLE, + MAILMIME_MULTIPLE, + MAILMIME_MESSAGE +}; + +struct mailmime { + /* parent information */ + int mm_parent_type; + struct mailmime * mm_parent; + clistiter * mm_multipart_pos; + + int mm_type; + const char * mm_mime_start; + size_t mm_length; + + struct mailmime_fields * mm_mime_fields; + struct mailmime_content * mm_content_type; + + struct mailmime_data * mm_body; + union { + /* single part */ + struct mailmime_data * mm_single; /* XXX - was body */ + + /* multi-part */ + struct { + struct mailmime_data * mm_preamble; + struct mailmime_data * mm_epilogue; + clist * mm_mp_list; + } mm_multipart; + + /* message */ + struct { + struct mailimf_fields * mm_fields; + struct mailmime * mm_msg_mime; + } mm_message; + + } mm_data; +}; + +LIBETPAN_EXPORT +struct mailmime * mailmime_new(int mm_type, + const char * mm_mime_start, size_t mm_length, + struct mailmime_fields * mm_mime_fields, + struct mailmime_content * mm_content_type, + struct mailmime_data * mm_body, + struct mailmime_data * mm_preamble, + struct mailmime_data * mm_epilogue, + clist * mm_mp_list, + struct mailimf_fields * mm_fields, + struct mailmime * mm_msg_mime); + +LIBETPAN_EXPORT +void mailmime_free(struct mailmime * mime); + +struct mailmime_encoded_word { + char * wd_charset; + char * wd_text; +}; + +LIBETPAN_EXPORT +struct mailmime_encoded_word * +mailmime_encoded_word_new(char * wd_charset, char * wd_text); + +LIBETPAN_EXPORT +void mailmime_encoded_word_free(struct mailmime_encoded_word * ew); + +LIBETPAN_EXPORT +void mailmime_charset_free(char * charset); + +LIBETPAN_EXPORT +void mailmime_encoded_text_free(char * text); + + +struct mailmime_disposition { + struct mailmime_disposition_type * dsp_type; + clist * dsp_parms; /* struct mailmime_disposition_parm */ +}; + + +enum { + MAILMIME_DISPOSITION_TYPE_ERROR, + MAILMIME_DISPOSITION_TYPE_INLINE, + MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + MAILMIME_DISPOSITION_TYPE_EXTENSION +}; + +struct mailmime_disposition_type { + int dsp_type; + char * dsp_extension; +}; + + +enum { + MAILMIME_DISPOSITION_PARM_FILENAME, + MAILMIME_DISPOSITION_PARM_CREATION_DATE, + MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE, + MAILMIME_DISPOSITION_PARM_READ_DATE, + MAILMIME_DISPOSITION_PARM_SIZE, + MAILMIME_DISPOSITION_PARM_PARAMETER +}; + +struct mailmime_disposition_parm { + int pa_type; + union { + char * pa_filename; + char * pa_creation_date; + char * pa_modification_date; + char * pa_read_date; + size_t pa_size; + struct mailmime_parameter * pa_parameter; + } pa_data; +}; + +LIBETPAN_EXPORT +struct mailmime_disposition * +mailmime_disposition_new(struct mailmime_disposition_type * dsp_type, + clist * dsp_parms); + +LIBETPAN_EXPORT +void mailmime_disposition_free(struct mailmime_disposition * dsp); + +LIBETPAN_EXPORT +struct mailmime_disposition_type * +mailmime_disposition_type_new(int dt_type, char * dt_extension); + +LIBETPAN_EXPORT +void mailmime_disposition_type_free(struct mailmime_disposition_type * dsp_type); + +LIBETPAN_EXPORT +struct mailmime_disposition_parm * +mailmime_disposition_parm_new(int pa_type, + char * pa_filename, + char * pa_creation_date, + char * pa_modification_date, + char * pa_read_date, + size_t pa_size, + struct mailmime_parameter * pa_parameter); + +LIBETPAN_EXPORT +void mailmime_disposition_parm_free(struct mailmime_disposition_parm * + dsp_parm); + +LIBETPAN_EXPORT +void mailmime_filename_parm_free(char * filename); + +LIBETPAN_EXPORT +void mailmime_creation_date_parm_free(char * date); + +LIBETPAN_EXPORT +void mailmime_modification_date_parm_free(char * date); + +LIBETPAN_EXPORT +void mailmime_read_date_parm_free(char * date); + +LIBETPAN_EXPORT +void mailmime_quoted_date_time_free(char * date); + +struct mailmime_section { + clist * sec_list; /* list of (uint32 *) */ +}; + +LIBETPAN_EXPORT +struct mailmime_section * mailmime_section_new(clist * list); + +LIBETPAN_EXPORT +void mailmime_section_free(struct mailmime_section * section); + + +LIBETPAN_EXPORT +void mailmime_decoded_part_free(char * part); + +struct mailmime_single_fields { + struct mailmime_content * fld_content; + char * fld_content_charset; + char * fld_content_boundary; + char * fld_content_name; + struct mailmime_mechanism * fld_encoding; + char * fld_id; + char * fld_description; + uint32_t fld_version; + struct mailmime_disposition * fld_disposition; + char * fld_disposition_filename; + char * fld_disposition_creation_date; + char * fld_disposition_modification_date; + char * fld_disposition_read_date; + size_t fld_disposition_size; + struct mailmime_language * fld_language; + char * fld_location; +}; + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Sources/libetpan/include/mailmime_types_helper.h b/Sources/libetpan/include/mailmime_types_helper.h new file mode 100644 index 00000000..742d0cb0 --- /dev/null +++ b/Sources/libetpan/include/mailmime_types_helper.h @@ -0,0 +1,204 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_types_helper.h,v 1.17 2008/01/14 17:13:53 hoa Exp $ + */ + +#ifndef MAILMIME_TYPES_HELPER_H + +#define MAILMIME_TYPES_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailmime_types.h" + +LIBETPAN_EXPORT +int mailmime_transfer_encoding_get(struct mailmime_fields * fields); + +LIBETPAN_EXPORT +struct mailmime_disposition * +mailmime_disposition_new_filename(int type, char * filename); + +LIBETPAN_EXPORT +struct mailmime_fields * mailmime_fields_new_empty(void); + +LIBETPAN_EXPORT +int mailmime_fields_add(struct mailmime_fields * fields, + struct mailmime_field * field); + +LIBETPAN_EXPORT +struct mailmime_fields * +mailmime_fields_new_with_data(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language); + +LIBETPAN_EXPORT +struct mailmime_fields * +mailmime_fields_new_with_version(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language); + +LIBETPAN_EXPORT +struct mailmime_content * mailmime_get_content_message(void); +LIBETPAN_EXPORT +struct mailmime_content * mailmime_get_content_text(void); +/* struct mailmime_content * mailmime_get_content(char * mime_type); */ + +#define mailmime_get_content mailmime_content_new_with_str + +LIBETPAN_EXPORT +struct mailmime_data * +mailmime_data_new_data(int encoding, int encoded, + const char * data, size_t length); + +LIBETPAN_EXPORT +struct mailmime_data * +mailmime_data_new_file(int encoding, int encoded, + char * filename); + +#if 0 +struct mailmime * +mailmime_new_message_file(char * filename); + +struct mailmime * +mailmime_new_message_text(char * data_str, size_t length); +#endif + +LIBETPAN_EXPORT +struct mailmime * +mailmime_new_message_data(struct mailmime * msg_mime); + +LIBETPAN_EXPORT +struct mailmime * +mailmime_new_empty(struct mailmime_content * content, + struct mailmime_fields * mime_fields); + +LIBETPAN_EXPORT +int +mailmime_new_with_content(const char * content_type, + struct mailmime_fields * mime_fields, + struct mailmime ** result); + +LIBETPAN_EXPORT +int mailmime_set_preamble_file(struct mailmime * build_info, + char * filename); + +LIBETPAN_EXPORT +int mailmime_set_epilogue_file(struct mailmime * build_info, + char * filename); + +LIBETPAN_EXPORT +int mailmime_set_preamble_text(struct mailmime * build_info, + char * data_str, size_t length); + +LIBETPAN_EXPORT +int mailmime_set_epilogue_text(struct mailmime * build_info, + char * data_str, size_t length); + +LIBETPAN_EXPORT +int mailmime_set_body_file(struct mailmime * build_info, + char * filename); + +LIBETPAN_EXPORT +int mailmime_set_body_text(struct mailmime * build_info, + char * data_str, size_t length); + +LIBETPAN_EXPORT +int mailmime_add_part(struct mailmime * build_info, + struct mailmime * part); + +LIBETPAN_EXPORT +void mailmime_remove_part(struct mailmime * mime); + +LIBETPAN_EXPORT +void mailmime_set_imf_fields(struct mailmime * build_info, + struct mailimf_fields * fields); + + +LIBETPAN_EXPORT +struct mailmime_disposition * +mailmime_disposition_new_with_data(int type, + char * filename, char * creation_date, char * modification_date, + char * read_date, size_t size); + +LIBETPAN_EXPORT +void mailmime_single_fields_init(struct mailmime_single_fields * single_fields, + struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content); + +LIBETPAN_EXPORT +struct mailmime_single_fields * +mailmime_single_fields_new(struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content); + +LIBETPAN_EXPORT +void mailmime_single_fields_free(struct mailmime_single_fields * + single_fields); + +LIBETPAN_EXPORT +int mailmime_smart_add_part(struct mailmime * mime, + struct mailmime * mime_sub); + +LIBETPAN_EXPORT +int mailmime_smart_remove_part(struct mailmime * mime); + +LIBETPAN_EXPORT +struct mailmime_content * mailmime_content_new_with_str(const char * str); + +LIBETPAN_EXPORT +struct mailmime_fields * mailmime_fields_new_encoding(int type); + +LIBETPAN_EXPORT +struct mailmime * mailmime_multiple_new(const char * type); + +LIBETPAN_EXPORT +struct mailmime_fields * mailmime_fields_new_filename(int dsp_type, + char * filename, int encoding_type); + +LIBETPAN_EXPORT +struct mailmime_parameter * +mailmime_param_new_with_data(char * name, char * value); + +LIBETPAN_EXPORT +char * mailmime_generate_boundary(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailmime_write.h b/Sources/libetpan/include/mailmime_write.h new file mode 100644 index 00000000..72197b57 --- /dev/null +++ b/Sources/libetpan/include/mailmime_write.h @@ -0,0 +1,73 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_write.h,v 1.13 2004/11/21 21:53:39 hoa Exp $ + */ + +#ifndef MAILMIME_WRITE_H + +#define MAILMIME_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailmime_types.h" +#include + +int mailmime_fields_write(FILE * f, int * col, + struct mailmime_fields * fields); + +int mailmime_content_write(FILE * f, int * col, + struct mailmime_content * content); + +int mailmime_content_type_write(FILE * f, int * col, + struct mailmime_content * content); + +int mailmime_write(FILE * f, int * col, + struct mailmime * build_info); + +int mailmime_quoted_printable_write(FILE * f, int * col, int istext, + const char * text, size_t size); + +int mailmime_base64_write(FILE * f, int * col, + const char * text, size_t size); + +int mailmime_data_write(FILE * f, int * col, + struct mailmime_data * data, + int istext); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailmime_write_file.h b/Sources/libetpan/include/mailmime_write_file.h new file mode 100644 index 00000000..2a1afc40 --- /dev/null +++ b/Sources/libetpan/include/mailmime_write_file.h @@ -0,0 +1,118 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_write_file.h,v 1.3 2005/06/01 12:22:19 smarinier Exp $ + */ + +#ifndef MAILMIME_WRITE_FILE_H + +#define MAILMIME_WRITE_FILE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailmime_types.h" +#include "stdio.h" + +#define MAILMIME_WRITE_COMPATIBILITY + +LIBETPAN_EXPORT +int mailmime_fields_write_file(FILE * f, int * col, + struct mailmime_fields * fields); + +LIBETPAN_EXPORT +int mailmime_content_write_file(FILE * f, int * col, + struct mailmime_content * content); + +LIBETPAN_EXPORT +int mailmime_content_type_write_file(FILE * f, int * col, + struct mailmime_content * content); + +LIBETPAN_EXPORT +int mailmime_write_file(FILE * f, int * col, + struct mailmime * build_info); + +LIBETPAN_EXPORT +int mailmime_quoted_printable_write_file(FILE * f, int * col, int istext, + const char * text, size_t size); + +LIBETPAN_EXPORT +int mailmime_base64_write_file(FILE * f, int * col, + const char * text, size_t size); + +LIBETPAN_EXPORT +int mailmime_data_write_file(FILE * f, int * col, + struct mailmime_data * data, + int istext); + + +/* binary compatibility with 0.34 - begin */ + +#ifdef MAILMIME_WRITE_COMPATIBILITY +LIBETPAN_EXPORT +int mailmime_fields_write(FILE * f, int * col, + struct mailmime_fields * fields); + +LIBETPAN_EXPORT +int mailmime_content_write(FILE * f, int * col, + struct mailmime_content * content); + +LIBETPAN_EXPORT +int mailmime_content_type_write(FILE * f, int * col, + struct mailmime_content * content); + +LIBETPAN_EXPORT +int mailmime_write(FILE * f, int * col, + struct mailmime * build_info); + +LIBETPAN_EXPORT +int mailmime_quoted_printable_write(FILE * f, int * col, int istext, + const char * text, size_t size); + +LIBETPAN_EXPORT +int mailmime_base64_write(FILE * f, int * col, + const char * text, size_t size); + +LIBETPAN_EXPORT +int mailmime_data_write(FILE * f, int * col, + struct mailmime_data * data, + int istext); +#endif + +/* binary compatibility with 0.34 - end */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailmime_write_generic.h b/Sources/libetpan/include/mailmime_write_generic.h new file mode 100644 index 00000000..b625552d --- /dev/null +++ b/Sources/libetpan/include/mailmime_write_generic.h @@ -0,0 +1,73 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_write_generic.h,v 1.2 2004/11/21 21:53:39 hoa Exp $ + */ + +#ifndef MAILMIME_WRITE_GENERIC_H + +#define MAILMIME_WRITE_GENERIC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailmime_types.h" +#include "stdio.h" + +int mailmime_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_fields * fields); + +int mailmime_content_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_content * content); + +int mailmime_content_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_content * content); + +int mailmime_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime * build_info); + +int mailmime_quoted_printable_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, int istext, + const char * text, size_t size); + +int mailmime_base64_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + const char * text, size_t size); + +int mailmime_data_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_data * mime_data, + int istext); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailmime_write_mem.h b/Sources/libetpan/include/mailmime_write_mem.h new file mode 100644 index 00000000..56400595 --- /dev/null +++ b/Sources/libetpan/include/mailmime_write_mem.h @@ -0,0 +1,80 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_write_mem.h,v 1.3 2006/06/07 12:52:45 smarinier Exp $ + */ + +#ifndef MAILMIME_WRITE_MEM_H + +#define MAILMIME_WRITE_MEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailmime_types.h" +#include "mmapstring.h" + +LIBETPAN_EXPORT +int mailmime_fields_write_mem(MMAPString * f, int * col, + struct mailmime_fields * fields); + +LIBETPAN_EXPORT +int mailmime_content_write_mem(MMAPString * f, int * col, + struct mailmime_content * content); + +LIBETPAN_EXPORT +int mailmime_content_type_write_mem(MMAPString * f, int * col, + struct mailmime_content * content); + +LIBETPAN_EXPORT +int mailmime_write_mem(MMAPString * f, int * col, + struct mailmime * build_info); + +LIBETPAN_EXPORT +int mailmime_quoted_printable_write_mem(MMAPString * f, int * col, int istext, + const char * text, size_t size); + +LIBETPAN_EXPORT +int mailmime_base64_write_mem(MMAPString * f, int * col, + const char * text, size_t size); + +LIBETPAN_EXPORT +int mailmime_data_write_mem(MMAPString * f, int * col, + struct mailmime_data * data, + int istext); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailpop3.h b/Sources/libetpan/include/mailpop3.h new file mode 100644 index 00000000..155ee42e --- /dev/null +++ b/Sources/libetpan/include/mailpop3.h @@ -0,0 +1,146 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailpop3.h,v 1.19 2010/04/05 12:56:44 hoa Exp $ + */ + +#ifndef MAILPOP3_H + +#define MAILPOP3_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailpop3_types.h" + +#include "mailpop3_helper.h" + +#include "mailpop3_socket.h" +#include "mailpop3_ssl.h" + +#define POP3_STRING_SIZE 513 + +LIBETPAN_EXPORT +mailpop3 * mailpop3_new(size_t pop3_progr_rate, + progress_function * pop3_progr_fun); + +LIBETPAN_EXPORT +void mailpop3_free(mailpop3 * f); + +LIBETPAN_EXPORT +void mailpop3_set_timeout(mailpop3 * f, time_t timeout); + +LIBETPAN_EXPORT +time_t mailpop3_get_timeout(mailpop3 * f); + +LIBETPAN_EXPORT +void mailpop3_set_progress_callback(mailpop3 * f, mailprogress_function * progr_fun, void * context); + +LIBETPAN_EXPORT +int mailpop3_connect(mailpop3 * f, mailstream * s); + +LIBETPAN_EXPORT +int mailpop3_quit(mailpop3 * f); + +LIBETPAN_EXPORT +int mailpop3_apop(mailpop3 * f, const char * user, const char * password); + +LIBETPAN_EXPORT +int mailpop3_user(mailpop3 * f, const char * user); + +LIBETPAN_EXPORT +int mailpop3_pass(mailpop3 * f, const char * password); + +LIBETPAN_EXPORT +int mailpop3_list(mailpop3 * f, carray ** result); + +LIBETPAN_EXPORT +int mailpop3_retr(mailpop3 * f, unsigned int indx, char ** result, + size_t * result_len); + +LIBETPAN_EXPORT +int mailpop3_top(mailpop3 * f, unsigned int indx, + unsigned int count, char ** result, + size_t * result_len); + +LIBETPAN_EXPORT +int mailpop3_dele(mailpop3 * f, unsigned int indx); + +LIBETPAN_EXPORT +int mailpop3_noop(mailpop3 * f); + +LIBETPAN_EXPORT +int mailpop3_rset(mailpop3 * f); + +LIBETPAN_EXPORT +void mailpop3_top_free(char * str); + +LIBETPAN_EXPORT +void mailpop3_retr_free(char * str); + +LIBETPAN_EXPORT +int mailpop3_get_msg_info(mailpop3 * f, unsigned int indx, + struct mailpop3_msg_info ** result); + +LIBETPAN_EXPORT +int mailpop3_capa(mailpop3 * f, clist ** result); + +LIBETPAN_EXPORT +void mailpop3_capa_resp_free(clist * capa_list); + +LIBETPAN_EXPORT +int mailpop3_stat(mailpop3 * f, struct mailpop3_stat_response ** result); + +LIBETPAN_EXPORT +void mailpop3_stat_resp_free(struct mailpop3_stat_response * stat_result); + +LIBETPAN_EXPORT +int mailpop3_stls(mailpop3 * f); + +LIBETPAN_EXPORT +int mailpop3_auth(mailpop3 * f, const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); + +LIBETPAN_EXPORT +void mailpop3_set_logger(mailpop3 * session, void (* logger)(mailpop3 * session, int log_type, + const char * str, size_t size, void * context), void * logger_context); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailpop3_helper.h b/Sources/libetpan/include/mailpop3_helper.h new file mode 100644 index 00000000..d278bc1a --- /dev/null +++ b/Sources/libetpan/include/mailpop3_helper.h @@ -0,0 +1,64 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailpop3_helper.h,v 1.9 2008/02/20 22:15:53 hoa Exp $ + */ + +#ifndef MAILPOP3_HELPER_H + +#define MAILPOP3_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailpop3.h" + +int mailpop3_login_apop(mailpop3 * f, + const char * user, + const char * password); + +int mailpop3_login(mailpop3 * f, + const char * user, + const char * password); + +int mailpop3_header(mailpop3 * f, uint32_t indx, char ** result, + size_t * result_len); + +void mailpop3_header_free(char * str); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Sources/libetpan/include/mailpop3_socket.h b/Sources/libetpan/include/mailpop3_socket.h new file mode 100644 index 00000000..62b75406 --- /dev/null +++ b/Sources/libetpan/include/mailpop3_socket.h @@ -0,0 +1,64 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailpop3_socket.h,v 1.16 2006/12/26 13:13:24 hoa Exp $ + */ + +#ifndef MAILPOP3_SOCKET_H + +#define MAILPOP3_SOCKET_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_INTTYPES_H +# include +#endif + +#include "mailpop3_types.h" + +LIBETPAN_EXPORT +int mailpop3_socket_connect(mailpop3 * f, const char * server, uint16_t port); + +LIBETPAN_EXPORT +int mailpop3_socket_starttls(mailpop3 * f); + +LIBETPAN_EXPORT +int mailpop3_socket_starttls_with_callback(mailpop3 * f, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailpop3_ssl.h b/Sources/libetpan/include/mailpop3_ssl.h new file mode 100644 index 00000000..d73cae3c --- /dev/null +++ b/Sources/libetpan/include/mailpop3_ssl.h @@ -0,0 +1,61 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailpop3_ssl.h,v 1.17 2006/12/26 13:13:24 hoa Exp $ + */ + +#ifndef MAILPOP3_SSL_H + +#define MAILPOP3_SSL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_INTTYPES_H +# include +#endif + +#include "mailpop3_types.h" + +LIBETPAN_EXPORT +int mailpop3_ssl_connect(mailpop3 * f, const char * server, uint16_t port); + +LIBETPAN_EXPORT +int mailpop3_ssl_connect_with_callback(mailpop3 * f, const char * server, uint16_t port, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailpop3_types.h b/Sources/libetpan/include/mailpop3_types.h new file mode 100644 index 00000000..fedabe70 --- /dev/null +++ b/Sources/libetpan/include/mailpop3_types.h @@ -0,0 +1,131 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailpop3_types.h,v 1.19 2006/12/13 18:31:33 hoa Exp $ + */ + +#ifndef MAILPOP3_TYPES_H + +#define MAILPOP3_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "libetpan-config.h" +#include "mailstream.h" +#include "mmapstring.h" +#include "carray.h" +#include "clist.h" + +enum { + MAILPOP3_NO_ERROR = 0, + MAILPOP3_ERROR_BAD_STATE, + MAILPOP3_ERROR_UNAUTHORIZED, + MAILPOP3_ERROR_STREAM, + MAILPOP3_ERROR_DENIED, + MAILPOP3_ERROR_BAD_USER, + MAILPOP3_ERROR_BAD_PASSWORD, + MAILPOP3_ERROR_CANT_LIST, + MAILPOP3_ERROR_NO_SUCH_MESSAGE, + MAILPOP3_ERROR_MEMORY, + MAILPOP3_ERROR_CONNECTION_REFUSED, + MAILPOP3_ERROR_APOP_NOT_SUPPORTED, + MAILPOP3_ERROR_CAPA_NOT_SUPPORTED, + MAILPOP3_ERROR_STLS_NOT_SUPPORTED, + MAILPOP3_ERROR_SSL, + MAILPOP3_ERROR_QUIT_FAILED +}; + +typedef struct mailpop3 mailpop3; + +struct mailpop3 +{ + char * pop3_response; /* response message */ + char * pop3_timestamp; /* connection timestamp */ + + /* internals */ + mailstream * pop3_stream; + size_t pop3_progr_rate; + progress_function * pop3_progr_fun; + + MMAPString * pop3_stream_buffer; /* buffer for lines reading */ + MMAPString * pop3_response_buffer; /* buffer for responses */ + + carray * pop3_msg_tab; /* list of pop3_msg_info structures */ + int pop3_state; /* state */ + + unsigned int pop3_deleted_count; + + struct { + void * sasl_conn; + const char * sasl_server_fqdn; + const char * sasl_login; + const char * sasl_auth_name; + const char * sasl_password; + const char * sasl_realm; + void * sasl_secret; + } pop3_sasl; + + time_t pop3_timeout; + mailprogress_function * pop3_progress_fun; + void * pop3_progress_context; + + void (* pop3_logger)(mailpop3 * session, int log_type, const char * str, size_t size, void * context); + void * pop3_logger_context; +}; + +struct mailpop3_msg_info +{ + unsigned int msg_index; + uint32_t msg_size; + char * msg_uidl; + int msg_deleted; +}; + + +struct mailpop3_capa { + char * cap_name; + clist * cap_param; /* (char *) */ +}; + + +struct mailpop3_stat_response { + unsigned int msgs_count; + size_t msgs_size; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailprivacy.h b/Sources/libetpan/include/mailprivacy.h new file mode 100644 index 00000000..3cff6580 --- /dev/null +++ b/Sources/libetpan/include/mailprivacy.h @@ -0,0 +1,145 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailprivacy.h,v 1.6 2007/12/10 21:32:59 hoa Exp $ + */ + +#ifndef MAILPRIVACY_H + +#define MAILPRIVACY_H + +#include "mailmessage.h" +#include "mailprivacy_types.h" +#include "mailprivacy_tools.h" + +LIBETPAN_EXPORT +struct mailprivacy * mailprivacy_new(char * tmp_dir, int make_alternative); + +LIBETPAN_EXPORT +void mailprivacy_free(struct mailprivacy * privacy); + +LIBETPAN_EXPORT +int mailprivacy_msg_get_bodystructure(struct mailprivacy * privacy, + mailmessage * msg_info, + struct mailmime ** result); + +LIBETPAN_EXPORT +void mailprivacy_msg_flush(struct mailprivacy * privacy, + mailmessage * msg_info); + +LIBETPAN_EXPORT +int mailprivacy_msg_fetch_section(struct mailprivacy * privacy, + mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + +LIBETPAN_EXPORT +int mailprivacy_msg_fetch_section_header(struct mailprivacy * privacy, + mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +LIBETPAN_EXPORT +int mailprivacy_msg_fetch_section_mime(struct mailprivacy * privacy, + mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +LIBETPAN_EXPORT +int mailprivacy_msg_fetch_section_body(struct mailprivacy * privacy, + mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +LIBETPAN_EXPORT +void mailprivacy_msg_fetch_result_free(struct mailprivacy * privacy, + mailmessage * msg_info, + char * msg); + +LIBETPAN_EXPORT +int mailprivacy_msg_fetch(struct mailprivacy * privacy, + mailmessage * msg_info, + char ** result, + size_t * result_len); + +LIBETPAN_EXPORT +int mailprivacy_msg_fetch_header(struct mailprivacy * privacy, + mailmessage * msg_info, + char ** result, + size_t * result_len); + +LIBETPAN_EXPORT +int mailprivacy_register(struct mailprivacy * privacy, + struct mailprivacy_protocol * protocol); + +LIBETPAN_EXPORT +void mailprivacy_unregister(struct mailprivacy * privacy, + struct mailprivacy_protocol * protocol); + +LIBETPAN_EXPORT +char * mailprivacy_get_encryption_name(struct mailprivacy * privacy, + char * privacy_driver, char * privacy_encryption); + +/* deprecated */ +LIBETPAN_EXPORT +int mailprivacy_encrypt(struct mailprivacy * privacy, + char * privacy_driver, char * privacy_encryption, + struct mailmime * mime, + struct mailmime ** result); + +/* introduced the use of passphrase */ +LIBETPAN_EXPORT +int mailprivacy_encrypt_msg(struct mailprivacy * privacy, + char * privacy_driver, char * privacy_encryption, + mailmessage * msg, + struct mailmime * mime, + struct mailmime ** result); + +LIBETPAN_EXPORT +void mailprivacy_debug(struct mailprivacy * privacy, FILE * f); + +LIBETPAN_EXPORT +carray * mailprivacy_get_protocols(struct mailprivacy * privacy); + +LIBETPAN_EXPORT +int mailprivacy_is_encrypted(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime); + +LIBETPAN_EXPORT +void mailprivacy_recursive_unregister_mime(struct mailprivacy * privacy, + struct mailmime * mime); + +#endif diff --git a/Sources/libetpan/include/mailprivacy_gnupg.h b/Sources/libetpan/include/mailprivacy_gnupg.h new file mode 100644 index 00000000..9309c936 --- /dev/null +++ b/Sources/libetpan/include/mailprivacy_gnupg.h @@ -0,0 +1,60 @@ +/* + * etPan! -- a mail user agent + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailprivacy_gnupg.h,v 1.5 2007/10/30 00:40:39 hoa Exp $ + */ + +#ifndef MAIL_PRIVACY_GNUPG_H + +#define MAIL_PRIVACY_GNUPG_H + +#include "mailprivacy_types.h" + +LIBETPAN_EXPORT +int mailprivacy_gnupg_init(struct mailprivacy * privacy); + +LIBETPAN_EXPORT +void mailprivacy_gnupg_done(struct mailprivacy * privacy); + +LIBETPAN_EXPORT +clist * mailprivacy_gnupg_encryption_id_list(struct mailprivacy * privacy, + mailmessage * msg); + +LIBETPAN_EXPORT +void mailprivacy_gnupg_encryption_id_list_clear(struct mailprivacy * privacy, + mailmessage * msg); + +LIBETPAN_EXPORT +int mailprivacy_gnupg_set_encryption_id(struct mailprivacy * privacy, + char * user_id, char * passphrase); + +#endif diff --git a/Sources/libetpan/include/mailprivacy_smime.h b/Sources/libetpan/include/mailprivacy_smime.h new file mode 100644 index 00000000..b42d04d9 --- /dev/null +++ b/Sources/libetpan/include/mailprivacy_smime.h @@ -0,0 +1,104 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailprivacy_smime.h,v 1.5 2007/10/30 00:40:39 hoa Exp $ + */ + +#ifndef MAILPRIVACY_SMIME_H + +#define MAILPRIVACY_SMIME_H + +#include "mailprivacy_types.h" + +LIBETPAN_EXPORT +int mailprivacy_smime_init(struct mailprivacy * privacy); + +LIBETPAN_EXPORT +void mailprivacy_smime_done(struct mailprivacy * privacy); + +LIBETPAN_EXPORT +void mailprivacy_smime_set_cert_dir(struct mailprivacy * privacy, + char * directory); + + +/* + set directory where certificates of authority certifications are + stored. +*/ + +LIBETPAN_EXPORT +void mailprivacy_smime_set_CA_dir(struct mailprivacy * privacy, + char * directory); + + +/* + to disable the verification of signers certificates of a + signed message. +*/ + +LIBETPAN_EXPORT +void mailprivacy_smime_set_CA_check(struct mailprivacy * privacy, + int enabled); + + +/* + to store certificates of signed messages +*/ + +LIBETPAN_EXPORT +void mailprivacy_smime_set_store_cert(struct mailprivacy * privacy, + int enabled); + +/* + set directory where private keys are stored. + name of the files in that directory must be in form : + [email-address]-private-key.pem +*/ + +LIBETPAN_EXPORT +void mailprivacy_smime_set_private_keys_dir(struct mailprivacy * privacy, + char * directory); + + +LIBETPAN_EXPORT +clist * mailprivacy_smime_encryption_id_list(struct mailprivacy * privacy, + mailmessage * msg); + +LIBETPAN_EXPORT +void mailprivacy_smime_encryption_id_list_clear(struct mailprivacy * privacy, + mailmessage * msg); + +LIBETPAN_EXPORT +int mailprivacy_smime_set_encryption_id(struct mailprivacy * privacy, + char * user_id, char * passphrase); + +#endif diff --git a/Sources/libetpan/include/mailprivacy_tools.h b/Sources/libetpan/include/mailprivacy_tools.h new file mode 100644 index 00000000..d2a3ded2 --- /dev/null +++ b/Sources/libetpan/include/mailprivacy_tools.h @@ -0,0 +1,120 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailprivacy_tools.h,v 1.7 2007/12/10 21:32:59 hoa Exp $ + */ + +#ifndef MAIL_PRIVACY_TOOLS_H + +#define MAIL_PRIVACY_TOOLS_H + +#include "mailmessage.h" +#include "mailprivacy_types.h" + +LIBETPAN_EXPORT +void mailprivacy_mime_clear(struct mailmime * mime); + +LIBETPAN_EXPORT +FILE * mailprivacy_get_tmp_file(struct mailprivacy * privacy, + char * filename, size_t size); + +LIBETPAN_EXPORT +int mailprivacy_get_tmp_filename(struct mailprivacy * privacy, + char * filename, size_t size); + +LIBETPAN_EXPORT +struct mailmime * +mailprivacy_new_file_part(struct mailprivacy * privacy, + char * filename, + char * default_content_type, int default_encoding); + +LIBETPAN_EXPORT +int mailmime_substitute(struct mailmime * old_mime, + struct mailmime * new_mime); + +LIBETPAN_EXPORT +int mailprivacy_fetch_mime_body_to_file(struct mailprivacy * privacy, + char * filename, size_t size, + mailmessage * msg, struct mailmime * mime); + +LIBETPAN_EXPORT +int mailprivacy_get_part_from_file(struct mailprivacy * privacy, + int check_privacy, int reencode, + char * filename, + struct mailmime ** result_mime); + +LIBETPAN_EXPORT +int mail_quote_filename(char * result, size_t size, char * path); + +LIBETPAN_EXPORT +void mailprivacy_prepare_mime(struct mailmime * mime); + +LIBETPAN_EXPORT +char * mailprivacy_dup_imf_file(struct mailprivacy * privacy, + char * source_filename); + +LIBETPAN_EXPORT +struct mailmime_fields * +mailprivacy_mime_fields_dup(struct mailprivacy * privacy, + struct mailmime_fields * mime_fields); + +LIBETPAN_EXPORT +struct mailmime_parameter * +mailmime_parameter_dup(struct mailmime_parameter * param); + +LIBETPAN_EXPORT +struct mailmime_composite_type * +mailmime_composite_type_dup(struct mailmime_composite_type * composite_type); + +LIBETPAN_EXPORT +struct mailmime_discrete_type * +mailmime_discrete_type_dup(struct mailmime_discrete_type * discrete_type); + +LIBETPAN_EXPORT +struct mailmime_type * mailmime_type_dup(struct mailmime_type * type); + +LIBETPAN_EXPORT +struct mailmime_content * +mailmime_content_dup(struct mailmime_content * content); + +LIBETPAN_EXPORT +int mailprivacy_fetch_decoded_to_file(struct mailprivacy * privacy, + char * filename, size_t size, + mailmessage * msg, struct mailmime * mime); + +LIBETPAN_EXPORT +int mailprivacy_get_mime(struct mailprivacy * privacy, + int check_privacy, int reencode, + char * content, size_t content_len, + struct mailmime ** result_mime); + +#endif diff --git a/Sources/libetpan/include/mailprivacy_tools_private.h b/Sources/libetpan/include/mailprivacy_tools_private.h new file mode 100644 index 00000000..43573815 --- /dev/null +++ b/Sources/libetpan/include/mailprivacy_tools_private.h @@ -0,0 +1,48 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILPRIVACY_TOOLS_PRIVATE_H + +#define MAILPRIVACY_TOOLS_PRIVATE_H + +#include "mailmessage.h" +#include "mailprivacy_types.h" + +enum { + NO_ERROR_PASSPHRASE = 0, + ERROR_PASSPHRASE_COMMAND, + ERROR_PASSPHRASE_FILE +}; + +int mailprivacy_spawn_and_wait(char * command, char * passphrase, + char * stdoutfile, char * stderrfile, + int * bad_passphrase); + +#endif diff --git a/Sources/libetpan/include/mailprivacy_types.h b/Sources/libetpan/include/mailprivacy_types.h new file mode 100644 index 00000000..b8a448cd --- /dev/null +++ b/Sources/libetpan/include/mailprivacy_types.h @@ -0,0 +1,83 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailprivacy_types.h,v 1.4 2005/11/21 16:17:57 hoa Exp $ + */ + +#ifndef MAIL_PRIVACY_TYPES_H + +#define MAIL_PRIVACY_TYPES_H + +#include "chash.h" +#include "carray.h" +#include "mailmessage.h" +#include "mailmime.h" + +struct mailprivacy { + char * tmp_dir; /* working tmp directory */ + chash * msg_ref; /* mailmessage => present or not */ + chash * mmapstr; /* mmapstring => present or not present */ + chash * mime_ref; /* mime => present or not */ + carray * protocols; + int make_alternative; + /* if make_alternative is 0, replaces the part with decrypted + part, if 1, adds a multipart/alternative and put the decrypted + and encrypted part as subparts. + */ +}; + +struct mailprivacy_encryption { + char * name; + char * description; + + int (* encrypt)(struct mailprivacy *, + mailmessage *, + struct mailmime *, struct mailmime **); +}; + +struct mailprivacy_protocol { + char * name; + char * description; + + /* introduced to easy the port to sylpheed */ + int (* is_encrypted)(struct mailprivacy *, + mailmessage *, struct mailmime *); + + int (* decrypt)(struct mailprivacy *, + mailmessage *, struct mailmime *, + struct mailmime **); + + int encryption_count; + struct mailprivacy_encryption * encryption_tab; +}; + +#endif diff --git a/Sources/libetpan/include/mailsasl.h b/Sources/libetpan/include/mailsasl.h new file mode 100644 index 00000000..6d567889 --- /dev/null +++ b/Sources/libetpan/include/mailsasl.h @@ -0,0 +1,50 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILSASL_H + +#define MAILSASL_H + +#ifdef __cplusplus +extern"C"{ +#endif + +/* if Cyrus-SASL is used outside of libetpan */ +void mailsasl_external_ref(void); + +void mailsasl_ref(void); +void mailsasl_unref(void); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/Sources/libetpan/include/mailsasl_private.h b/Sources/libetpan/include/mailsasl_private.h new file mode 100644 index 00000000..3ee1c38b --- /dev/null +++ b/Sources/libetpan/include/mailsasl_private.h @@ -0,0 +1,18 @@ +#ifndef MAILSASL_PRIVATE_H + +#define MAILSASL_PRIVATE_H + +#ifdef __cplusplus +extern"C"{ +#endif + +extern void mailsasl_init_lock(void); + +extern void mailsasl_uninit_lock(void); + +#ifdef __cplusplus +} +#endif + + +#endif \ No newline at end of file diff --git a/Sources/libetpan/include/mailsem.h b/Sources/libetpan/include/mailsem.h new file mode 100644 index 00000000..c492bbd8 --- /dev/null +++ b/Sources/libetpan/include/mailsem.h @@ -0,0 +1,59 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsem.h,v 1.2 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef MAILSEM_H + +#define MAILSEM_H + +#include "libetpan-config.h" + +struct mailsem { + void * sem_sem; + int sem_kind; +}; + +LIBETPAN_EXPORT +struct mailsem * mailsem_new(void); + +LIBETPAN_EXPORT +void mailsem_free(struct mailsem * sem); + +LIBETPAN_EXPORT +int mailsem_up(struct mailsem * sem); + +LIBETPAN_EXPORT +int mailsem_down(struct mailsem * sem); + +#endif diff --git a/Sources/libetpan/include/mailsmtp.h b/Sources/libetpan/include/mailsmtp.h new file mode 100644 index 00000000..74344f00 --- /dev/null +++ b/Sources/libetpan/include/mailsmtp.h @@ -0,0 +1,191 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsmtp.h,v 1.23 2010/11/28 17:01:26 hoa Exp $ + */ + +#ifndef MAILSMTP_H + +#define MAILSMTP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailsmtp_types.h" +#include "mailsmtp_helper.h" +#include "mailsmtp_socket.h" +#include "mailsmtp_ssl.h" +#include "mailsmtp_oauth2.h" + + +LIBETPAN_EXPORT +mailsmtp * mailsmtp_new(size_t progr_rate, + progress_function * progr_fun); + +LIBETPAN_EXPORT +void mailsmtp_free(mailsmtp * session); + +LIBETPAN_EXPORT +void mailsmtp_set_timeout(mailsmtp * session, time_t timeout); + +LIBETPAN_EXPORT +time_t mailsmtp_get_timeout(mailsmtp * session); + +LIBETPAN_EXPORT +int mailsmtp_connect(mailsmtp * session, mailstream * s); + +LIBETPAN_EXPORT +int mailsmtp_quit(mailsmtp * session); + + +/* This call is deprecated and mailesmtp_auth_sasl() should be used instead */ +/** + * Tries AUTH with detected method - "better" method first: + * CRAM-MD5 -> PLAIN -> LOGIN + */ +LIBETPAN_EXPORT +int mailsmtp_auth(mailsmtp * session, const char * user, const char * pass); + +/* This call is deprecated and mailesmtp_auth_sasl() should be used instead */ +/** + * tries to autenticate with the server using given auth-type + * returns MAILSMTP_NO_ERROR on success + */ +LIBETPAN_EXPORT +int mailsmtp_auth_type(mailsmtp * session, + const char * user, const char * pass, int type); + +LIBETPAN_EXPORT +int mailsmtp_helo(mailsmtp * session); + +LIBETPAN_EXPORT +int mailsmtp_helo_with_ip(mailsmtp * session, int useip); + +LIBETPAN_EXPORT +int mailsmtp_mail(mailsmtp * session, const char * from); + +LIBETPAN_EXPORT +int mailsmtp_rcpt(mailsmtp * session, const char * to); + +LIBETPAN_EXPORT +int mailsmtp_data(mailsmtp * session); + +LIBETPAN_EXPORT +int mailsmtp_data_message(mailsmtp * session, + const char * message, + size_t size); + +LIBETPAN_EXPORT +int maillmtp_data_message(mailsmtp * session, + const char * message, + size_t size, + clist * recipient_list, + int * retcodes); + +LIBETPAN_EXPORT +int mailsmtp_data_message_quit(mailsmtp * session, + const char * message, + size_t size); + +LIBETPAN_EXPORT +int mailsmtp_data_message_quit_no_disconnect(mailsmtp * session, + const char * message, + size_t size); + +LIBETPAN_EXPORT +int mailesmtp_lhlo(mailsmtp * session, const char *hostname); + +LIBETPAN_EXPORT +int mailesmtp_ehlo(mailsmtp * session); + +LIBETPAN_EXPORT +int mailesmtp_ehlo_with_ip(mailsmtp * session, int useip); + +LIBETPAN_EXPORT +int mailesmtp_mail(mailsmtp * session, + const char * from, + int return_full, + const char * envid); + +LIBETPAN_EXPORT +int mailesmtp_mail_size(mailsmtp * session, + const char * from, + int return_full, + const char * envid, size_t size); + +LIBETPAN_EXPORT +int mailesmtp_rcpt(mailsmtp * session, + const char * to, + int notify, + const char * orcpt); + +LIBETPAN_EXPORT +int mailesmtp_clientid(mailsmtp * session, + const char * type, + const char * clientid); + +LIBETPAN_EXPORT +int mailesmtp_starttls(mailsmtp * session); + +LIBETPAN_EXPORT +const char * mailsmtp_strerror(int errnum); + +/* sasl authentication */ +LIBETPAN_EXPORT +int mailesmtp_auth_sasl(mailsmtp * session, const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); + +LIBETPAN_EXPORT +int mailsmtp_noop(mailsmtp * session); + +LIBETPAN_EXPORT +int mailsmtp_reset(mailsmtp * session); + +LIBETPAN_EXPORT +void mailsmtp_set_progress_callback(mailsmtp * session, + mailprogress_function * progr_fun, + void * context); + +LIBETPAN_EXPORT +void mailsmtp_set_logger(mailsmtp * session, void (* logger)(mailsmtp * session, int log_type, + const char * str, size_t size, void * context), void * logger_context); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailsmtp_helper.h b/Sources/libetpan/include/mailsmtp_helper.h new file mode 100644 index 00000000..3fb42f5b --- /dev/null +++ b/Sources/libetpan/include/mailsmtp_helper.h @@ -0,0 +1,107 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsmtp_helper.h,v 1.11 2006/05/22 13:39:43 hoa Exp $ + */ + +#ifndef MAILSMTP_HELPER_H + +#define MAILSMTP_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "libetpan-config.h" + +#include "mailsmtp_types.h" +#include "clist.h" + +LIBETPAN_EXPORT +int mailsmtp_init(mailsmtp * session); + +LIBETPAN_EXPORT +int mailsmtp_init_with_ip(mailsmtp * session, int useip); + +LIBETPAN_EXPORT +int mailesmtp_send(mailsmtp * session, + const char * from, + int return_full, + const char * envid, + clist * addresses, + const char * message, size_t size); + +LIBETPAN_EXPORT +int mailesmtp_send_quit(mailsmtp * session, + const char * from, + int return_full, + const char * envid, + clist * addresses, + const char * message, size_t size); +LIBETPAN_EXPORT +int mailesmtp_send_quit_no_disconnect(mailsmtp * session, + const char * from, + int return_full, + const char * envid, + clist * addresses, + const char * message, size_t size); + +LIBETPAN_EXPORT +int mailsmtp_send(mailsmtp * session, + const char * from, + clist * addresses, + const char * message, size_t size); + +LIBETPAN_EXPORT +clist * esmtp_address_list_new(void); + +LIBETPAN_EXPORT +int esmtp_address_list_add(clist * list, char * address, + int notify, char * orcpt); + +LIBETPAN_EXPORT +void esmtp_address_list_free(clist * l); + +LIBETPAN_EXPORT +clist * smtp_address_list_new(void); + +LIBETPAN_EXPORT +int smtp_address_list_add(clist * list, char * address); + +LIBETPAN_EXPORT +void smtp_address_list_free(clist * l); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailsmtp_oauth2.h b/Sources/libetpan/include/mailsmtp_oauth2.h new file mode 100644 index 00000000..93b5d69d --- /dev/null +++ b/Sources/libetpan/include/mailsmtp_oauth2.h @@ -0,0 +1,45 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILSMTP_OAUTH2_H + +#define MAILSMTP_OAUTH2_H + +#include "mailsmtp_types.h" + +LIBETPAN_EXPORT +int mailsmtp_oauth2_authenticate(mailsmtp * session, const char * auth_user, + const char * access_token); + +LIBETPAN_EXPORT +int mailsmtp_oauth2_outlook_authenticate(mailsmtp * session, const char * auth_user, + const char * access_token); + +#endif diff --git a/Sources/libetpan/include/mailsmtp_private.h b/Sources/libetpan/include/mailsmtp_private.h new file mode 100644 index 00000000..cc04aa30 --- /dev/null +++ b/Sources/libetpan/include/mailsmtp_private.h @@ -0,0 +1,43 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILSMTP_PRIVATE_H + +#define MAILSMTP_PRIVATE_H + +#include "mailsmtp_types.h" + +int mailsmtp_send_command(mailsmtp * f, char * command); + +int mailsmtp_send_command_private(mailsmtp * f, char * command); + +int mailsmtp_read_response(mailsmtp * session); + +#endif diff --git a/Sources/libetpan/include/mailsmtp_socket.h b/Sources/libetpan/include/mailsmtp_socket.h new file mode 100644 index 00000000..09996773 --- /dev/null +++ b/Sources/libetpan/include/mailsmtp_socket.h @@ -0,0 +1,62 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsmtp_socket.h,v 1.18 2006/12/26 13:13:25 hoa Exp $ + */ + +#ifndef MAILSMTP_SOCKET_H + +#define MAILSMTP_SOCKET_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "libetpan-config.h" +#include "mailsmtp_types.h" + +LIBETPAN_EXPORT +int mailsmtp_socket_connect(mailsmtp * session, + const char * server, uint16_t port); + +LIBETPAN_EXPORT +int mailsmtp_socket_starttls(mailsmtp * session); + +LIBETPAN_EXPORT +int mailsmtp_socket_starttls_with_callback(mailsmtp * session, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailsmtp_ssl.h b/Sources/libetpan/include/mailsmtp_ssl.h new file mode 100644 index 00000000..bdeedc9c --- /dev/null +++ b/Sources/libetpan/include/mailsmtp_ssl.h @@ -0,0 +1,63 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsmtp_ssl.h,v 1.16 2006/12/26 13:13:25 hoa Exp $ + */ + +#ifndef MAILSMTP_SSL_H + +#define MAILSMTP_SSL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_INTTYPES_H +# include +#endif + +#include "mailsmtp_types.h" + +LIBETPAN_EXPORT +int mailsmtp_ssl_connect(mailsmtp * session, + const char * server, uint16_t port); + +LIBETPAN_EXPORT +int mailsmtp_ssl_connect_with_callback(mailsmtp * session, + const char * server, uint16_t port, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailsmtp_types.h b/Sources/libetpan/include/mailsmtp_types.h new file mode 100644 index 00000000..b57c2100 --- /dev/null +++ b/Sources/libetpan/include/mailsmtp_types.h @@ -0,0 +1,158 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsmtp_types.h,v 1.20 2011/02/28 22:40:02 hoa Exp $ + */ + +#ifndef MAILSMTP_TYPES_H + +#define MAILSMTP_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailstream.h" +#include "mmapstring.h" + +enum { + MAILSMTP_NO_ERROR = 0, + MAILSMTP_ERROR_UNEXPECTED_CODE, + MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE, + MAILSMTP_ERROR_STREAM, + MAILSMTP_ERROR_HOSTNAME, + MAILSMTP_ERROR_NOT_IMPLEMENTED, + MAILSMTP_ERROR_ACTION_NOT_TAKEN, + MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION, + MAILSMTP_ERROR_IN_PROCESSING, + MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE, + MAILSMTP_ERROR_MAILBOX_UNAVAILABLE, + MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED, + MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND, + MAILSMTP_ERROR_USER_NOT_LOCAL, + MAILSMTP_ERROR_TRANSACTION_FAILED, + MAILSMTP_ERROR_MEMORY, + MAILSMTP_ERROR_AUTH_NOT_SUPPORTED, + MAILSMTP_ERROR_AUTH_LOGIN, + MAILSMTP_ERROR_AUTH_REQUIRED, + MAILSMTP_ERROR_AUTH_TOO_WEAK, + MAILSMTP_ERROR_AUTH_TRANSITION_NEEDED, + MAILSMTP_ERROR_AUTH_TEMPORARY_FAILTURE, + MAILSMTP_ERROR_AUTH_ENCRYPTION_REQUIRED, + MAILSMTP_ERROR_STARTTLS_TEMPORARY_FAILURE, + MAILSMTP_ERROR_STARTTLS_NOT_SUPPORTED, + MAILSMTP_ERROR_CONNECTION_REFUSED, + MAILSMTP_ERROR_AUTH_AUTHENTICATION_FAILED, + MAILSMTP_ERROR_SSL, + MAILSMTP_ERROR_CLIENTID_NOT_SUPPORTED +}; + +enum { + MAILSMTP_AUTH_NOT_CHECKED = 0, + MAILSMTP_AUTH_CHECKED = 1, + MAILSMTP_AUTH_CRAM_MD5 = 2, + MAILSMTP_AUTH_PLAIN = 4, + MAILSMTP_AUTH_LOGIN = 8, + MAILSMTP_AUTH_DIGEST_MD5 = 16, + MAILSMTP_AUTH_GSSAPI = 32, + MAILSMTP_AUTH_SRP = 64, + MAILSMTP_AUTH_NTLM = 128, + MAILSMTP_AUTH_KERBEROS_V4 = 256 +}; + +enum { + MAILSMTP_ESMTP = 1, + MAILSMTP_ESMTP_EXPN = 2, + MAILSMTP_ESMTP_8BITMIME = 4, + MAILSMTP_ESMTP_SIZE = 8, + MAILSMTP_ESMTP_ETRN = 16, + MAILSMTP_ESMTP_STARTTLS = 32, + MAILSMTP_ESMTP_DSN = 64, + MAILSMTP_ESMTP_PIPELINING = 128, + MAILSMTP_ESMTP_CLIENTID = 256 +}; + +typedef struct mailsmtp mailsmtp; + +struct mailsmtp { + mailstream * stream; + + size_t progr_rate; + progress_function * progr_fun; + + char * response; + + MMAPString * line_buffer; + MMAPString * response_buffer; + + int esmtp; /* contains flags MAILSMTP_ESMTP_* */ + int auth; /* contains flags MAILSMTP_AUTH_* */ + + struct { + void * sasl_conn; + const char * sasl_server_fqdn; + const char * sasl_login; + const char * sasl_auth_name; + const char * sasl_password; + const char * sasl_realm; + void * sasl_secret; + } smtp_sasl; + + size_t smtp_max_msg_size; + + mailprogress_function * smtp_progress_fun; + void * smtp_progress_context; + + int response_code; + + time_t smtp_timeout; + + void (* smtp_logger)(mailsmtp * session, int log_type, const char * str, size_t size, void * context); + void * smtp_logger_context; +}; + +#define MAILSMTP_DSN_NOTIFY_SUCCESS 1 +#define MAILSMTP_DSN_NOTIFY_FAILURE 2 +#define MAILSMTP_DSN_NOTIFY_DELAY 4 +#define MAILSMTP_DSN_NOTIFY_NEVER 8 + +struct esmtp_address { + char * address; + int notify; + char * orcpt; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailstorage.h b/Sources/libetpan/include/mailstorage.h new file mode 100644 index 00000000..12599226 --- /dev/null +++ b/Sources/libetpan/include/mailstorage.h @@ -0,0 +1,110 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstorage.h,v 1.17 2006/06/02 15:44:30 smarinier Exp $ + */ + +#ifndef MAIL_STORAGE_H + +#define MAIL_STORAGE_H + +#include "maildriver_types.h" +#include "mailstorage_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* storage */ + +/* + mailstorage_new + + This function creates an empty storage. This storage have to be initialized. + The "driver" and "data" fields should be initialized. + + @param id is the name of the storage. It can be NULL. + The given parameter is no more needed when the creation is finished. + The given string is duplicated. + + @return The mail storage is returned. +*/ + +LIBETPAN_EXPORT +struct mailstorage * mailstorage_new(const char * sto_id); + +LIBETPAN_EXPORT +void mailstorage_free(struct mailstorage * storage); + +/* + session will be initialized on success. +*/ + +LIBETPAN_EXPORT +int mailstorage_connect(struct mailstorage * storage); + +LIBETPAN_EXPORT +void mailstorage_disconnect(struct mailstorage * storage); + +LIBETPAN_EXPORT +int mailstorage_noop(struct mailstorage * storage); + + +/* folder */ + +LIBETPAN_EXPORT +struct mailfolder * mailfolder_new(struct mailstorage * fld_storage, + const char * fld_pathname, const char * fld_virtual_name); + +LIBETPAN_EXPORT +void mailfolder_free(struct mailfolder * folder); + +LIBETPAN_EXPORT +int mailfolder_add_child(struct mailfolder * parent, + struct mailfolder * child); + +LIBETPAN_EXPORT +int mailfolder_detach_parent(struct mailfolder * folder); + +LIBETPAN_EXPORT +int mailfolder_connect(struct mailfolder * folder); + +LIBETPAN_EXPORT +void mailfolder_disconnect(struct mailfolder * folder); + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/Sources/libetpan/include/mailstorage_tools.h b/Sources/libetpan/include/mailstorage_tools.h new file mode 100644 index 00000000..bd1b21f3 --- /dev/null +++ b/Sources/libetpan/include/mailstorage_tools.h @@ -0,0 +1,89 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstorage_tools.h,v 1.8 2007/06/30 12:58:21 hoa Exp $ + */ + +#include "mailstorage.h" + +#ifndef MAILSTORAGE_TOOLS_H + +#define MAILSTORAGE_TOOLS_H + +#ifdef __cplusplus +extern "C" { +#endif + +int mailstorage_generic_connect(mailsession_driver * driver, + char * servername, + uint16_t port, + char * command, + int connection_type, + int cache_function_id, + char * cache_directory, + int flags_function_id, + char * flags_directory, + mailsession ** result); + +int mailstorage_generic_connect_with_local_address(mailsession_driver * driver, + char * servername, + uint16_t port, + char * local_address, + uint16_t local_port, + char * command, + int connection_type, + int cache_function_id, + char * cache_directory, + int flags_function_id, + char * flags_directory, + mailsession ** result); + +int mailstorage_generic_auth(mailsession * session, + int connect_result, + int auth_type, + char * login, + char * password); + +int mailstorage_generic_auth_sasl(mailsession * session, + int connect_result, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailstorage_types.h b/Sources/libetpan/include/mailstorage_types.h new file mode 100644 index 00000000..ef3c3569 --- /dev/null +++ b/Sources/libetpan/include/mailstorage_types.h @@ -0,0 +1,203 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstorage_types.h,v 1.9 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifndef MAILSTORAGE_TYPES_H + +#define MAILSTORAGE_TYPES_H + +#include "maildriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct mailstorage; + +typedef struct mailstorage_driver mailstorage_driver; + + +/* + There is three kinds of identities : + - storage + - folders + - session + + A storage (struct mailstorage) represents whether a server or + a main path, + + A storage can be an IMAP server, the root path of a MH or a mbox file. + + Folders (struct mailfolder) are the mailboxes we can + choose in the server or as sub-folder of the main path. + + Folders for IMAP are the IMAP mailboxes, for MH this is one of the + folder of the MH storage, for mbox, there is only one folder, the + mbox file content; + + A mail session (struct mailsession) is whether a connection to a server + or a path that is open. It is the abstraction lower folders and storage. + It allow us to send commands. + + We have a session driver for mail session for each kind of storage. + + From a session, we can get a message (struct mailmessage) to read. + We have a message driver for each kind of storage. +*/ + +/* + mailstorage_driver is the driver structure for mail storages + + - name is the name of the driver + + - connect() connects the storage to the remote access or to + the path in the local filesystem. + + - get_folder() can have two kinds of behaviour. + Either it creates a new session and independant from the session + used by the storage and select the given mailbox or + it selects the given mailbox in the current session. + It depends on the efficiency of the mail driver. + + - uninitialize() frees the data created with mailstorage constructor. +*/ + +struct mailstorage_driver { + char * sto_name; + int (* sto_connect)(struct mailstorage * storage); + int (* sto_get_folder_session)(struct mailstorage * storage, + char * pathname, mailsession ** result); + void (* sto_uninitialize)(struct mailstorage * storage); +}; + +/* + mailstorage is the data structure for a storage + + - id is the name of the storage, it can be NULL. + + - data is the data specific to the driver. + This is the internal state of the storage. + + - session is the session related to the storage. + + - driver is the driver for the storage. + + - shared_folders is the list of folders returned by the storage. +*/ + +struct mailstorage { + char * sto_id; + void * sto_data; + mailsession * sto_session; + mailstorage_driver * sto_driver; + clist * sto_shared_folders; /* list of (struct mailfolder *) */ + + void * sto_user_data; +}; + + + +/* + mailfolder is the data structure for a mailbox + + - pathname is the path of the mailbox on the storage + + - virtual_name is the folder identifier, it can be a path, + a name or NULL. + + - storage is the storage to which the folder belongs to. + + - session is the session related to the folder. It can be + different of the session of the storage. + + - shared_session is != 0 if the session is the same as the + session of the storage. + + - pos is the position of the folder in the "shared_folders" field + of the storage. + + folders can be chained into a tree. + + - parent is the parent of the folder. + + - sibling_index is the index of the folder in the list of children + of the parent. + + - children is the folder. +*/ + +struct mailfolder { + char * fld_pathname; + char * fld_virtual_name; + + struct mailstorage * fld_storage; + + mailsession * fld_session; + int fld_shared_session; + clistiter * fld_pos; + + struct mailfolder * fld_parent; + unsigned int fld_sibling_index; + carray * fld_children; /* array of (struct mailfolder *) */ + + void * fld_user_data; +}; + +/* + this is the type of socket connection +*/ + +enum { + CONNECTION_TYPE_PLAIN, /* when the connection is plain text */ + CONNECTION_TYPE_STARTTLS, /* when the connection is first plain, + then, we want to switch to + TLS (secure connection) */ + CONNECTION_TYPE_TRY_STARTTLS, /* the connection is first plain, + then, we will try to switch to TLS */ + CONNECTION_TYPE_TLS, /* the connection is over TLS */ + CONNECTION_TYPE_COMMAND, /* the connection is over a shell command */ + CONNECTION_TYPE_COMMAND_STARTTLS, /* the connection is over a shell + command and STARTTLS will be used */ + CONNECTION_TYPE_COMMAND_TRY_STARTTLS, /* the connection is over + a shell command and STARTTLS will + be tried */ + CONNECTION_TYPE_COMMAND_TLS /* the connection is over a shell + command in TLS */ +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailstream.h b/Sources/libetpan/include/mailstream.h new file mode 100644 index 00000000..3cada7a3 --- /dev/null +++ b/Sources/libetpan/include/mailstream.h @@ -0,0 +1,135 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream.h,v 1.21 2011/03/11 21:49:36 hoa Exp $ + */ + +#ifndef MAILSTREAM_H + +#define MAILSTREAM_H + +#ifndef _MSC_VER +# include +#endif + +#include "mailstream_low.h" +#include "mailstream_helper.h" +#include "mailstream_socket.h" +#include "mailstream_ssl.h" +#include "mailstream_cfstream.h" +#include "mailstream_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +LIBETPAN_EXPORT +mailstream * mailstream_new(mailstream_low * low, size_t buffer_size); + +LIBETPAN_EXPORT +ssize_t mailstream_write(mailstream * s, const void * buf, size_t count); + +LIBETPAN_EXPORT +ssize_t mailstream_read(mailstream * s, void * buf, size_t count); + +LIBETPAN_EXPORT +int mailstream_close(mailstream * s); + +LIBETPAN_EXPORT +int mailstream_flush(mailstream * s); + +LIBETPAN_EXPORT +ssize_t mailstream_feed_read_buffer(mailstream * s); + +LIBETPAN_EXPORT +void mailstream_log_error(mailstream * s, char * buf, size_t count); + +LIBETPAN_EXPORT +mailstream_low * mailstream_get_low(mailstream * s); + +LIBETPAN_EXPORT +void mailstream_set_low(mailstream * s, mailstream_low * low); + +LIBETPAN_EXPORT +void mailstream_cancel(mailstream * s); + +LIBETPAN_EXPORT +void mailstream_set_privacy(mailstream * s, int can_be_public); + +#ifdef LIBETPAN_MAILSTREAM_DEBUG +LIBETPAN_EXPORT +extern int mailstream_debug; + +/* direction is 1 for send, 0 for receive, -1 when it does not apply */ +LIBETPAN_EXPORT +extern void (* mailstream_logger)(int direction, + const char * str, size_t size); +LIBETPAN_EXPORT +extern void (* mailstream_logger_id)(mailstream_low * s, int is_stream_data, int direction, + const char * str, size_t size); +#endif + +LIBETPAN_EXPORT +void mailstream_set_logger(mailstream * s, void (* logger)(mailstream * s, int log_type, + const char * str, size_t size, void * context), void * logger_context); + +/* can be run in thread */ +LIBETPAN_EXPORT +int mailstream_wait_idle(mailstream * s, int max_idle_delay); + +/* in main thread */ +LIBETPAN_EXPORT +int mailstream_setup_idle(mailstream * s); + +LIBETPAN_EXPORT +void mailstream_unsetup_idle(mailstream * s); + +LIBETPAN_EXPORT +void mailstream_interrupt_idle(mailstream * s); + +/* Get certificate chain. Returns an array of MMAPString containing DER data or NULL if it's not a SSL connection */ +LIBETPAN_EXPORT +carray * mailstream_get_certificate_chain(mailstream * s); + +LIBETPAN_EXPORT +void mailstream_certificate_chain_free(carray * certificate_chain); + +#define LIBETPAN_MAILSTREAM_NETWORK_DELAY +LIBETPAN_EXPORT +extern struct timeval mailstream_network_delay; + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Sources/libetpan/include/mailstream_cancel.h b/Sources/libetpan/include/mailstream_cancel.h new file mode 100644 index 00000000..b492fb52 --- /dev/null +++ b/Sources/libetpan/include/mailstream_cancel.h @@ -0,0 +1,45 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILSTREAM_CANCEL_H + +#define MAILSTREAM_CANCEL_H + +#include "mailstream_cancel_types.h" + +struct mailstream_cancel * mailstream_cancel_new(void); +void mailstream_cancel_free(struct mailstream_cancel * cancel); + +int mailstream_cancel_cancelled(struct mailstream_cancel * cancel); +void mailstream_cancel_notify(struct mailstream_cancel * cancel); +void mailstream_cancel_ack(struct mailstream_cancel * cancel); +int mailstream_cancel_get_fd(struct mailstream_cancel * cancel); + +#endif diff --git a/Sources/libetpan/include/mailstream_cancel_types.h b/Sources/libetpan/include/mailstream_cancel_types.h new file mode 100644 index 00000000..723162e3 --- /dev/null +++ b/Sources/libetpan/include/mailstream_cancel_types.h @@ -0,0 +1,41 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILSTREAM_CANCEL_TYPES_H + +#define MAILSTREAM_CANCEL_TYPES_H + +struct mailstream_cancel { + int ms_cancelled; + int ms_fds[2]; + void * ms_internal; +}; + +#endif diff --git a/Sources/libetpan/include/mailstream_cfstream.h b/Sources/libetpan/include/mailstream_cfstream.h new file mode 100644 index 00000000..731cc3d9 --- /dev/null +++ b/Sources/libetpan/include/mailstream_cfstream.h @@ -0,0 +1,114 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef MAILSTREAM_CFSTREAM_H + +#define MAILSTREAM_CFSTREAM_H + +#include "libetpan-config.h" +#include "mailstream.h" + +#ifdef __cplusplus +extern "C" { +#endif + + LIBETPAN_EXPORT + extern int mailstream_cfstream_enabled; + + LIBETPAN_EXPORT + extern int mailstream_cfstream_voip_enabled; + + enum { + MAILSTREAM_CFSTREAM_SSL_ALLOWS_EXPIRED_CERTIFICATES = 1 << 0, + MAILSTREAM_CFSTREAM_SSL_ALLOWS_EXPIRED_ROOTS = 1 << 1, + MAILSTREAM_CFSTREAM_SSL_ALLOWS_ANY_ROOT = 1 << 2, + MAILSTREAM_CFSTREAM_SSL_DISABLE_VALIDATES_CERTIFICATE_CHAIN = 1 << 3, + MAILSTREAM_CFSTREAM_SSL_NO_VERIFICATION = MAILSTREAM_CFSTREAM_SSL_ALLOWS_EXPIRED_CERTIFICATES | + MAILSTREAM_CFSTREAM_SSL_ALLOWS_EXPIRED_ROOTS | + MAILSTREAM_CFSTREAM_SSL_ALLOWS_ANY_ROOT | + MAILSTREAM_CFSTREAM_SSL_DISABLE_VALIDATES_CERTIFICATE_CHAIN + }; + + enum { + MAILSTREAM_CFSTREAM_SSL_LEVEL_NONE, + MAILSTREAM_CFSTREAM_SSL_LEVEL_SSLv2, + MAILSTREAM_CFSTREAM_SSL_LEVEL_SSLv3, + MAILSTREAM_CFSTREAM_SSL_LEVEL_TLSv1, + MAILSTREAM_CFSTREAM_SSL_LEVEL_NEGOCIATED_SSL + }; + + /* socket */ + + extern mailstream_low_driver * mailstream_cfstream_driver; + + mailstream * mailstream_cfstream_open(const char * hostname, int16_t port); + mailstream * mailstream_cfstream_open_timeout(const char * hostname, int16_t port, time_t timeout); + mailstream * mailstream_cfstream_open_voip(const char * hostname, int16_t port, int voip_enabled); + mailstream * mailstream_cfstream_open_voip_timeout(const char * hostname, int16_t port, int voip_enabled, + time_t timeout); + + mailstream_low * mailstream_low_cfstream_open(const char * hostname, int16_t port); + mailstream_low * mailstream_low_cfstream_open_timeout(const char * hostname, int16_t port, + time_t timeout); + mailstream_low * mailstream_low_cfstream_open_voip(const char * hostname, int16_t port, int voip_enabled); + mailstream_low * mailstream_low_cfstream_open_voip_timeout(const char * hostname, int16_t port, + int voip_enabled, time_t timeout); + + /* first, set these settings */ + void mailstream_cfstream_set_ssl_verification_mask(mailstream * s, int verification_mask); + void mailstream_cfstream_set_ssl_peer_name(mailstream * s, const char * peer_name); + void mailstream_cfstream_set_ssl_is_server(mailstream * s, int is_server); + void mailstream_cfstream_set_ssl_level(mailstream * s, int ssl_level); + /* missing setting certificate */ + + /* then, enable SSL */ + int mailstream_cfstream_set_ssl_enabled(mailstream * s, int ssl_enabled); + int mailstream_cfstream_is_ssl_enabled(mailstream * s); + + /* support for IMAP IDLE */ + + /* can be run in thread */ + int mailstream_cfstream_wait_idle(mailstream * s, int max_idle_delay); + int mailstream_low_cfstream_wait_idle(mailstream_low * low, int max_idle_delay); + + /* in main thread */ + /* + void mailstream_low_cfstream_setup_idle(mailstream_low * s); + void mailstream_low_cfstream_interrupt_idle(mailstream_low * s); + void mailstream_low_cfstream_unsetup_idle(mailstream_low * s); + */ + /* SSL certificate */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailstream_compress.h b/Sources/libetpan/include/mailstream_compress.h new file mode 100644 index 00000000..07ec5806 --- /dev/null +++ b/Sources/libetpan/include/mailstream_compress.h @@ -0,0 +1,72 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2013 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* Created by Ian Ragsdale on 3/8/13. */ + +#ifndef MAILSTREAM_COMPRESS_H +#define MAILSTREAM_COMPRESS_H + +#define USE_DEFLATE 1 + +#include "mailstream.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailstream_low_driver * mailstream_compress_driver; + +struct mailstream_compress_context; + +/* exported methods */ +LIBETPAN_EXPORT +mailstream_low * mailstream_low_compress_open(mailstream_low * ms); + +LIBETPAN_EXPORT +int mailstream_low_compress_wait_idle(mailstream_low * low, + struct mailstream_cancel * idle, + int max_idle_delay); + + /* +LIBETPAN_EXPORT +int mailstream_low_compress_setup_idle(mailstream_low * low); + +LIBETPAN_EXPORT +int mailstream_low_compress_unsetup_idle(mailstream_low * low); + +LIBETPAN_EXPORT +int mailstream_low_compress_interrupt_idle(mailstream_low * low); +*/ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Sources/libetpan/include/mailstream_helper.h b/Sources/libetpan/include/mailstream_helper.h new file mode 100644 index 00000000..fe9d8852 --- /dev/null +++ b/Sources/libetpan/include/mailstream_helper.h @@ -0,0 +1,88 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream_helper.h,v 1.13 2010/11/28 17:01:26 hoa Exp $ + */ + +#ifndef MAILSTREAM_HELPER_H + +#define MAILSTREAM_HELPER_H + +#include "mmapstring.h" +#include "mailstream.h" + +#ifdef __cplusplus +extern "C" { +#endif + +char * mailstream_read_line(mailstream * stream, MMAPString * line); + +char * mailstream_read_line_append(mailstream * stream, MMAPString * line); + +char * mailstream_read_line_remove_eol(mailstream * stream, MMAPString * line); + +char * mailstream_read_multiline(mailstream * s, size_t size, + MMAPString * stream_buffer, + MMAPString * multiline_buffer, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, void * context); + +int mailstream_is_end_multiline(const char * line); + +int mailstream_send_data_crlf(mailstream * s, const char * message, + size_t size, + size_t progr_rate, + progress_function * progr_fun); + +int mailstream_send_data_crlf_with_context(mailstream * s, const char * message, + size_t size, + mailprogress_function * progr_fun, + void * context); + +int mailstream_send_data(mailstream * s, const char * message, + size_t size, + size_t progr_rate, + progress_function * progr_fun); + +int mailstream_send_data_with_context(mailstream * s, const char * message, + size_t size, + mailprogress_function * progr_fun, + void * context); + +size_t mailstream_get_data_crlf_size(const char * message, size_t size); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailstream_low.h b/Sources/libetpan/include/mailstream_low.h new file mode 100644 index 00000000..7d71172e --- /dev/null +++ b/Sources/libetpan/include/mailstream_low.h @@ -0,0 +1,123 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream_low.h,v 1.15 2011/05/04 16:01:10 hoa Exp $ + */ + +#ifndef MAILSTREAM_LOW_H + +#define MAILSTREAM_LOW_H + +#include "sys/types.h" +#include "mailstream_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* general functions */ + +LIBETPAN_EXPORT +mailstream_low * mailstream_low_new(void * data, + mailstream_low_driver * driver); + +ssize_t mailstream_low_write(mailstream_low * s, + const void * buf, size_t count); + +ssize_t mailstream_low_read(mailstream_low * s, void * buf, size_t count); + +LIBETPAN_EXPORT +int mailstream_low_close(mailstream_low * s); + +LIBETPAN_EXPORT +int mailstream_low_get_fd(mailstream_low * s); + +LIBETPAN_EXPORT +struct mailstream_cancel * mailstream_low_get_cancel(mailstream_low * s); + +LIBETPAN_EXPORT +void mailstream_low_free(mailstream_low * s); + +LIBETPAN_EXPORT +void mailstream_low_cancel(mailstream_low * s); + +LIBETPAN_EXPORT +void mailstream_low_log_error(mailstream_low * s, + const void * buf, size_t count); + +LIBETPAN_EXPORT +void mailstream_low_set_privacy(mailstream_low * s, int can_be_public); + +LIBETPAN_EXPORT +int mailstream_low_set_identifier(mailstream_low * s, + char * identifier); + +LIBETPAN_EXPORT +const char * mailstream_low_get_identifier(mailstream_low * s); + +LIBETPAN_EXPORT +void mailstream_low_set_timeout(mailstream_low * s, + time_t timeout); + +LIBETPAN_EXPORT +time_t mailstream_low_get_timeout(mailstream_low * s); + +LIBETPAN_EXPORT +void mailstream_low_set_logger(mailstream_low * s, void (* logger)(mailstream_low * s, int log_type, + const char * str, size_t size, void * context), void * logger_context); + +/* Get certificate chain. Returns an array of MMAPString containing DER data or NULL if it's not a SSL connection */ +LIBETPAN_EXPORT +carray * mailstream_low_get_certificate_chain(mailstream_low * s); + +LIBETPAN_EXPORT +int mailstream_low_wait_idle(mailstream_low * low, struct mailstream_cancel * cancel, + int max_idle_delay); + +/* + All those functions returns -1 if interrupt idle is not implemented and + should be based on select(). +*/ +LIBETPAN_EXPORT +int mailstream_low_setup_idle(mailstream_low * low); + +LIBETPAN_EXPORT +int mailstream_low_unsetup_idle(mailstream_low * low); + +LIBETPAN_EXPORT +int mailstream_low_interrupt_idle(mailstream_low * low); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailstream_socket.h b/Sources/libetpan/include/mailstream_socket.h new file mode 100644 index 00000000..423c2271 --- /dev/null +++ b/Sources/libetpan/include/mailstream_socket.h @@ -0,0 +1,59 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream_socket.h,v 1.12 2011/04/15 10:43:31 hoa Exp $ + */ + +#ifndef MAILSTREAM_SOCKET_H + +#define MAILSTREAM_SOCKET_H + +#include "mailstream.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* socket */ + +extern mailstream_low_driver * mailstream_socket_driver; + +mailstream_low * mailstream_low_socket_open(int fd); +void mailstream_socket_set_use_read(mailstream * stream, int use_read); +mailstream * mailstream_socket_open(int fd); +mailstream * mailstream_socket_open_timeout(int fd, time_t timeout); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailstream_ssl.h b/Sources/libetpan/include/mailstream_ssl.h new file mode 100644 index 00000000..6b619e52 --- /dev/null +++ b/Sources/libetpan/include/mailstream_ssl.h @@ -0,0 +1,140 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream_ssl.h,v 1.18 2008/07/03 19:42:27 colinleroy Exp $ + */ + +#ifndef MAILSTREAM_SSL_H + +#define MAILSTREAM_SSL_H + +#include "mailstream.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* socket */ + +#if LIBETPAN_IOS_DISABLE_SSL +#undef USE_SSL +#endif + +#ifdef USE_SSL +extern mailstream_low_driver * mailstream_ssl_driver; +#endif + +struct mailstream_ssl_context; + +LIBETPAN_EXPORT +mailstream_low * mailstream_low_ssl_open(int fd); + +LIBETPAN_EXPORT +mailstream_low * mailstream_low_ssl_open_timeout(int fd, time_t timeout); + +LIBETPAN_EXPORT +mailstream_low * mailstream_low_tls_open(int fd); + +LIBETPAN_EXPORT +mailstream_low * mailstream_low_tls_open_timeout(int fd, time_t timeout); + +LIBETPAN_EXPORT +mailstream * mailstream_ssl_open(int fd); + +LIBETPAN_EXPORT +mailstream * mailstream_ssl_open_timeout(int fd, time_t timeout); + +LIBETPAN_EXPORT +mailstream * mailstream_ssl_open_with_callback(int fd, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +LIBETPAN_EXPORT +mailstream * mailstream_ssl_open_with_callback_timeout(int fd, time_t timeout, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +LIBETPAN_EXPORT +void mailstream_gnutls_init_not_required(void); + +LIBETPAN_EXPORT +void mailstream_openssl_init_not_required(void); + +LIBETPAN_EXPORT +void mailstream_ssl_init_not_required(void); + +LIBETPAN_EXPORT +ssize_t mailstream_ssl_get_certificate(mailstream *stream, unsigned char **cert_DER); + +LIBETPAN_EXPORT +mailstream_low * mailstream_low_ssl_open_with_callback(int fd, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +LIBETPAN_EXPORT +mailstream_low * mailstream_low_ssl_open_with_callback_timeout(int fd, time_t timeout, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +LIBETPAN_EXPORT +mailstream_low * mailstream_low_tls_open_with_callback(int fd, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +LIBETPAN_EXPORT +mailstream_low * mailstream_low_tls_open_with_callback_timeout(int fd, time_t timeout, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +LIBETPAN_EXPORT +int mailstream_ssl_set_client_certicate(struct mailstream_ssl_context * ssl_context, + char * file_name); + +LIBETPAN_EXPORT +int mailstream_ssl_set_client_certificate_data(struct mailstream_ssl_context * ssl_context, + unsigned char *x509_der, size_t len); +int mailstream_ssl_set_client_private_key_data(struct mailstream_ssl_context * ssl_context, + unsigned char *pkey_der, size_t len); + +LIBETPAN_EXPORT +int mailstream_ssl_set_server_certicate(struct mailstream_ssl_context * ssl_context, + char * CAfile, char * CApath); + +LIBETPAN_EXPORT +int mailstream_ssl_set_server_name(struct mailstream_ssl_context * ssl_context, + char * hostname); + +LIBETPAN_EXPORT +void * mailstream_ssl_get_openssl_ssl_ctx(struct mailstream_ssl_context * ssl_context); + +LIBETPAN_EXPORT +int mailstream_ssl_get_fd(struct mailstream_ssl_context * ssl_context); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailstream_ssl_private.h b/Sources/libetpan/include/mailstream_ssl_private.h new file mode 100644 index 00000000..a0d2df9c --- /dev/null +++ b/Sources/libetpan/include/mailstream_ssl_private.h @@ -0,0 +1,48 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILSTREAM_SSL_PRIVATE_H + +#define MAILSTREAM_SSL_PRIVATE_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern void mailstream_ssl_init_lock(void); + +extern void mailstream_ssl_uninit_lock(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailstream_types.h b/Sources/libetpan/include/mailstream_types.h new file mode 100644 index 00000000..271d3f74 --- /dev/null +++ b/Sources/libetpan/include/mailstream_types.h @@ -0,0 +1,137 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream_types.h,v 1.17 2011/04/19 12:22:17 hoa Exp $ + */ + +#ifndef MAILSTREAM_TYPES_H + +#define MAILSTREAM_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define LIBETPAN_MAILSTREAM_DEBUG +#ifndef LIBETPAN_CONFIG_H +# include "libetpan-config.h" +#endif +#include "carray.h" + +struct _mailstream; + +typedef struct _mailstream mailstream; + +struct _mailstream_low; + +typedef struct _mailstream_low mailstream_low; + +enum { + /* Buffer is a log text string. */ + MAILSTREAM_LOG_TYPE_INFO_RECEIVED, + MAILSTREAM_LOG_TYPE_INFO_SENT, + + /* Buffer is data sent over the network. */ + MAILSTREAM_LOG_TYPE_ERROR_PARSE, + MAILSTREAM_LOG_TYPE_ERROR_RECEIVED, /* no data */ + MAILSTREAM_LOG_TYPE_ERROR_SENT, /* no data */ + + /* Buffer is data sent over the network. */ + MAILSTREAM_LOG_TYPE_DATA_RECEIVED, + MAILSTREAM_LOG_TYPE_DATA_SENT, + MAILSTREAM_LOG_TYPE_DATA_SENT_PRIVATE, /* data is private, for example a password. */ +}; + +struct _mailstream { + size_t buffer_max_size; + + char * write_buffer; + size_t write_buffer_len; + + char * read_buffer; + size_t read_buffer_len; + + mailstream_low * low; + + struct mailstream_cancel * idle; + int idling; + void (* logger)(mailstream * s, int log_type, + const char * str, size_t size, void * logger_context); + void * logger_context; +}; + +struct mailstream_low_driver { + ssize_t (* mailstream_read)(mailstream_low *, void *, size_t); + ssize_t (* mailstream_write)(mailstream_low *, const void *, size_t); + int (* mailstream_close)(mailstream_low *); + int (* mailstream_get_fd)(mailstream_low *); + void (* mailstream_free)(mailstream_low *); + void (* mailstream_cancel)(mailstream_low *); + struct mailstream_cancel * (* mailstream_get_cancel)(mailstream_low *); + /* Returns an array of MMAPString containing DER data or NULL if it's not a SSL connection */ + carray * (* mailstream_get_certificate_chain)(mailstream_low *); + /* Will be called from the main thread */ + int (* mailstream_setup_idle)(mailstream_low *); + int (* mailstream_unsetup_idle)(mailstream_low *); + int (* mailstream_interrupt_idle)(mailstream_low *); +}; + +typedef struct mailstream_low_driver mailstream_low_driver; + +struct _mailstream_low { + void * data; + mailstream_low_driver * driver; + int privacy; + char * identifier; + unsigned long timeout; /* in seconds, 0 will use the global value */ + void (* logger)(mailstream_low * s, int log_type, + const char * str, size_t size, void * logger_context); + void * logger_context; +}; + +typedef void progress_function(size_t current, size_t maximum); + +typedef void mailprogress_function(size_t current, size_t maximum, void * context); + +enum { + MAILSTREAM_IDLE_ERROR, + MAILSTREAM_IDLE_INTERRUPTED, + MAILSTREAM_IDLE_HASDATA, + MAILSTREAM_IDLE_TIMEOUT, + MAILSTREAM_IDLE_CANCELLED +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailthread.h b/Sources/libetpan/include/mailthread.h new file mode 100644 index 00000000..59ae7d52 --- /dev/null +++ b/Sources/libetpan/include/mailthread.h @@ -0,0 +1,111 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailthread.h,v 1.15 2007/12/10 21:32:59 hoa Exp $ + */ + +#ifndef MAILTHREAD_H + +#define MAILTHREAD_H + +#include "mailthread_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mail_build_thread constructs a tree with the message using the + given style. + + @param type is the type of threading to apply, the value can be + MAIL_THREAD_REFERENCES, MAIL_THREAD_REFERENCES_NO_SUBJECT, + MAIL_THREAD_ORDEREDSUBJECT or MAIL_THREAD_NONE, + + @param default_from is the default charset to use whenever the + subject is not tagged with a charset. "US-ASCII" can be used + if you don't know what to use. + + @param env_list is the message list (with header fields fetched) + to use to build the message tree. + + @param result * result) will contain the resulting message tree. + + @param if comp_func is NULL, no sorting algorithm is used. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mail_build_thread(int type, char * default_from, + struct mailmessage_list * env_list, + struct mailmessage_tree ** result, + int (* comp_func)(struct mailmessage_tree **, + struct mailmessage_tree **)); + +/* + mail_thread_sort sort the messages in the message tree, using the + given sort function. + + @param tree is the message tree to sort. + + @param comp_func is the sort function to use (this is the same kind of + functions than those used for qsort()). mailthread_tree_timecomp can be + used for default sort. + + @param sort_sub if this value is 0, only the children of the root message + are sorted. +*/ + +LIBETPAN_EXPORT +int mail_thread_sort(struct mailmessage_tree * tree, + int (* comp_func)(struct mailmessage_tree **, + struct mailmessage_tree **), + int sort_sub); + +/* + mailthread_tree_timecomp is the default sort function. + + The message are compared by date, then by message numbers. + The tree are given in (* ptree1) and (* ptree2). +*/ + +LIBETPAN_EXPORT +int mailthread_tree_timecomp(struct mailmessage_tree ** ptree1, + struct mailmessage_tree ** ptree2); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mailthread_types.h b/Sources/libetpan/include/mailthread_types.h new file mode 100644 index 00000000..c0b9b0cf --- /dev/null +++ b/Sources/libetpan/include/mailthread_types.h @@ -0,0 +1,64 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailthread_types.h,v 1.9 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifndef MAILTHREAD_TYPES_H + +#define MAILTHREAD_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "maildriver_types.h" +#include "mailmessage_types.h" + +/* + This is the type of tree construction to apply. +*/ + +enum { + MAIL_THREAD_REFERENCES, /* this is threading using + References fields only) */ + MAIL_THREAD_REFERENCES_NO_SUBJECT, /* this is threading using References + fields, then subject */ + MAIL_THREAD_ORDEREDSUBJECT, /* this is threading using only subject */ + MAIL_THREAD_NONE /* no thread */ +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mboxdriver.h b/Sources/libetpan/include/mboxdriver.h new file mode 100644 index 00000000..38e4b55a --- /dev/null +++ b/Sources/libetpan/include/mboxdriver.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver.h,v 1.14 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MBOXDRIVER_H + +#define MBOXDRIVER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mboxdriver_types.h" + +extern mailsession_driver * mbox_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mboxdriver_cached.h b/Sources/libetpan/include/mboxdriver_cached.h new file mode 100644 index 00000000..c502a942 --- /dev/null +++ b/Sources/libetpan/include/mboxdriver_cached.h @@ -0,0 +1,54 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver_cached.h,v 1.11 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MBOXDRIVER_CACHED_H + +#define MBOXDRIVER_CACHED_H + +#include "libetpan-config.h" + +#include "mboxdriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * mbox_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mboxdriver_cached_message.h b/Sources/libetpan/include/mboxdriver_cached_message.h new file mode 100644 index 00000000..681568ac --- /dev/null +++ b/Sources/libetpan/include/mboxdriver_cached_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver_cached_message.h,v 1.6 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MBOXDRIVER_CACHED_MESSAGE_H + +#define MBOXDRIVER_CACHED_MESSAGE_H + +#include "mailmessage.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * mbox_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mboxdriver_message.h b/Sources/libetpan/include/mboxdriver_message.h new file mode 100644 index 00000000..95a0b5d6 --- /dev/null +++ b/Sources/libetpan/include/mboxdriver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver_message.h,v 1.6 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MBOXDRIVER_MESSAGE_H + +#define MBOXDRIVER_MESSAGE_H + +#include "mboxdriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * mbox_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mboxdriver_types.h b/Sources/libetpan/include/mboxdriver_types.h new file mode 100644 index 00000000..4b246171 --- /dev/null +++ b/Sources/libetpan/include/mboxdriver_types.h @@ -0,0 +1,107 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver_types.h,v 1.7 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifndef MBOXDRIVER_TYPES_H + +#define MBOXDRIVER_TYPES_H + +#include "maildriver_types.h" +#include "mailmbox.h" +#include "mailstorage_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* mbox driver */ + +enum { + MBOXDRIVER_SET_READ_ONLY = 1, + MBOXDRIVER_SET_NO_UID +}; + +struct mbox_session_state_data { + struct mailmbox_folder * mbox_folder; + int mbox_force_read_only; + int mbox_force_no_uid; +}; + +/* cached version */ + +enum { + /* the mapping of the parameters should be the same as for mbox */ + MBOXDRIVER_CACHED_SET_READ_ONLY = 1, + MBOXDRIVER_CACHED_SET_NO_UID, + /* cache specific */ + MBOXDRIVER_CACHED_SET_CACHE_DIRECTORY, + MBOXDRIVER_CACHED_SET_FLAGS_DIRECTORY +}; + +struct mbox_cached_session_state_data { + mailsession * mbox_ancestor; + char * mbox_quoted_mb; + char mbox_cache_directory[PATH_MAX]; + char mbox_flags_directory[PATH_MAX]; + struct mail_flags_store * mbox_flags_store; +}; + +/* mbox storage */ + +/* + mbox_mailstorage is the state data specific to the mbox storage. + + - pathname is the filename that contains the mailbox. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache. + + - flags_directory is the location of the flags. +*/ + +struct mbox_mailstorage { + char * mbox_pathname; + + int mbox_cached; + char * mbox_cache_directory; + char * mbox_flags_directory; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mboxstorage.h b/Sources/libetpan/include/mboxstorage.h new file mode 100644 index 00000000..c1fbd329 --- /dev/null +++ b/Sources/libetpan/include/mboxstorage.h @@ -0,0 +1,70 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxstorage.h,v 1.8 2006/06/02 15:44:29 smarinier Exp $ + */ + +#ifndef MBOXSTORAGE_H + +#define MBOXSTORAGE_H + +#include "mboxdriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mbox_mailstorage_init is the constructor for a mbox storage. + + @param storage this is the storage to initialize. + + @param pathname is the filename that contains the mailbox. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache + + @param flags_directory is the location of the flags +*/ + +LIBETPAN_EXPORT +int mbox_mailstorage_init(struct mailstorage * storage, + const char * mb_pathname, int mb_cached, + const char * mb_cache_directory, const char * mb_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/md5.h b/Sources/libetpan/include/md5.h new file mode 100644 index 00000000..219b7712 --- /dev/null +++ b/Sources/libetpan/include/md5.h @@ -0,0 +1,88 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: md5.h,v 1.11 2006/06/02 15:44:29 smarinier Exp $ + */ + +/* MD5.H - header file for MD5C.C + */ + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. +These notices must be retained in any copies of any part of this +documentation and/or software. + */ + +#include "md5global.h" + +#ifndef MD5_H + +#define MD5_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* MD5 context. */ +typedef struct { + UINT4 state[4]; /* state (ABCD) */ + UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ + unsigned char buffer[64]; /* input buffer */ +} MD5_CTX; + +void MD5Init PROTO_LIST ((MD5_CTX *)); +void MD5Update PROTO_LIST + ((MD5_CTX *, const unsigned char *, unsigned int)); +void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *)); + +void hmac_md5 PROTO_LIST ((const unsigned char *, int, const unsigned char *, int, unsigned char *)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/md5global.h b/Sources/libetpan/include/md5global.h new file mode 100644 index 00000000..aed23d2b --- /dev/null +++ b/Sources/libetpan/include/md5global.h @@ -0,0 +1,82 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: md5global.h,v 1.7 2006/06/02 15:44:29 smarinier Exp $ + */ + +/* GLOBAL.H - RSAREF types and constants + */ + +#ifndef MD5GLOBAL_H + +#define MD5GLOBAL_H + +#include "md5namespace.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* PROTOTYPES should be set to one if and only if the compiler supports + function argument prototyping. +The following makes PROTOTYPES default to 0 if it has not already + been defined with C compiler flags. + */ +#ifndef PROTOTYPES +#define PROTOTYPES 1 +#endif + +/* POINTER defines a generic pointer type */ +typedef unsigned char *POINTER; +typedef const unsigned char *CONST_POINTER; + +/* UINT2 defines a two byte word */ +typedef unsigned short int UINT2; + +/* UINT4 defines a four byte word */ +typedef unsigned long int UINT4; + +/* PROTO_LIST is defined depending on how PROTOTYPES is defined above. +If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it + returns an empty list. + */ +#if PROTOTYPES +#define PROTO_LIST(list) list +#else +#define PROTO_LIST(list) () +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/md5namespace.h b/Sources/libetpan/include/md5namespace.h new file mode 100644 index 00000000..633fbdc8 --- /dev/null +++ b/Sources/libetpan/include/md5namespace.h @@ -0,0 +1,45 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2015 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef MD5NAMESPACE_H + +#define MD5NAMESPACE_H + +#define MD5Init lep_MD5Init +#define MD5Update lep_MD5Update +#define MD5Final lep_MD5Final +#define hmac_md5 lep_hmac_md5 +#define hmac_md5_init lep_hmac_md5_init +#define hmac_md5_precalc lep_hmac_md5_precalc +#define hmac_md5_import lep_hmac_md5_import +#define hmac_md5_final lep_hmac_md5_final + +#endif diff --git a/Sources/libetpan/include/mhdriver.h b/Sources/libetpan/include/mhdriver.h new file mode 100644 index 00000000..3a6ee96a --- /dev/null +++ b/Sources/libetpan/include/mhdriver.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver.h,v 1.12 2004/11/21 21:53:33 hoa Exp $ + */ + +#ifndef MHDRIVER_H + +#define MHDRIVER_H + +#include "maildriver.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * mh_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mhdriver_cached.h b/Sources/libetpan/include/mhdriver_cached.h new file mode 100644 index 00000000..48823d95 --- /dev/null +++ b/Sources/libetpan/include/mhdriver_cached.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver_cached.h,v 1.10 2004/11/21 21:53:33 hoa Exp $ + */ + +#ifndef MHDRIVER_CACHED_H + +#define MHDRIVER_CACHED_H + +#include "mhdriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * mh_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mhdriver_cached_message.h b/Sources/libetpan/include/mhdriver_cached_message.h new file mode 100644 index 00000000..143a01cd --- /dev/null +++ b/Sources/libetpan/include/mhdriver_cached_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver_cached_message.h,v 1.6 2004/11/21 21:53:33 hoa Exp $ + */ + +#ifndef MHDRIVER_CACHED_MESSAGE_H + +#define MHDRIVER_CACHED_MESSAGE_H + +#include "mhdriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * mh_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mhdriver_message.h b/Sources/libetpan/include/mhdriver_message.h new file mode 100644 index 00000000..a73c8670 --- /dev/null +++ b/Sources/libetpan/include/mhdriver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver_message.h,v 1.6 2004/11/21 21:53:33 hoa Exp $ + */ + +#ifndef MHDRIVER_MESSAGE_H + +#define MHDRIVER_MESSAGE_H + +#include "mhdriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * mh_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mhdriver_types.h b/Sources/libetpan/include/mhdriver_types.h new file mode 100644 index 00000000..dff1ee12 --- /dev/null +++ b/Sources/libetpan/include/mhdriver_types.h @@ -0,0 +1,100 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver_types.h,v 1.8 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifndef MHDRIVER_TYPES_H + +#define MHDRIVER_TYPES_H + +#include "libetpan-config.h" + +#include "maildriver_types.h" +#include "mailmh.h" +#include "clist.h" +#include "generic_cache_types.h" +#include "mailstorage_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct mh_session_state_data { + struct mailmh * mh_session; + + struct mailmh_folder * mh_cur_folder; + + clist * mh_subscribed_list; +}; + +enum { + MHDRIVER_CACHED_SET_CACHE_DIRECTORY = 1, + MHDRIVER_CACHED_SET_FLAGS_DIRECTORY +}; + +struct mh_cached_session_state_data { + mailsession * mh_ancestor; + char * mh_quoted_mb; + char mh_cache_directory[PATH_MAX]; + char mh_flags_directory[PATH_MAX]; + struct mail_flags_store * mh_flags_store; +}; + +/* mh storage */ + +/* + mh_mailstorage is the state data specific to the MH storage. + + - pathname is the root path of the MH storage. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache. + + - flags_directory is the location of the flags. +*/ + +struct mh_mailstorage { + char * mh_pathname; + + int mh_cached; + char * mh_cache_directory; + char * mh_flags_directory; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mhstorage.h b/Sources/libetpan/include/mhstorage.h new file mode 100644 index 00000000..4530289a --- /dev/null +++ b/Sources/libetpan/include/mhstorage.h @@ -0,0 +1,68 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhstorage.h,v 1.8 2006/06/02 15:44:29 smarinier Exp $ + */ + +#ifndef MHSTORAGE_H + +#define MHSTORAGE_H + +#include "mhdriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mh_mailstorage_init is the constructor for a MH storage + + @param pathname is the filename the root path of the MH storage. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache. + + @param flags_directory is the location of the flags. +*/ + +LIBETPAN_EXPORT +int mh_mailstorage_init(struct mailstorage * storage, + const char * mh_pathname, int mh_cached, + const char * mh_cache_directory, const char * mh_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/mime_message_driver.h b/Sources/libetpan/include/mime_message_driver.h new file mode 100644 index 00000000..66751dbb --- /dev/null +++ b/Sources/libetpan/include/mime_message_driver.h @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mime_message_driver.h,v 1.5 2004/12/13 23:18:28 hoa Exp $ + */ + +#ifndef MIME_MESSAGE_DRIVER_H + +#define MIME_MESSAGE_DRIVER_H + +#include "mailmessage.h" + +#define LIBETPAN_MIME_MESSAGE + +extern mailmessage_driver * mime_message_driver; + +mailmessage * mime_message_init(struct mailmime * mime); + +void mime_message_detach_mime(mailmessage * msg); + +/* deprecated */ +int mime_message_set_tmpdir(mailmessage * msg, char * tmpdir); + +#endif diff --git a/Sources/libetpan/include/mmapstring.h b/Sources/libetpan/include/mmapstring.h new file mode 100644 index 00000000..bd985720 --- /dev/null +++ b/Sources/libetpan/include/mmapstring.h @@ -0,0 +1,161 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mmapstring.h,v 1.14 2008/02/28 14:06:27 colinleroy Exp $ + */ + +#ifndef __MMAP_STRING_H__ + +#define __MMAP_STRING_H__ + +#include "sys/types.h" + +#ifndef LIBETPAN_CONFIG_H +# include "libetpan-config.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* +#define TMPDIR "/tmp" +*/ + +typedef struct _MMAPString MMAPString; + +struct _MMAPString +{ + char * str; + size_t len; + size_t allocated_len; + int fd; + size_t mmapped_size; + /* + char * old_non_mmapped_str; + */ +}; + +/* configure location of mmaped files */ + +LIBETPAN_EXPORT +void mmap_string_set_tmpdir(const char * directory); + +/* Strings + */ +LIBETPAN_EXPORT +MMAPString * mmap_string_new (const char * init); + +LIBETPAN_EXPORT +MMAPString * mmap_string_new_len (const char * init, + size_t len); + +LIBETPAN_EXPORT +MMAPString * mmap_string_sized_new (size_t dfl_size); + +LIBETPAN_EXPORT +void mmap_string_free (MMAPString * string); + +LIBETPAN_EXPORT +MMAPString * mmap_string_assign (MMAPString * string, + const char * rval); + +LIBETPAN_EXPORT +MMAPString * mmap_string_truncate (MMAPString *string, + size_t len); + +LIBETPAN_EXPORT +MMAPString * mmap_string_set_size (MMAPString * string, + size_t len); + +LIBETPAN_EXPORT +MMAPString * mmap_string_insert_len (MMAPString * string, + size_t pos, + const char * val, + size_t len); + +LIBETPAN_EXPORT +MMAPString * mmap_string_append (MMAPString * string, + const char * val); + +LIBETPAN_EXPORT +MMAPString * mmap_string_append_len (MMAPString * string, + const char * val, + size_t len); + +LIBETPAN_EXPORT +MMAPString * mmap_string_append_c (MMAPString * string, + char c); + +LIBETPAN_EXPORT +MMAPString * mmap_string_prepend (MMAPString * string, + const char * val); + +LIBETPAN_EXPORT +MMAPString * mmap_string_prepend_c (MMAPString * string, + char c); + +LIBETPAN_EXPORT +MMAPString * mmap_string_prepend_len (MMAPString * string, + const char * val, + size_t len); + +LIBETPAN_EXPORT +MMAPString * mmap_string_insert (MMAPString * string, + size_t pos, + const char * val); + +LIBETPAN_EXPORT +MMAPString * mmap_string_insert_c (MMAPString *string, + size_t pos, + char c); + +LIBETPAN_EXPORT +MMAPString * mmap_string_erase(MMAPString * string, + size_t pos, + size_t len); + +LIBETPAN_EXPORT +void mmap_string_set_ceil(size_t ceil); + +LIBETPAN_EXPORT +int mmap_string_ref(MMAPString * string); + +LIBETPAN_EXPORT +int mmap_string_unref(char * str); + +#ifdef __cplusplus +} +#endif + + +#endif /* __MMAP_STRING_H__ */ diff --git a/Sources/libetpan/include/mmapstring_private.h b/Sources/libetpan/include/mmapstring_private.h new file mode 100644 index 00000000..1dd6c207 --- /dev/null +++ b/Sources/libetpan/include/mmapstring_private.h @@ -0,0 +1,48 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MMAPSTRING_PRIVATE_H + +#define MMAPSTRING_PRIVATE_H + +#ifdef __cplusplus +extern "C" +{ +#endif + + extern void mmapstring_init_lock(void); + + extern void mmapstring_uninit_lock(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/namespace.h b/Sources/libetpan/include/namespace.h new file mode 100644 index 00000000..ea33e9fc --- /dev/null +++ b/Sources/libetpan/include/namespace.h @@ -0,0 +1,57 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2011 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef NAMESPACE_H + +#define NAMESPACE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "libetpan-config.h" +#include "namespace_types.h" +#include "mailimap_extension.h" + +LIBETPAN_EXPORT +extern struct mailimap_extension_api mailimap_extension_namespace; + +LIBETPAN_EXPORT +int mailimap_namespace(mailimap * session, struct mailimap_namespace_data ** result); + +LIBETPAN_EXPORT +int mailimap_has_namespace(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/namespace_parser.h b/Sources/libetpan/include/namespace_parser.h new file mode 100644 index 00000000..9be2f501 --- /dev/null +++ b/Sources/libetpan/include/namespace_parser.h @@ -0,0 +1,55 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2011 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + + +#ifndef NAMESPACE_PARSER_H + +#define NAMESPACE_PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_parser.h" +#include "namespace_types.h" + +int +mailimap_namespace_extension_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, progress_function * progr_fun); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/namespace_sender.h b/Sources/libetpan/include/namespace_sender.h new file mode 100644 index 00000000..bb95b277 --- /dev/null +++ b/Sources/libetpan/include/namespace_sender.h @@ -0,0 +1,48 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef NAMESPACE_SENDER_H + +#define NAMESPACE_SENDER_H + +#include "mailimap_sender.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int mailimap_namespace_send(mailstream * fd); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/namespace_types.h b/Sources/libetpan/include/namespace_types.h new file mode 100644 index 00000000..462dd340 --- /dev/null +++ b/Sources/libetpan/include/namespace_types.h @@ -0,0 +1,93 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef NAMESPACE_TYPES_H + +#define NAMESPACE_TYPES_H + +#include "clist.h" + +enum { + MAILIMAP_NAMESPACE_TYPE_NAMESPACE +}; + +struct mailimap_namespace_response_extension { + char * ns_name; /* != NULL */ + clist * ns_values; /* != NULL, list of char * */ +}; + +LIBETPAN_EXPORT +struct mailimap_namespace_response_extension * +mailimap_namespace_response_extension_new(char * name, + clist * values); + +LIBETPAN_EXPORT +void mailimap_namespace_response_extension_free(struct mailimap_namespace_response_extension * ext); + +struct mailimap_namespace_info { + char * ns_prefix; /* != NULL */ + char ns_delimiter; + clist * ns_extensions; /* can be NULL, list of mailimap_namespace_response_extension */ +}; + +LIBETPAN_EXPORT +struct mailimap_namespace_info * mailimap_namespace_info_new(char * prefix, char delimiter, + clist * extensions); + +LIBETPAN_EXPORT +void mailimap_namespace_info_free(struct mailimap_namespace_info * info); + +struct mailimap_namespace_item { + clist * ns_data_list; /* != NULL, list of mailimap_namespace_info */ +}; + +LIBETPAN_EXPORT +struct mailimap_namespace_item * mailimap_namespace_item_new(clist * data_list); + +LIBETPAN_EXPORT +void mailimap_namespace_item_free(struct mailimap_namespace_item * item); + +struct mailimap_namespace_data { + struct mailimap_namespace_item * ns_personal; /* can be NULL */ + struct mailimap_namespace_item * ns_other; /* can be NULL */ + struct mailimap_namespace_item * ns_shared; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_namespace_data * +mailimap_namespace_data_new(struct mailimap_namespace_item * personal, + struct mailimap_namespace_item * other, + struct mailimap_namespace_item * shared); + +LIBETPAN_EXPORT +void mailimap_namespace_data_free(struct mailimap_namespace_data * ns); + +#endif diff --git a/Sources/libetpan/include/newsfeed.h b/Sources/libetpan/include/newsfeed.h new file mode 100644 index 00000000..92708700 --- /dev/null +++ b/Sources/libetpan/include/newsfeed.h @@ -0,0 +1,76 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * Copyright (C) 2006 Andrej Kacian + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef NEWSFEED_H +#define NEWSFEED_H + +#include "newsfeed_types.h" +#include "newsfeed_item.h" +#include "newsfeed_item_enclosure.h" + +struct newsfeed * newsfeed_new(void); +void newsfeed_free(struct newsfeed * feed); + +int newsfeed_get_response_code(struct newsfeed * feed); + +int newsfeed_set_url(struct newsfeed * feed, const char * url); +const char * newsfeed_get_url(struct newsfeed * feed); + +int newsfeed_set_title(struct newsfeed * feed, const char * title); +const char * newsfeed_get_title(struct newsfeed * feed); + +int newsfeed_set_description(struct newsfeed * feed, const char * description); +const char * newsfeed_get_description(struct newsfeed * feed); + +int newsfeed_set_language(struct newsfeed * feed, const char * language); +const char * newsfeed_get_language(struct newsfeed * feed); + +int newsfeed_set_author(struct newsfeed * feed, const char * author); +const char * newsfeed_get_author(struct newsfeed * feed); + +int newsfeed_set_generator(struct newsfeed * feed, const char * generator); +const char * newsfeed_get_generator(struct newsfeed * feed); + +unsigned int newsfeed_item_list_get_count(struct newsfeed * feed); +struct newsfeed_item * newsfeed_get_item(struct newsfeed * feed, unsigned int n); + +void newsfeed_set_date(struct newsfeed * feed, time_t date); +time_t newsfeed_get_date(struct newsfeed * feed); + +void newsfeed_set_timeout(struct newsfeed * feed, unsigned int timeout); +unsigned int newsfeed_get_timeout(struct newsfeed * feed); + +int newsfeed_add_item(struct newsfeed * feed, struct newsfeed_item * item); + +int newsfeed_update(struct newsfeed * feed, time_t last_update); + +#endif /* NEWSFEED_H */ diff --git a/Sources/libetpan/include/newsfeed_item.h b/Sources/libetpan/include/newsfeed_item.h new file mode 100644 index 00000000..aa43e186 --- /dev/null +++ b/Sources/libetpan/include/newsfeed_item.h @@ -0,0 +1,71 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * Copyright (C) 2006 Andrej Kacian + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef NEWSFEED_ITEM_H +#define NEWSFEED_ITEM_H + +#include "newsfeed_types.h" + +struct newsfeed_item * newsfeed_item_new(struct newsfeed * feed); +void newsfeed_item_free(struct newsfeed_item * item); + +struct newsfeed * newsfeed_item_get_feed(struct newsfeed_item * item); + +const char * newsfeed_item_get_url(struct newsfeed_item * item); +int newsfeed_item_set_url(struct newsfeed_item * item, const char * url); + +const char * newsfeed_item_get_title(struct newsfeed_item * item); +int newsfeed_item_set_title(struct newsfeed_item * item, const char * title); + +const char * newsfeed_item_get_summary(struct newsfeed_item * item); +int newsfeed_item_set_summary(struct newsfeed_item * item, const char * summary); + +const char * newsfeed_item_get_text(struct newsfeed_item * item); +int newsfeed_item_set_text(struct newsfeed_item * item, const char * text); + +const char * newsfeed_item_get_author(struct newsfeed_item * item); +int newsfeed_item_set_author(struct newsfeed_item * item, const char * author); + +const char * newsfeed_item_get_id(struct newsfeed_item * item); +int newsfeed_item_set_id(struct newsfeed_item * item, const char * id); + +time_t newsfeed_item_get_date_published(struct newsfeed_item * item); +void newsfeed_item_set_date_published(struct newsfeed_item * item, time_t date); + +time_t newsfeed_item_get_date_modified(struct newsfeed_item * item); +void newsfeed_item_set_date_modified(struct newsfeed_item * item, time_t date); + +struct newsfeed_item_enclosure * newsfeed_item_get_enclosure(struct newsfeed_item * item); +void newsfeed_item_set_enclosure(struct newsfeed_item * item, + struct newsfeed_item_enclosure * enclosure); + +#endif /* __FEEDITEM_H */ diff --git a/Sources/libetpan/include/newsfeed_item_enclosure.h b/Sources/libetpan/include/newsfeed_item_enclosure.h new file mode 100644 index 00000000..705ff678 --- /dev/null +++ b/Sources/libetpan/include/newsfeed_item_enclosure.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef NEWSFEED_ITEM_ENCLOSURE_H + +#define NEWSFEED_ITEM_ENCLOSURE_H + +#include "newsfeed_types.h" + +struct newsfeed_item_enclosure * newsfeed_item_enclosure_new(void); +void newsfeed_item_enclosure_free(struct newsfeed_item_enclosure * enclosure); + +char * newsfeed_item_enclosure_get_url(struct newsfeed_item_enclosure * enclosure); +int newsfeed_item_enclosure_set_url(struct newsfeed_item_enclosure * enclosure, + const char * url); + +char * newsfeed_item_enclosure_get_type(struct newsfeed_item_enclosure * enclosure); +int newsfeed_item_enclosure_set_type(struct newsfeed_item_enclosure * enclosure, + const char * type); + +size_t newsfeed_item_enclosure_get_size(struct newsfeed_item_enclosure * enclosure); +void newsfeed_item_enclosure_set_size(struct newsfeed_item_enclosure * enclosure, + size_t size); + +#endif diff --git a/Sources/libetpan/include/newsfeed_private.h b/Sources/libetpan/include/newsfeed_private.h new file mode 100644 index 00000000..2c6ba2c9 --- /dev/null +++ b/Sources/libetpan/include/newsfeed_private.h @@ -0,0 +1,59 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef NEWSFEED_PRIVATE_H + +#define NEWSFEED_PRIVATE_H + +#include "newsfeed_types.h" +#include "mmapstring.h" + +#ifdef HAVE_EXPAT +#include +#endif + +struct newsfeed_parser_context { + unsigned int depth; + unsigned int location; + MMAPString *str; + + struct newsfeed * feed; + struct newsfeed_item * curitem; + + int error; + +#ifdef HAVE_EXPAT + void * parser; +#endif +}; + +time_t newsfeed_rfc822_date_parse(char * text); + +#endif diff --git a/Sources/libetpan/include/newsfeed_types.h b/Sources/libetpan/include/newsfeed_types.h new file mode 100644 index 00000000..d549b388 --- /dev/null +++ b/Sources/libetpan/include/newsfeed_types.h @@ -0,0 +1,96 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef NEWSFEED_TYPES_H + +#define NEWSFEED_TYPES_H + +#include "carray.h" +#include "sys/types.h" + +enum { + NEWSFEED_NO_ERROR = 0, + NEWSFEED_ERROR_CANCELLED, + NEWSFEED_ERROR_INTERNAL, + NEWSFEED_ERROR_BADURL, + NEWSFEED_ERROR_RESOLVE_PROXY, + NEWSFEED_ERROR_RESOLVE_HOST, + NEWSFEED_ERROR_CONNECT, + NEWSFEED_ERROR_STREAM, + NEWSFEED_ERROR_PROTOCOL, + NEWSFEED_ERROR_PARSE, + NEWSFEED_ERROR_ACCESS, + NEWSFEED_ERROR_AUTHENTICATION, + NEWSFEED_ERROR_FTP, + NEWSFEED_ERROR_PARTIAL_FILE, + NEWSFEED_ERROR_FETCH, + NEWSFEED_ERROR_HTTP, + NEWSFEED_ERROR_FILE, + NEWSFEED_ERROR_PUT, + NEWSFEED_ERROR_MEMORY, + NEWSFEED_ERROR_SSL, + NEWSFEED_ERROR_LDAP, + NEWSFEED_ERROR_UNSUPPORTED_PROTOCOL +}; + +struct newsfeed { + char * feed_url; + char * feed_title; + char * feed_description; + char * feed_language; + char * feed_author; + char * feed_generator; + time_t feed_date; + carray * feed_item_list; + int feed_response_code; + + unsigned int feed_timeout; +}; + +struct newsfeed_item { + char * fi_url; + char * fi_title; + char * fi_summary; + char * fi_text; + char * fi_author; + char * fi_id; + time_t fi_date_published; + time_t fi_date_modified; + struct newsfeed * fi_feed; /* owner */ + struct newsfeed_item_enclosure * fi_enclosure; +}; + +struct newsfeed_item_enclosure { + char * fie_url; + char * fie_type; + size_t fie_size; +}; + +#endif diff --git a/Sources/libetpan/include/newsnntp.h b/Sources/libetpan/include/newsnntp.h new file mode 100644 index 00000000..8dddcf2c --- /dev/null +++ b/Sources/libetpan/include/newsnntp.h @@ -0,0 +1,695 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: newsnntp.h,v 1.21 2008/02/20 22:15:53 hoa Exp $ + */ + +#ifndef NEWSNNTP_H + +#define NEWSNNTP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_INTTYPES_H +# include +#endif +#include "sys/types.h" +#include "time.h" + +#include "clist.h" +#include "mailstream.h" +#include "newsnntp_socket.h" +#include "newsnntp_ssl.h" +#include "newsnntp_types.h" + +/* + newsnntp_new() + + This function returns a new NNTP session. + + @param progr_rate When downloading messages, a function will be called + each time the amount of bytes downloaded reaches a multiple of this + value, this can be 0. + @param progr_fun This is the function to call to notify the progress, + this can be NULL. + + @return an NNTP session is returned. +*/ + +LIBETPAN_EXPORT +newsnntp * newsnntp_new(size_t nntp_progr_rate, + progress_function * nntp_progr_fun); + +/* + newsnntp_free() + + This function will free the data structures associated with + the NNTP session. + + @param session NNTP session +*/ + +LIBETPAN_EXPORT +void newsnntp_free(newsnntp * session); + +/* + newsnntp_set_logger() set a logger for the connection. + + @param session NNTP session + @param logger logger function. See mailstream_types.h to know possible log_type values. + str is the log, data received or data sent. + @param logger_context parameter that is passed to the logger function. + @return the value of the timeout in seconds. +*/ + +LIBETPAN_EXPORT +void newsnntp_set_logger(newsnntp * session, void (* logger)(newsnntp * session, int log_type, + const char * str, size_t size, void * context), void * logger_context); + +/* + newsnntp_set_progress_callback() set NNTP progression callbacks. + + @param session NNTP session + @param progr_fun callback function. +*/ + +LIBETPAN_EXPORT +void newsnntp_set_progress_callback(newsnntp * f, mailprogress_function * progr_fun, void * context); + +/* + newsnntp_set_timeout() set the network timeout of the NNTP session. + + @param session NNTP session + @param timeout value of the timeout in seconds. +*/ + +LIBETPAN_EXPORT +void newsnntp_set_timeout(newsnntp * session, time_t timeout); + +/* + newsnntp_get_timeout() get the network timeout of the NNTP session. + + @param session NNTP session + + @return value of the timeout in seconds. +*/ + +LIBETPAN_EXPORT +time_t newsnntp_get_timeout(newsnntp * session); + +/* + newsnntp_connect() + + This function will connect the NNTP session with the given stream. + + @param session the NNTP session + @param s stream to use + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_connect(newsnntp * session, mailstream * s); + +/* + newsnntp_quit() disconnect the NNTP session. + + @param session NNTP session + */ + +LIBETPAN_EXPORT +int newsnntp_quit(newsnntp * session); + +/* + newsnntp_head() fetch the headers of an article. + + @param session NNTP session + @param indx index of the article to fetch. + @param result the header data. + @param result_len the length of the result data. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_head(newsnntp * session, uint32_t indx, + char ** result, size_t * result_len); + +/* + newsnntp_head_free() + + This function will free the data associated with an NNTP + article header. + + @param str header data. +*/ + +LIBETPAN_EXPORT +void newsnntp_head_free(char * str); + +/* + newsnntp_article() fetch the header and contents of an article. + + @param session NNTP session + @param indx index of the article to fetch. + @param result the article data. + @param result_len the length of the result data. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_article(newsnntp * session, uint32_t indx, + char ** result, size_t * result_len); + +/* + newsnntp_article_by_message_id() fetch the header and contents + of an article by message id. + + @param session NNTP session + @param msg_id ID of the article to fetch. + @param result The article data. + @param result_len The length of the result data. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_article_by_message_id(newsnntp * session, char * msg_id, + char ** result, size_t * result_len); + +/* + newsnntp_article_free() + + This function will free the data associated with an NNTP + article. + + @param str article data. +*/ + +LIBETPAN_EXPORT +void newsnntp_article_free(char * str); + +/* + newsnntp_body() fetch the contents of an article. + + @param session NNTP session + @param indx index of the article to fetch. + @param result body data. + @param result_len length of the result data. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_body(newsnntp * session, uint32_t indx, + char ** result, size_t * result_len); + +/* + newsnntp_body_free() + + This function will free the data associated with an NNTP + article body. + + @param str article body data. +*/ + +LIBETPAN_EXPORT +void newsnntp_body_free(char * str); + +/* + newsnntp_mode_reader() switch the mode of the server to + reader mode. + + @param session NNTP session + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_mode_reader(newsnntp * session); + +/* + newsnntp_date() fetches the current Coordinated Universal + Time from the server's perspective. + + @param session NNTP session + @param tm server's current time. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_date(newsnntp * session, struct tm * tm); + +/* + newsnntp_authinfo_username() sets the session's username. + + @param session NNTP session + @param username username. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_authinfo_username(newsnntp * session, const char * username); + +/* + newsnntp_authinfo_password() sets the session's password. + + @param session NNTP session + @param username password. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_authinfo_password(newsnntp * session, const char * password); + +/* + newsnntp_post() posts a message to a newsgroup. + + @param session NNTP session + @param message the message data. + @param size the size of the message. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_post(newsnntp * session, const char * message, size_t size); + + + +/******************* requests ******************************/ + +/* + newsnntp_group() select a newsgroup and fetch info about it. + + @param session NNTP session + @param groupname name of the newsgroup. + @param info information about the group. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_group(newsnntp * session, const char * groupname, + struct newsnntp_group_info ** info); + +/* + newsnntp_group_free() + + This function will free the data associated with NNTP group + data. + + @param info group info. +*/ + +LIBETPAN_EXPORT +void newsnntp_group_free(struct newsnntp_group_info * info); + +/* + newsnntp_list() select a newsgroup and fetch info about it. + + @param session NNTP session + @param result list of struct newsnntp_group_info *. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_list(newsnntp * session, clist ** result); + +/* + newsnntp_list_free() + + This function will free the data associated with a list + of newsnntp_group_info *. + + @param l the list of group info. +*/ + +LIBETPAN_EXPORT +void newsnntp_list_free(clist * l); + +/* + newsnntp_list_overview_fmt() fetch the server's format + overview. + + @param session NNTP session + @param result string describing the server's format + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_list_overview_fmt(newsnntp * session, clist ** result); + +/* + newsnntp_list_overview_fmt_free() + + This function will free the data associated with a list + obtained from newsnntp_list_overview_fmt() + + @param l the list of format data. +*/ + +LIBETPAN_EXPORT +void newsnntp_list_overview_fmt_free(clist * l); + +/* + newsnntp_list_active() fetch groups matching a wildmat string. + + @param session NNTP session + @param wildmat an optional wildmat pattern string + @param result a list of struct newsnntp_group_info * + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_list_active(newsnntp * session, const char * wildmat, clist ** result); + +/* + newsnntp_list_active_free() + + This function will free the data associated with a list + obtained from newsnntp_list_active() + + @param l the list of group data. +*/ + +LIBETPAN_EXPORT +void newsnntp_list_active_free(clist * l); + +/* + newsnntp_list_active_times() fetches when the selected newsgroup + was created. + + @param session NNTP session + @param result a list of struct newsnntp_group_time * + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_list_active_times(newsnntp * session, clist ** result); + +/* + newsnntp_list_active_times_free() + + This function will free the data associated with a list + obtained from newsnntp_list_active_times() + + @param l the list of group time data. +*/ + +LIBETPAN_EXPORT +void newsnntp_list_active_times_free(clist * l); + +/* + newsnntp_list_distribution() fetches a list of descriptions of + distributions known to the server. + + @param session NNTP session + @param result a list of struct newsnntp_distrib_value_meaning * + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_list_distribution(newsnntp * session, clist ** result); + +/* + newsnntp_list_distribution_free() + + This function will free the data associated with a list + obtained from newsnntp_list_distribution() + + @param l the list of distribution data. +*/ + +LIBETPAN_EXPORT +void newsnntp_list_distribution_free(clist * l); + +/* + newsnntp_list_distrib_pats() fetches a list of canonical + distribution values. Good for figuring out what to put in the + Distribution header of an article being posted. + + @param session NNTP session + @param result a list of struct newsnntp_distrib_default_value * + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_list_distrib_pats(newsnntp * session, clist ** result); + +/* + newsnntp_list_distribution_free() + + This function will free the data associated with a list + obtained from newsnntp_list_distrib_pats() + + @param l the list of distribution data. +*/ + +LIBETPAN_EXPORT +void newsnntp_list_distrib_pats_free(clist * l); + +/* + newsnntp_list_newsgroups() fetches a list of newsgroups and + their descriptions. + + @param session NNTP session + @param pattern an optional wildmat pattern + @param result a list of struct newsnntp_group_description * + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_list_newsgroups(newsnntp * session, const char * pattern, + clist ** result); + +/* + newsnntp_list_newsgroups_free() + + This function will free the data associated with a list + obtained from newsnntp_list_newsgroups() + + @param l the list of newsgroup data. +*/ + +LIBETPAN_EXPORT +void newsnntp_list_newsgroups_free(clist * l); + +/* + newsnntp_list_subscriptions() fetches a default list of + subscriptions for new users of the server. + + @param session NNTP session + @param result a list of newsgroup name strings + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_list_subscriptions(newsnntp * session, clist ** result); + +/* + newsnntp_list_subscriptions_free() + + This function will free the data associated with a list of + subscriptions. + + @param l the list of newsgroup data. +*/ + +LIBETPAN_EXPORT +void newsnntp_list_subscriptions_free(clist * l); + +/* + newsnntp_listgroup() fetches a list of all article numbers + for a particular group. + + @param session NNTP session + @param group_name the group name + @param result a list of uint32_t article numbers + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_listgroup(newsnntp * session, const char * group_name, + clist ** result); + +/* + newsnntp_listgroup_free() + + This function will free the data associated with a list of + subscriptions. + + @param l the list of article numbers. +*/ + +LIBETPAN_EXPORT +void newsnntp_listgroup_free(clist * l); + +/* + newsnntp_xhdr_single() retrieves specific header fields from a + specific article. + + @param session NNTP session + @param header the field name + @param result a list of struct newsnntp_xhdr_resp_item *. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_xhdr_single(newsnntp * session, const char * header, uint32_t article, + clist ** result); + +/* + newsnntp_xhdr_range() retrieves specific header fields from + a range of specific articles. + + @param session NNTP session + @param header the field name + @param rangeinf the lower bound of the range + @param rangesup the upper bound of the range + @param result a list of struct newsnntp_xhdr_resp_item *. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_xhdr_range(newsnntp * session, const char * header, + uint32_t rangeinf, uint32_t rangesup, + clist ** result); + +/* + newsnntp_xhdr_free() + + This function will free the data associated with a list of + struct newsnntp_xhdr_resp_item *. + + @param l the list of article header responses. +*/ + +LIBETPAN_EXPORT +void newsnntp_xhdr_free(clist * l); + +/* + newsnntp_xover_single() retrieves overview data for a specific + article. + + @param session NNTP session + @param header the field name + @param result a list of struct newsnntp_xhdr_resp_item *. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_xover_single(newsnntp * session, uint32_t article, + struct newsnntp_xover_resp_item ** result); + +/* + newsnntp_xover_range() retrieves overview information for a + particular range of articles. + + @param session NNTP session + @param header the field name + @param rangeinf the lower bound of the range + @param rangesup the upper bound of the range + @param result a list of struct newsnntp_xover_resp_item *. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_xover_range(newsnntp * session, uint32_t rangeinf, uint32_t rangesup, + clist ** result); +void xover_resp_item_free(struct newsnntp_xover_resp_item * n); + +/* + newsnntp_xover_resp_list_free() + + This function will free the data associated with a list of + struct newsnntp_xover_resp_item *. + + @param l the list of overview responses. +*/ + +LIBETPAN_EXPORT +void newsnntp_xover_resp_list_free(clist * l); + +/* deprecated */ +LIBETPAN_EXPORT +int newsnntp_authinfo_generic(newsnntp * session, const char * authentificator, + const char * arguments); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/newsnntp_socket.h b/Sources/libetpan/include/newsnntp_socket.h new file mode 100644 index 00000000..bb3cea4a --- /dev/null +++ b/Sources/libetpan/include/newsnntp_socket.h @@ -0,0 +1,58 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: newsnntp_socket.h,v 1.14 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifndef NEWSNNTP_SOCKET_H + +#define NEWSNNTP_SOCKET_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "sys/types.h" +#ifdef HAVE_INTTYPES_H +# include +#endif + +#include "newsnntp_types.h" + +LIBETPAN_EXPORT +int newsnntp_socket_connect(newsnntp * f, const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/newsnntp_ssl.h b/Sources/libetpan/include/newsnntp_ssl.h new file mode 100644 index 00000000..0843ada9 --- /dev/null +++ b/Sources/libetpan/include/newsnntp_ssl.h @@ -0,0 +1,62 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: newsnntp_ssl.h,v 1.17 2006/12/26 13:13:24 hoa Exp $ + */ + +#ifndef NEWSNNTP_SSL_H + +#define NEWSNNTP_SSL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "sys/types.h" +#ifdef HAVE_INTTYPES_H +# include +#endif + +#include "newsnntp_types.h" + +LIBETPAN_EXPORT +int newsnntp_ssl_connect(newsnntp * f, const char * server, uint16_t port); + +LIBETPAN_EXPORT +int newsnntp_ssl_connect_with_callback(newsnntp * f, const char * server, uint16_t port, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/newsnntp_types.h b/Sources/libetpan/include/newsnntp_types.h new file mode 100644 index 00000000..e87b8d63 --- /dev/null +++ b/Sources/libetpan/include/newsnntp_types.h @@ -0,0 +1,155 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: newsnntp_types.h,v 1.15 2006/12/13 18:31:32 hoa Exp $ + */ + +#ifndef NEWSNNTP_TYPES_H + +#define NEWSNNTP_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "libetpan-config.h" +#include "clist.h" + +#include "mailstream.h" +#include "mmapstring.h" + +enum { + NEWSNNTP_NO_ERROR = 0, + NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME=1, /* DEPRECATED, use ERROR instead */ + NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME=1, + NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD, + NEWSNNTP_ERROR_STREAM, + NEWSNNTP_ERROR_UNEXPECTED, + NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED, + NEWSNNTP_ERROR_NO_ARTICLE_SELECTED, + NEWSNNTP_ERROR_INVALID_ARTICLE_NUMBER, + NEWSNNTP_ERROR_ARTICLE_NOT_FOUND, + NEWSNNTP_ERROR_UNEXPECTED_RESPONSE, + NEWSNNTP_ERROR_INVALID_RESPONSE, + NEWSNNTP_ERROR_NO_SUCH_NEWS_GROUP, + NEWSNNTP_ERROR_POSTING_NOT_ALLOWED, + NEWSNNTP_ERROR_POSTING_FAILED, + NEWSNNTP_ERROR_PROGRAM_ERROR, + NEWSNNTP_ERROR_NO_PERMISSION, + NEWSNNTP_ERROR_COMMAND_NOT_UNDERSTOOD, + NEWSNNTP_ERROR_COMMAND_NOT_SUPPORTED, + NEWSNNTP_ERROR_CONNECTION_REFUSED, + NEWSNNTP_ERROR_MEMORY, + NEWSNNTP_ERROR_AUTHENTICATION_REJECTED, + NEWSNNTP_ERROR_BAD_STATE, + NEWSNNTP_ERROR_SSL, + NEWSNNTP_ERROR_AUTHENTICATION_OUT_OF_SEQUENCE, +}; + +typedef struct newsnntp newsnntp; + +struct newsnntp +{ + mailstream * nntp_stream; + + int nntp_readonly; + + size_t nntp_progr_rate; + progress_function * nntp_progr_fun; + + MMAPString * nntp_stream_buffer; + MMAPString * nntp_response_buffer; + + char * nntp_response; + + time_t nntp_timeout; + + void (* nntp_logger)(newsnntp * session, int log_type, const char * str, size_t size, void * context); + void * nntp_logger_context; + + mailprogress_function * nntp_progress_fun; + void * nntp_progress_context; +}; + +struct newsnntp_group_info +{ + char * grp_name; + uint32_t grp_first; + uint32_t grp_last; + uint32_t grp_count; + char grp_type; +}; + +struct newsnntp_group_time { + char * grp_name; + time_t grp_date; + char * grp_email; +}; + +struct newsnntp_distrib_value_meaning { + char * dst_value; + char * dst_meaning; +}; + +struct newsnntp_distrib_default_value { + uint32_t dst_weight; + char * dst_group_pattern; + char * dst_value; +}; + +struct newsnntp_group_description { + char * grp_name; + char * grp_description; +}; + +struct newsnntp_xhdr_resp_item { + uint32_t hdr_article; + char * hdr_value; +}; + +struct newsnntp_xover_resp_item { + uint32_t ovr_article; + char * ovr_subject; + char * ovr_author; + char * ovr_date; + char * ovr_message_id; + char * ovr_references; + size_t ovr_size; + uint32_t ovr_line_count; + clist * ovr_others; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/nntpdriver.h b/Sources/libetpan/include/nntpdriver.h new file mode 100644 index 00000000..c466b6c4 --- /dev/null +++ b/Sources/libetpan/include/nntpdriver.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver.h,v 1.16 2004/11/21 21:53:33 hoa Exp $ + */ + +#ifndef NNTPDRIVER_H + +#define NNTPDRIVER_H + +#include "nntpdriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * nntp_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/nntpdriver_cached.h b/Sources/libetpan/include/nntpdriver_cached.h new file mode 100644 index 00000000..090dd1fd --- /dev/null +++ b/Sources/libetpan/include/nntpdriver_cached.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver_cached.h,v 1.14 2004/11/21 21:53:33 hoa Exp $ + */ + +#ifndef NNTPDRIVER_CACHED_H + +#define NNTPDRIVER_CACHED_H + +#include "nntpdriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * nntp_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/nntpdriver_cached_message.h b/Sources/libetpan/include/nntpdriver_cached_message.h new file mode 100644 index 00000000..fb730206 --- /dev/null +++ b/Sources/libetpan/include/nntpdriver_cached_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver_cached_message.h,v 1.6 2004/11/21 21:53:33 hoa Exp $ + */ + +#include "mailmessage_types.h" + +#ifndef NNTPDRIVER_CACHED_MESSAGE_H + +#define NNTPDRIVER_CACHED_MESSAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * nntp_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/nntpdriver_message.h b/Sources/libetpan/include/nntpdriver_message.h new file mode 100644 index 00000000..6e9dcae5 --- /dev/null +++ b/Sources/libetpan/include/nntpdriver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver_message.h,v 1.6 2004/11/21 21:53:33 hoa Exp $ + */ + +#ifndef NNTPDRIVER_MESSAGE_H + +#define NNTPDRIVER_MESSAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nntpdriver_types.h" + +extern mailmessage_driver * nntp_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/nntpdriver_types.h b/Sources/libetpan/include/nntpdriver_types.h new file mode 100644 index 00000000..7e479428 --- /dev/null +++ b/Sources/libetpan/include/nntpdriver_types.h @@ -0,0 +1,149 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver_types.h,v 1.10 2007/06/30 12:58:21 hoa Exp $ + */ + +#ifndef NNTPDRIVER_TYPES_H + +#define NNTPDRIVER_TYPES_H + +#include "libetpan-config.h" + +#include "maildriver_types.h" +#include "newsnntp.h" +#include "clist.h" +#include "generic_cache_types.h" +#include "mailstorage_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* NNTP driver for session */ + +enum { + NNTPDRIVER_SET_MAX_ARTICLES = 1 +}; + +struct nntp_session_state_data { + newsnntp * nntp_session; + char * nntp_userid; + char * nntp_password; + + struct newsnntp_group_info * nntp_group_info; + char * nntp_group_name; + + clist * nntp_subscribed_list; + + uint32_t nntp_max_articles; + + int nntp_mode_reader; +}; + +/* cached NNTP driver for session */ + +enum { + /* the mapping of the parameters should be the same as for nntp */ + NNTPDRIVER_CACHED_SET_MAX_ARTICLES = 1, + /* cache specific */ + NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY, + NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY +}; + +struct nntp_cached_session_state_data { + mailsession * nntp_ancestor; + char nntp_cache_directory[PATH_MAX]; + char nntp_flags_directory[PATH_MAX]; + struct mail_flags_store * nntp_flags_store; +}; + + +/* nntp storage */ + +/* + nntp_mailstorage is the state data specific to the IMAP4rev1 storage. + + - storage this is the storage to initialize. + + - servername this is the name of the NNTP server + + - port is the port to connect to, on the server. + you give 0 to use the default port. + + - connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN or CONNECTION_TYPE_TLS. + + - auth_type is the authenticate mechanism to use. + The value can be NNTP_AUTH_TYPE_PLAIN. + + - login is the login of the POP3 account. + + - password is the password of the POP3 account. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache + + - flags_directory is the location of the flags +*/ + +struct nntp_mailstorage { + char * nntp_servername; + uint16_t nntp_port; + char * nntp_command; + int nntp_connection_type; + + int nntp_auth_type; + char * nntp_login; + char * nntp_password; + + int nntp_cached; + char * nntp_cache_directory; + char * nntp_flags_directory; + + char * nntp_local_address; + uint16_t nntp_local_port; +}; + +/* this is the type of NNTP authentication */ + +enum { + NNTP_AUTH_TYPE_PLAIN /* plain text authentication */ +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/nntpstorage.h b/Sources/libetpan/include/nntpstorage.h new file mode 100644 index 00000000..b6241a6c --- /dev/null +++ b/Sources/libetpan/include/nntpstorage.h @@ -0,0 +1,104 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpstorage.h,v 1.11 2007/06/30 12:58:21 hoa Exp $ + */ + +#ifndef NNTPSTORAGE_H + +#define NNTPSTORAGE_H + +#include "nntpdriver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + nntp_mailstorage_init is the constructor for a NNTP storage + + @param storage this is the storage to initialize. + + @param servername this is the name of the NNTP server + + @param port is the port to connect to, on the server. + you give 0 to use the default port. + + @param command the command used to connect to the server instead of + allowing normal TCP connections to be used. + + @param connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS, + CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS, + CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS, + CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,. + + @param auth_type is the authenticate mechanism to use. + The value can be NNTP_AUTH_TYPE_PLAIN. + + @param login is the login of the POP3 account. + + @param password is the password of the POP3 account. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache + + @param flags_directory is the location of the flags +*/ + +LIBETPAN_EXPORT +int nntp_mailstorage_init(struct mailstorage * storage, + const char * nntp_servername, uint16_t nntp_port, + const char * nntp_command, + int nntp_connection_type, int nntp_auth_type, + const char * nntp_login, const char * nntp_password, + int nntp_cached, const char * nntp_cache_directory, + const char * nntp_flags_directory); + +LIBETPAN_EXPORT +int nntp_mailstorage_init_with_local_address(struct mailstorage * storage, + const char * nntp_servername, uint16_t nntp_port, + const char * nntp_local_servername, uint16_t nntp_local_port, + const char * nntp_command, + int nntp_connection_type, int nntp_auth_type, + const char * nntp_login, const char * nntp_password, + int nntp_cached, const char * nntp_cache_directory, + const char * nntp_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/parser.h b/Sources/libetpan/include/parser.h new file mode 100644 index 00000000..eb29dcd6 --- /dev/null +++ b/Sources/libetpan/include/parser.h @@ -0,0 +1,42 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef PARSER_H + +#define PARSER_H + +#include "newsfeed_private.h" + +void newsfeed_parser_set_expat_handlers(struct newsfeed_parser_context * ctx); +size_t newsfeed_writefunc(void * ptr, size_t size, size_t nmemb, void * stream); +const char * newsfeed_parser_get_attribute_value(const char ** attr, + const char * name); + +#endif /* __PARSER_H */ diff --git a/Sources/libetpan/include/parser_atom03.h b/Sources/libetpan/include/parser_atom03.h new file mode 100644 index 00000000..974b943e --- /dev/null +++ b/Sources/libetpan/include/parser_atom03.h @@ -0,0 +1,39 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * Copyright (C) 2006 Andrej Kacian + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef PARSER_ATOM03_H +#define PARSER_ATOM03_H + +void newsfeed_parser_atom03_start(void * data, const char * el, const char ** attr); +void newsfeed_parser_atom03_end(void * data, const char * el); + +#endif /* PARSER_ATOM03_H */ diff --git a/Sources/libetpan/include/parser_atom10.h b/Sources/libetpan/include/parser_atom10.h new file mode 100644 index 00000000..a8bad78d --- /dev/null +++ b/Sources/libetpan/include/parser_atom10.h @@ -0,0 +1,39 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * Copyright (C) 2006 Andrej Kacian + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef PARSER_ATOM10_H +#define PARSER_ATOM10_H + +void newsfeed_parser_atom10_start(void * data, const char * el, const char ** attr); +void newsfeed_parser_atom10_end(void * data, const char * el); + +#endif /* PARSER_ATOM10_H */ diff --git a/Sources/libetpan/include/parser_rdf.h b/Sources/libetpan/include/parser_rdf.h new file mode 100644 index 00000000..857e6a00 --- /dev/null +++ b/Sources/libetpan/include/parser_rdf.h @@ -0,0 +1,45 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * Copyright (C) 2006 Andrej Kacian + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef PARSER_RDF_H +#define PARSER_RDF_H + +void newsfeed_parser_rdf_start(void * data, const char * el, const char ** attr); +void newsfeed_parser_rdf_end(void * data, const char * el); + +enum { + FEED_LOC_RDF_NONE, + FEED_LOC_RDF_CHANNEL, + FEED_LOC_RDF_ITEM +}; + +#endif /* __PARSER_RDF_H */ diff --git a/Sources/libetpan/include/parser_rss20.h b/Sources/libetpan/include/parser_rss20.h new file mode 100644 index 00000000..12c3ee67 --- /dev/null +++ b/Sources/libetpan/include/parser_rss20.h @@ -0,0 +1,39 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * Copyright (C) 2006 Andrej Kacian + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef PARSER_RSS20_H +#define PARSER_RSS20_H + +void newsfeed_parser_rss20_start(void * data, const char * el, const char ** attr); +void newsfeed_parser_rss20_end(void * data, const char * el); + +#endif /* PARSER_RSS20_H */ diff --git a/Sources/libetpan/include/pop3driver.h b/Sources/libetpan/include/pop3driver.h new file mode 100644 index 00000000..311624ab --- /dev/null +++ b/Sources/libetpan/include/pop3driver.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver.h,v 1.15 2004/11/21 21:53:34 hoa Exp $ + */ + +#ifndef POP3DRIVER_H + +#define POP3DRIVER_H + +#include "pop3driver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * pop3_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/pop3driver_cached.h b/Sources/libetpan/include/pop3driver_cached.h new file mode 100644 index 00000000..1d394959 --- /dev/null +++ b/Sources/libetpan/include/pop3driver_cached.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver_cached.h,v 1.15 2004/11/21 21:53:34 hoa Exp $ + */ + +#ifndef POP3DRIVER_CACHED_H + +#define POP3DRIVER_CACHED_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pop3driver_types.h" + +extern mailsession_driver * pop3_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/pop3driver_cached_message.h b/Sources/libetpan/include/pop3driver_cached_message.h new file mode 100644 index 00000000..1702b2b1 --- /dev/null +++ b/Sources/libetpan/include/pop3driver_cached_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver_cached_message.h,v 1.6 2004/11/21 21:53:34 hoa Exp $ + */ + +#ifndef POP3DRIVER_CACHED_MESSAGE_H + +#define POP3DRIVER_CACHED_MESSAGE_H + +#include "pop3driver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * pop3_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/pop3driver_message.h b/Sources/libetpan/include/pop3driver_message.h new file mode 100644 index 00000000..2b58a467 --- /dev/null +++ b/Sources/libetpan/include/pop3driver_message.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver_message.h,v 1.6 2004/11/21 21:53:34 hoa Exp $ + */ + +#ifndef POP3DRIVER_MESSAGE_H + +#define POP3DRIVER_MESSAGE_H + +#include "pop3driver_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * pop3_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/pop3driver_types.h b/Sources/libetpan/include/pop3driver_types.h new file mode 100644 index 00000000..584086c0 --- /dev/null +++ b/Sources/libetpan/include/pop3driver_types.h @@ -0,0 +1,175 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver_types.h,v 1.11 2007/06/30 12:58:21 hoa Exp $ + */ + +#ifndef POP3DRIVER_TYPES_H + +#define POP3DRIVER_TYPES_H + +#include "libetpan-config.h" + +#include "maildriver_types.h" +#include "mailpop3.h" +#include "maildriver_types.h" +#include "chash.h" +#include "mailstorage_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* POP3 driver for session */ + +enum { + POP3DRIVER_SET_AUTH_TYPE = 1 +}; + +enum { + POP3DRIVER_AUTH_TYPE_PLAIN = 0, + POP3DRIVER_AUTH_TYPE_APOP, + POP3DRIVER_AUTH_TYPE_TRY_APOP +}; + +struct pop3_session_state_data { + int pop3_auth_type; + mailpop3 * pop3_session; + void (* pop3_ssl_callback)(struct mailstream_ssl_context * ssl_context, void * data); + void * pop3_ssl_cb_data; +}; + +/* cached POP3 driver for session */ + +enum { + /* the mapping of the parameters should be the same as for pop3 */ + POP3DRIVER_CACHED_SET_AUTH_TYPE = 1, + POP3DRIVER_CACHED_SET_SSL_CALLBACK = 2, + POP3DRIVER_CACHED_SET_SSL_CALLBACK_DATA = 3, + /* cache specific */ + POP3DRIVER_CACHED_SET_CACHE_DIRECTORY = 1001, + POP3DRIVER_CACHED_SET_FLAGS_DIRECTORY = 1002 +}; + +struct pop3_cached_session_state_data { + mailsession * pop3_ancestor; + char pop3_cache_directory[PATH_MAX]; + char pop3_flags_directory[PATH_MAX]; + chash * pop3_flags_hash; + carray * pop3_flags_array; + struct mail_flags_store * pop3_flags_store; +}; + +/* pop3 storage */ + +/* + pop3_mailstorage is the state data specific to the POP3 storage. + + - servername this is the name of the POP3 server + + - port is the port to connect to, on the server. + you give 0 to use the default port. + + - connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS, + CONNECTION_TYPE_TRY_STARTTLS or CONNECTION_TYPE_TLS. + + - auth_type is the authenticate mechanism to use. + The value can be POP3_AUTH_TYPE_PLAIN, POP3_AUTH_TYPE_APOP + or POP3_AUTH_TYPE_TRY_APOP. Other values are not yet implemented. + + - login is the login of the POP3 account. + + - password is the password of the POP3 account. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache. + + - flags_directory is the location of the flags. +*/ + +struct pop3_mailstorage { + char * pop3_servername; + uint16_t pop3_port; + char * pop3_command; + int pop3_connection_type; + + int pop3_auth_type; + char * pop3_login; /* deprecated */ + char * pop3_password; /* deprecated */ + + int pop3_cached; + char * pop3_cache_directory; + char * pop3_flags_directory; + + struct { + int sasl_enabled; + char * sasl_auth_type; + char * sasl_server_fqdn; + char * sasl_local_ip_port; + char * sasl_remote_ip_port; + char * sasl_login; + char * sasl_auth_name; + char * sasl_password; + char * sasl_realm; + } pop3_sasl; + + char * pop3_local_address; + uint16_t pop3_local_port; +}; + +/* this is the type of POP3 authentication */ + +enum { + POP3_AUTH_TYPE_PLAIN, /* plain text authentication */ + POP3_AUTH_TYPE_APOP, /* APOP authentication */ + POP3_AUTH_TYPE_TRY_APOP, /* first, try APOP, if it fails, + try plain text */ + POP3_AUTH_TYPE_SASL_ANONYMOUS, /* SASL anonymous */ + POP3_AUTH_TYPE_SASL_CRAM_MD5, /* SASL CRAM MD5 */ + POP3_AUTH_TYPE_SASL_KERBEROS_V4, /* SASL KERBEROS V4 */ + POP3_AUTH_TYPE_SASL_PLAIN, /* SASL plain */ + POP3_AUTH_TYPE_SASL_SCRAM_MD5, /* SASL SCRAM MD5 */ + POP3_AUTH_TYPE_SASL_GSSAPI, /* SASL GSSAPI */ + POP3_AUTH_TYPE_SASL_DIGEST_MD5 /* SASL digest MD5 */ +}; + +#define POP3_SASL_AUTH_TYPE_APOP "X-LIBETPAN-APOP" +#define POP3_SASL_AUTH_TYPE_TRY_APOP "X-LIBETPAN-TRY-APOP" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/pop3storage.h b/Sources/libetpan/include/pop3storage.h new file mode 100644 index 00000000..a000c473 --- /dev/null +++ b/Sources/libetpan/include/pop3storage.h @@ -0,0 +1,125 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3storage.h,v 1.12 2007/06/30 12:58:21 hoa Exp $ + */ + +#ifndef POP3STORAGE_H + +#define POP3STORAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "pop3driver_types.h" +#include "pop3driver.h" +#include "pop3driver_cached.h" + +/* + pop3_mailstorage_init is the constructor for a POP3 storage + + @param storage this is the storage to initialize. + + @param servername this is the name of the POP3 server + + @param port is the port to connect to, on the server. + you give 0 to use the default port. + + @param command the command used to connect to the server instead of + allowing normal TCP connections to be used. + + @param connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS, + CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS, + CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS, + CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,. + + @param auth_type is the authenticate mechanism to use. + The value can be POP3_AUTH_TYPE_PLAIN, POP3_AUTH_TYPE_APOP + or POP3_AUTH_TYPE_TRY_APOP. Other values are not yet implemented. + + @param login is the login of the POP3 account. + + @param password is the password of the POP3 account. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache + + @param flags_directory is the location of the flags +*/ + +LIBETPAN_EXPORT +int pop3_mailstorage_init(struct mailstorage * storage, + const char * pop3_servername, uint16_t pop3_port, + const char * pop3_command, + int pop3_connection_type, int pop3_auth_type, + const char * pop3_login, const char * pop3_password, + int pop3_cached, const char * pop3_cache_directory, + const char * pop3_flags_directory); + +LIBETPAN_EXPORT +int pop3_mailstorage_init_sasl(struct mailstorage * storage, + const char * pop3_servername, uint16_t pop3_port, + const char * pop3_command, + int pop3_connection_type, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm, + int pop3_cached, const char * pop3_cache_directory, + const char * pop3_flags_directory); + +LIBETPAN_EXPORT +int pop3_mailstorage_init_sasl_with_local_address(struct mailstorage * storage, + const char * pop3_servername, uint16_t pop3_port, + const char * imap_local_address, uint16_t imap_local_port, + const char * pop3_command, + int pop3_connection_type, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm, + int pop3_cached, const char * pop3_cache_directory, + const char * pop3_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/qresync.h b/Sources/libetpan/include/qresync.h new file mode 100644 index 00000000..2e3bdc08 --- /dev/null +++ b/Sources/libetpan/include/qresync.h @@ -0,0 +1,75 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2013 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef QRESYNC_H + +#define QRESYNC_H + +#include "mailimap_extension_types.h" +#include "mailimap_types.h" +#include "clist.h" +#include "qresync_types.h" + +LIBETPAN_EXPORT +extern struct mailimap_extension_api mailimap_extension_qresync; + +/* +mailimap_select_qresync() +known_uids can be NULL +seq_match_data_sequences can be NULL +seq_match_data_uids can be NULL +*/ + +LIBETPAN_EXPORT + int mailimap_select_qresync(mailimap * session, const char * mb, + uint32_t uidvalidity, uint64_t modseq_value, + struct mailimap_set * known_uids, + struct mailimap_set * seq_match_data_sequences, + struct mailimap_set * seq_match_data_uids, + clist ** fetch_result, struct mailimap_qresync_vanished ** p_vanished, + uint64_t * p_mod_sequence_value); + +LIBETPAN_EXPORT +int mailimap_fetch_qresync(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, uint64_t mod_sequence_value, + clist ** fetch_result, struct mailimap_qresync_vanished ** p_vanished); + +LIBETPAN_EXPORT +int mailimap_uid_fetch_qresync(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, uint64_t mod_sequence_value, + clist ** fetch_result, struct mailimap_qresync_vanished ** p_vanished); + +LIBETPAN_EXPORT +int mailimap_has_qresync(mailimap * session); + +#endif diff --git a/Sources/libetpan/include/qresync_private.h b/Sources/libetpan/include/qresync_private.h new file mode 100644 index 00000000..14a5eaec --- /dev/null +++ b/Sources/libetpan/include/qresync_private.h @@ -0,0 +1,46 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2013 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef QRESYNC_PRIVATE_H +#define QRESYNC_PRIVATE_H + +int mailimap_fetch_qresync_vanished(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, uint64_t mod_sequence_value, int vanished, + clist ** fetch_result, struct mailimap_qresync_vanished ** p_vanished); + +LIBETPAN_EXPORT +int mailimap_uid_fetch_qresync_vanished(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, uint64_t mod_sequence_value, int vanished, + clist ** fetch_result, struct mailimap_qresync_vanished ** p_vanished); + +#endif diff --git a/Sources/libetpan/include/qresync_types.h b/Sources/libetpan/include/qresync_types.h new file mode 100644 index 00000000..a2800409 --- /dev/null +++ b/Sources/libetpan/include/qresync_types.h @@ -0,0 +1,68 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2013 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef QRESYNC_TYPES_H + +#define QRESYNC_TYPES_H + +#include "libetpan-config.h" + +enum { + MAILIMAP_QRESYNC_TYPE_VANISHED, + MAILIMAP_QRESYNC_TYPE_RESP_TEXT_CODE +}; + +struct mailimap_qresync_vanished { + int qr_earlier; + struct mailimap_set * qr_known_uids; +}; + +enum { + MAILIMAP_QRESYNC_RESPTEXTCODE_CLOSED +}; + +struct mailimap_qresync_resptextcode { + int qr_type; +}; + +LIBETPAN_EXPORT +struct mailimap_qresync_vanished * mailimap_qresync_vanished_new(int qr_earlier, struct mailimap_set * qr_known_uids); + +LIBETPAN_EXPORT +void mailimap_qresync_vanished_free(struct mailimap_qresync_vanished * vanished); + +LIBETPAN_EXPORT +struct mailimap_qresync_resptextcode * mailimap_qresync_resptextcode_new(int qr_type); + +LIBETPAN_EXPORT +void mailimap_qresync_resptextcode_free(struct mailimap_qresync_resptextcode * resptextcode); + +#endif diff --git a/Sources/libetpan/include/quota.h b/Sources/libetpan/include/quota.h new file mode 100644 index 00000000..be1209f1 --- /dev/null +++ b/Sources/libetpan/include/quota.h @@ -0,0 +1,59 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef QUOTA_H + +#define QUOTA_H + +#include "libetpan-config.h" +#include "mailimap_extension.h" +#include "quota_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +LIBETPAN_EXPORT +extern struct mailimap_extension_api mailimap_extension_quota; + +void +mailimap_quota_free(struct mailimap_extension_data * ext_data); + +LIBETPAN_EXPORT +int mailimap_quota_getquotaroot(mailimap * session, + const char * list_mb, + struct mailimap_quota_complete_data ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/quota_parser.h b/Sources/libetpan/include/quota_parser.h new file mode 100644 index 00000000..a2f67f4b --- /dev/null +++ b/Sources/libetpan/include/quota_parser.h @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef QUOTA_PARSER_H + +#define QUOTA_PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_parser.h" +#include "quota_types.h" + +int +mailimap_quota_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, progress_function * progr_fun); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/quota_sender.h b/Sources/libetpan/include/quota_sender.h new file mode 100644 index 00000000..130eaf70 --- /dev/null +++ b/Sources/libetpan/include/quota_sender.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef QUOTA_SENDER_H + +#define QUOTA_SENDER_H + +#include "mailimap_sender.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int mailimap_quota_getquota_send(mailstream * fd, + const char * quotaroot); + +int mailimap_quota_getquotaroot_send(mailstream * fd, + const char * list_mb); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/quota_types.h b/Sources/libetpan/include/quota_types.h new file mode 100644 index 00000000..4386830d --- /dev/null +++ b/Sources/libetpan/include/quota_types.h @@ -0,0 +1,121 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef QUOTA_TYPES_H + +#define QUOTA_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "libetpan-config.h" +#include "mailstream.h" +#include "clist.h" + +struct mailimap_quota_quota_resource { + char * resource_name; + uint32_t usage; + uint32_t limit; +}; + +LIBETPAN_EXPORT +struct mailimap_quota_quota_resource * +mailimap_quota_quota_resource_new(char * resource_name, + uint32_t usage, uint32_t limit); + +LIBETPAN_EXPORT +void +mailimap_quota_quota_resource_free(struct mailimap_quota_quota_resource * res); + + + +struct mailimap_quota_quota_data { + char * quotaroot; + clist * quota_list; + /* list of (struct mailimap_quota_quota_resource *) */ +}; + +LIBETPAN_EXPORT +struct mailimap_quota_quota_data * +mailimap_quota_quota_data_new(char * quotaroot, clist * quota_list); + +LIBETPAN_EXPORT +void +mailimap_quota_quota_data_free(struct mailimap_quota_quota_data * data); + + + +struct mailimap_quota_quotaroot_data { + char * mailbox; + clist * quotaroot_list; + /* list of (char *) */ +}; + +LIBETPAN_EXPORT +struct mailimap_quota_quotaroot_data * +mailimap_quota_quotaroot_data_new(char * mailbox, clist * quotaroot_list); + +LIBETPAN_EXPORT +void +mailimap_quota_quotaroot_data_free( + struct mailimap_quota_quotaroot_data * data); + + + +enum { + MAILIMAP_QUOTA_TYPE_QUOTA_DATA, /* child of mailbox-data */ + MAILIMAP_QUOTA_TYPE_QUOTAROOT_DATA /* child of mailbox-data */ +}; + + + +struct mailimap_quota_complete_data { + struct mailimap_quota_quotaroot_data * quotaroot_data; + clist * quota_list; + /* list of (struct mailimap_quota_quota_data *) */ +}; + +LIBETPAN_EXPORT +struct mailimap_quota_complete_data * +mailimap_quota_complete_data_new( + struct mailimap_quota_quotaroot_data * quotaroot_data, + clist * quota_list); + +LIBETPAN_EXPORT +void +mailimap_quota_complete_data_free(struct mailimap_quota_complete_data * data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/timeutils.h b/Sources/libetpan/include/timeutils.h new file mode 100644 index 00000000..10f0a9f5 --- /dev/null +++ b/Sources/libetpan/include/timeutils.h @@ -0,0 +1,39 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef TIMEUTILS_H + +#define TIMEUTILS_H + +#include + +time_t mail_mkgmtime(struct tm * tmp); + +#endif diff --git a/Sources/libetpan/include/uidplus.h b/Sources/libetpan/include/uidplus.h new file mode 100644 index 00000000..95913b60 --- /dev/null +++ b/Sources/libetpan/include/uidplus.h @@ -0,0 +1,98 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef UIDPLUS_H + +#define UIDPLUS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "libetpan-config.h" +#include "mailimap_types.h" +#include "uidplus_types.h" + +LIBETPAN_EXPORT +extern struct mailimap_extension_api mailimap_extension_uidplus; + +LIBETPAN_EXPORT +int mailimap_uid_expunge(mailimap * session, struct mailimap_set * set); + +LIBETPAN_EXPORT +int mailimap_uidplus_copy(mailimap * session, struct mailimap_set * set, + const char * mb, + uint32_t * uidvalidity_result, + struct mailimap_set ** source_result, + struct mailimap_set ** dest_result); + +LIBETPAN_EXPORT +int mailimap_uidplus_uid_copy(mailimap * session, struct mailimap_set * set, + const char * mb, + uint32_t * uidvalidity_result, + struct mailimap_set ** source_result, + struct mailimap_set ** dest_result); + +LIBETPAN_EXPORT +int mailimap_uidplus_move(mailimap * session, struct mailimap_set * set, + const char * mb, + uint32_t * uidvalidity_result, + struct mailimap_set ** source_result, + struct mailimap_set ** dest_result); + +LIBETPAN_EXPORT +int mailimap_uidplus_uid_move(mailimap * session, struct mailimap_set * set, + const char * mb, + uint32_t * uidvalidity_result, + struct mailimap_set ** source_result, + struct mailimap_set ** dest_result); + +LIBETPAN_EXPORT +int mailimap_uidplus_append(mailimap * session, const char * mailbox, + struct mailimap_flag_list * flag_list, + struct mailimap_date_time * date_time, + const char * literal, size_t literal_size, + uint32_t * uidvalidity_result, + uint32_t * uid_result); + +LIBETPAN_EXPORT +int mailimap_uidplus_append_simple(mailimap * session, const char * mailbox, + const char * content, size_t size, + uint32_t * uidvalidity_result, + uint32_t * uid_result); + +LIBETPAN_EXPORT +int mailimap_has_uidplus(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/uidplus_parser.h b/Sources/libetpan/include/uidplus_parser.h new file mode 100644 index 00000000..833f0246 --- /dev/null +++ b/Sources/libetpan/include/uidplus_parser.h @@ -0,0 +1,55 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef UIDPLUS_PARSER_H + +#define UIDPLUS_PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "mailstream_types.h" +#include "mmapstring.h" +#include "mailimap_types.h" +#include "mailimap_extension_types.h" + +int mailimap_uidplus_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/uidplus_sender.h b/Sources/libetpan/include/uidplus_sender.h new file mode 100644 index 00000000..54e9b838 --- /dev/null +++ b/Sources/libetpan/include/uidplus_sender.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef UIDPLUS_SENDER_H + +#define UIDPLUS_SENDER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "libetpan-config.h" + +#include "mailimap_types.h" +#include "mailstream_types.h" + +int +mailimap_uid_expunge_send(mailstream * fd, + struct mailimap_set * set); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/uidplus_types.h b/Sources/libetpan/include/uidplus_types.h new file mode 100644 index 00000000..2ca911b6 --- /dev/null +++ b/Sources/libetpan/include/uidplus_types.h @@ -0,0 +1,83 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef UIDPLUS_TYPES_H + +#define UIDPLUS_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef WIN32 +#include "inttypes.h" +#endif + +#include "mailimap_types.h" + +enum { + MAILIMAP_UIDPLUS_RESP_CODE_APND, + MAILIMAP_UIDPLUS_RESP_CODE_COPY, + MAILIMAP_UIDPLUS_RESP_CODE_UIDNOTSTICKY +}; + +struct mailimap_uidplus_resp_code_apnd { + uint32_t uid_uidvalidity; + struct mailimap_set * uid_set; +}; + +struct mailimap_uidplus_resp_code_copy { + uint32_t uid_uidvalidity; + struct mailimap_set * uid_source_set; + struct mailimap_set * uid_dest_set; +}; + +LIBETPAN_EXPORT +struct mailimap_uidplus_resp_code_apnd * +mailimap_uidplus_resp_code_apnd_new(uint32_t uid_uidvalidity, struct mailimap_set * uid_set); + +LIBETPAN_EXPORT +void mailimap_uidplus_resp_code_apnd_free(struct mailimap_uidplus_resp_code_apnd * resp_code_apnd); + +LIBETPAN_EXPORT +struct mailimap_uidplus_resp_code_copy * +mailimap_uidplus_resp_code_copy_new(uint32_t uid_uidvalidity, struct mailimap_set * uid_source_set, struct mailimap_set * uid_dest_set); + +LIBETPAN_EXPORT +void mailimap_uidplus_resp_code_copy_free(struct mailimap_uidplus_resp_code_copy * resp_code_copy); + +LIBETPAN_EXPORT +void mailimap_uidplus_free(struct mailimap_extension_data * ext_data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/include/xgmlabels.h b/Sources/libetpan/include/xgmlabels.h new file mode 100644 index 00000000..86a8672f --- /dev/null +++ b/Sources/libetpan/include/xgmlabels.h @@ -0,0 +1,85 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2011 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef XGMLABELS_H +#define XGMLABELS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "libetpan-config.h" +#include "mailimap_extension.h" + + struct mailimap_msg_att_xgmlabels { + clist * att_labels; /* != NULL */ + }; + + LIBETPAN_EXPORT + extern struct mailimap_extension_api mailimap_extension_xgmlabels; + + LIBETPAN_EXPORT + struct mailimap_fetch_att * mailimap_fetch_att_new_xgmlabels(void); + + LIBETPAN_EXPORT + int mailimap_has_xgmlabels(mailimap * session); + + LIBETPAN_EXPORT + struct mailimap_msg_att_xgmlabels * mailimap_msg_att_xgmlabels_new(clist * att_labels); + + LIBETPAN_EXPORT + struct mailimap_msg_att_xgmlabels * mailimap_msg_att_xgmlabels_new_empty(void); + + LIBETPAN_EXPORT + int mailimap_msg_att_xgmlabels_add(struct mailimap_msg_att_xgmlabels * att, char * label); + + LIBETPAN_EXPORT void mailimap_msg_att_xgmlabels_free(struct mailimap_msg_att_xgmlabels * att); + + LIBETPAN_EXPORT + int + mailimap_store_xgmlabels(mailimap * session, + struct mailimap_set * set, + int fl_sign, int fl_silent, + struct mailimap_msg_att_xgmlabels * labels); + + LIBETPAN_EXPORT + int + mailimap_uid_store_xgmlabels(mailimap * session, + struct mailimap_set * set, + int fl_sign, int fl_silent, + struct mailimap_msg_att_xgmlabels * labels); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/Sources/libetpan/include/xgmmsgid.h b/Sources/libetpan/include/xgmmsgid.h new file mode 100644 index 00000000..06160e27 --- /dev/null +++ b/Sources/libetpan/include/xgmmsgid.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef XGMMSGID_H +#define XGMMSGID_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "libetpan-config.h" +#include "mailimap_extension.h" + + LIBETPAN_EXPORT + extern struct mailimap_extension_api mailimap_extension_xgmmsgid; + + LIBETPAN_EXPORT + struct mailimap_fetch_att * mailimap_fetch_att_new_xgmmsgid(void); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/Sources/libetpan/include/xgmthrid.h b/Sources/libetpan/include/xgmthrid.h new file mode 100644 index 00000000..93260e67 --- /dev/null +++ b/Sources/libetpan/include/xgmthrid.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef XGMTHRID_H +#define XGMTHRID_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "libetpan-config.h" +#include "mailimap_extension.h" + + LIBETPAN_EXPORT + extern struct mailimap_extension_api mailimap_extension_xgmthrid; + + LIBETPAN_EXPORT + struct mailimap_fetch_att * mailimap_fetch_att_new_xgmthrid(void); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/Sources/libetpan/include/xlist.h b/Sources/libetpan/include/xlist.h new file mode 100644 index 00000000..ddf66c37 --- /dev/null +++ b/Sources/libetpan/include/xlist.h @@ -0,0 +1,63 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2011 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef XLIST_H + +#define XLIST_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "libetpan-config.h" +#include "mailimap_extension.h" + +LIBETPAN_EXPORT +extern struct mailimap_extension_api mailimap_extension_xlist; + +/* + mailimap_xlist() + + same as mailimap_list() but with additional flags to indicate identity of mailboxes. +*/ + +LIBETPAN_EXPORT +int mailimap_xlist(mailimap * session, const char * mb, + const char * list_mb, clist ** result); + +LIBETPAN_EXPORT +int mailimap_has_xlist(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/Makefile.am b/Sources/libetpan/low-level/Makefile.am new file mode 100644 index 00000000..055d99fb --- /dev/null +++ b/Sources/libetpan/low-level/Makefile.am @@ -0,0 +1,46 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +SUBDIRS = imap imf maildir mbox mh mime nntp pop3 smtp feed + +noinst_LTLIBRARIES = liblow-level.la +liblow_level_la_SOURCES = +liblow_level_la_LIBADD = \ + imap/libimap.la \ + imf/libimf.la \ + maildir/libmaildir.la \ + mbox/libmbox.la \ + mh/libmh.la \ + mime/libmime.la \ + nntp/libnntp.la \ + pop3/libpop3.la \ + smtp/libsmtp.la \ + feed/libfeed.la diff --git a/Sources/libetpan/low-level/feed/Makefile.am b/Sources/libetpan/low-level/feed/Makefile.am new file mode 100644 index 00000000..c6f55a0f --- /dev/null +++ b/Sources/libetpan/low-level/feed/Makefile.am @@ -0,0 +1,48 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +etpaninclude_HEADERS = \ + newsfeed_types.h newsfeed.h newsfeed_item.h newsfeed_item_enclosure.h + +AM_CPPFLAGS = -I$(top_builddir)/include \ + -I$(top_srcdir)/src/data-types -I$(top_srcdir)/src/low-level/imf + +noinst_LTLIBRARIES = libfeed.la + +libfeed_la_SOURCES = \ + date.h date.c newsfeed_item.c newsfeed.c \ + parser.h parser.c \ + newsfeed_item_enclosure.c \ + newsfeed_private.h newsfeed_private.c \ + parser_atom10.h parser_atom10.c \ + parser_atom03.h parser_atom03.c \ + parser_rdf.h parser_rdf.c \ + parser_rss20.h parser_rss20.c diff --git a/Sources/libetpan/low-level/feed/date.c b/Sources/libetpan/low-level/feed/date.c new file mode 100644 index 00000000..c7b62d23 --- /dev/null +++ b/Sources/libetpan/low-level/feed/date.c @@ -0,0 +1,390 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include +#include +#include +#ifndef WIN32 +#include +#endif + +#include "mailimf.h" +#include "timeutils.h" + +/* +YYYYMMDDThhmmss +YYYYMMDDThhmmssZ +YYYYMMDDThhmmss±hhmm +YYYYMMDDThhmmss±hh + +YYYY-MM-DDThh:mm:ss +YYYY-MM-DDThh:mm:ssZ +YYYY-MM-DDThh:mm:ss±hh:mm +YYYY-MM-DDThh:mm:ss±hh +*/ + + +/* +basic_format_parse() + +YYYYMMDDThhmmss +YYYYMMDDThhmmssZ +YYYYMMDDThhmmss±hhmm +YYYYMMDDThhmmss±hh +*/ + +static time_t basic_format_parse(const char * str) +{ + int r; + size_t len; + size_t current_index; + uint32_t value; + int year; + int month; + int day; + int hour; + int minute; + int second; + int offset; + int apply_offset; + struct tm ts; + int local_time; + time_t result; + + len = strlen(str); + current_index = 0; + + r = mailimf_number_parse(str, len, ¤t_index, &value); + if (r != MAILIMF_NO_ERROR) + return (time_t) -1; + + day = value % 100; + value /= 100; + month = value % 100; + value /= 100; + year = value; + + r = mailimf_char_parse(str, len, ¤t_index, 'T'); + if (r != MAILIMF_NO_ERROR) + return (time_t) -1; + + r = mailimf_number_parse(str, len, ¤t_index, &value); + if (r != MAILIMF_NO_ERROR) + return (time_t) -1; + + second = value % 100; + value /= 100; + minute = value % 100; + value /= 100; + hour = value; + + apply_offset = 0; + offset = 0; + r = mailimf_char_parse(str, len, ¤t_index, 'Z'); + if (r == MAILIMF_NO_ERROR) { + /* utc */ + offset = 0; + apply_offset = 1; + } + + if (r != MAILIMF_NO_ERROR) { + int offset_hour; + int offset_minute; + + r = mailimf_char_parse(str, len, ¤t_index, '+'); + if (r == MAILIMF_NO_ERROR) { + size_t last_index; + + last_index = current_index; + r = mailimf_number_parse(str, len, ¤t_index, &value); + if (r != MAILIMF_NO_ERROR) + return (time_t) -1; + if (current_index - last_index == 2) { + offset_hour = value; + offset_minute = 0; + } + else { + offset_minute = value % 100; + value /= 100; + offset_hour = value; + } + offset = offset_hour * 3600 + offset_minute; + apply_offset = 1; + } + } + + if (r != MAILIMF_NO_ERROR) { + int offset_hour; + int offset_minute; + + r = mailimf_char_parse(str, len, ¤t_index, '-'); + if (r == MAILIMF_NO_ERROR) { + size_t last_index; + + last_index = current_index; + r = mailimf_number_parse(str, len, ¤t_index, &value); + if (r != MAILIMF_NO_ERROR) + return (time_t) -1; + if (current_index - last_index == 2) { + offset_hour = value; + offset_minute = 0; + } + else { + offset_minute = value % 100; + value /= 100; + offset_hour = value; + } + offset = - (offset_hour * 3600 + offset_minute); + apply_offset = 1; + } + } + + local_time = 0; + if (r != MAILIMF_NO_ERROR) { + local_time = 1; + } + + memset(&ts, 0, sizeof(ts)); + + ts.tm_sec = second; + ts.tm_min = minute; + ts.tm_hour = hour; + ts.tm_mday = day; + ts.tm_mon = month - 1; + ts.tm_year = year - 1900; + + if (local_time) { + result = mktime(&ts); + } + else { + result = mail_mkgmtime(&ts); + if (apply_offset) + result -= offset; + } + + return result; +} + +/* +extended_format_parse() + +YYYY-MM-DDThh:mm:ss +YYYY-MM-DDThh:mm:ssZ +YYYY-MM-DDThh:mm:ss±hh:mm +YYYY-MM-DDThh:mm:ss±hh +*/ + +static time_t extended_format_parse(const char * str) +{ + int r; + size_t len; + size_t current_index; + uint32_t value; + int year; + int month; + int day; + int hour; + int minute; + int second; + int offset; + int apply_offset; + struct tm ts; + int local_time; + time_t result; + + len = strlen(str); + current_index = 0; + + r = mailimf_number_parse(str, len, ¤t_index, &value); + if (r != MAILIMF_NO_ERROR) + return (time_t) -1; + + year = value; + + r = mailimf_char_parse(str, len, ¤t_index, '-'); + if (r != MAILIMF_NO_ERROR) + return (time_t) -1; + + r = mailimf_number_parse(str, len, ¤t_index, &value); + if (r != MAILIMF_NO_ERROR) + return (time_t) -1; + + month = value; + + r = mailimf_char_parse(str, len, ¤t_index, '-'); + if (r != MAILIMF_NO_ERROR) + return (time_t) -1; + + r = mailimf_number_parse(str, len, ¤t_index, &value); + if (r != MAILIMF_NO_ERROR) + return (time_t) -1; + + day = value; + + r = mailimf_char_parse(str, len, ¤t_index, 'T'); + if (r != MAILIMF_NO_ERROR) + return (time_t) -1; + + r = mailimf_number_parse(str, len, ¤t_index, &value); + if (r != MAILIMF_NO_ERROR) + return (time_t) -1; + + hour = value; + + r = mailimf_char_parse(str, len, ¤t_index, ':'); + if (r != MAILIMF_NO_ERROR) + return (time_t) -1; + + r = mailimf_number_parse(str, len, ¤t_index, &value); + if (r != MAILIMF_NO_ERROR) + return (time_t) -1; + + minute = value; + + r = mailimf_char_parse(str, len, ¤t_index, ':'); + if (r != MAILIMF_NO_ERROR) + return (time_t) -1; + + r = mailimf_number_parse(str, len, ¤t_index, &value); + if (r != MAILIMF_NO_ERROR) + return (time_t) -1; + + second = value; + + apply_offset = 0; + offset = 0; + r = mailimf_char_parse(str, len, ¤t_index, 'Z'); + if (r == MAILIMF_NO_ERROR) { + /* utc */ + offset = 0; + apply_offset = 1; + } + + if (r != MAILIMF_NO_ERROR) { + r = mailimf_char_parse(str, len, ¤t_index, '+'); + if (r == MAILIMF_NO_ERROR) { + int offset_hour; + int offset_minute; + + r = mailimf_number_parse(str, len, ¤t_index, &value); + if (r != MAILIMF_NO_ERROR) + return (time_t) -1; + + offset_hour = value; + + r = mailimf_char_parse(str, len, ¤t_index, ':'); + if (r == MAILIMF_NO_ERROR) { + r = mailimf_number_parse(str, len, ¤t_index, &value); + if (r != MAILIMF_NO_ERROR) + return (time_t) -1; + + offset_minute = value; + } + else { + offset_minute = 0; + } + + offset = offset_hour * 3600 + offset_minute; + apply_offset = 1; + } + } + + if (r != MAILIMF_NO_ERROR) { + + r = mailimf_char_parse(str, len, ¤t_index, '-'); + if (r == MAILIMF_NO_ERROR) { + int offset_hour; + int offset_minute; + + r = mailimf_number_parse(str, len, ¤t_index, &value); + if (r != MAILIMF_NO_ERROR) + return (time_t) -1; + + offset_hour = value; + + r = mailimf_char_parse(str, len, ¤t_index, ':'); + if (r == MAILIMF_NO_ERROR) { + r = mailimf_number_parse(str, len, ¤t_index, &value); + if (r != MAILIMF_NO_ERROR) + return (time_t) -1; + + offset_minute = value; + } + else { + offset_minute = 0; + } + + offset = offset_hour * 3600 + offset_minute; + apply_offset = 1; + } + } + + local_time = 0; + if (r != MAILIMF_NO_ERROR) { + local_time = 1; + } + + memset(&ts, 0, sizeof(ts)); + + ts.tm_sec = second; + ts.tm_min = minute; + ts.tm_hour = hour; + ts.tm_mday = day; + ts.tm_mon = month - 1; + ts.tm_year = year - 1900; + + if (local_time) { + result = mktime(&ts); + } + else { + result = mail_mkgmtime(&ts); + if (apply_offset) + result -= offset; + } + + return result; +} + +time_t newsfeed_iso8601_date_parse(const char * str) +{ + time_t value; + + value = basic_format_parse(str); + if (value != (time_t) -1) { + return value; + } + + value = extended_format_parse(str); + if (value != (time_t) -1) { + return value; + } + + return (time_t) -1; +} diff --git a/Sources/libetpan/low-level/feed/date.h b/Sources/libetpan/low-level/feed/date.h new file mode 100644 index 00000000..a3244bfc --- /dev/null +++ b/Sources/libetpan/low-level/feed/date.h @@ -0,0 +1,38 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef DATE_H +#define DATE_H + +#include + +time_t newsfeed_iso8601_date_parse(char *date); + +#endif /* __DATE_H */ diff --git a/Sources/libetpan/low-level/feed/newsfeed.c b/Sources/libetpan/low-level/feed/newsfeed.c new file mode 100644 index 00000000..13472801 --- /dev/null +++ b/Sources/libetpan/low-level/feed/newsfeed.c @@ -0,0 +1,559 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * Copyright (C) 2006 Andrej Kacian + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "newsfeed.h" + +#include +#include + +#include "newsfeed_private.h" +#include "mailstream.h" +#include "newsfeed_item.h" +#include "parser.h" + +#ifdef HAVE_CURL +#include +#endif + +#ifdef LIBETPAN_REENTRANT +# ifndef WIN32 +# include +# endif +#endif + +#ifdef HAVE_CURL +static int curl_error_convert(int curl_res); +#endif + +/* feed_new() + * Initializes new Feed struct, setting its url and a default timeout. */ +struct newsfeed * newsfeed_new(void) +{ + struct newsfeed * feed; + + feed = malloc(sizeof(* feed)); + if (feed == NULL) + goto err; + + feed->feed_url = NULL; + feed->feed_title = NULL; + feed->feed_description = NULL; + feed->feed_language = NULL; + feed->feed_author = NULL; + feed->feed_generator = NULL; + feed->feed_item_list = carray_new(16); + if (feed->feed_item_list == NULL) + goto free; + feed->feed_response_code = 0; + feed->feed_timeout = 0; + + return feed; + + free: + free(feed); + err: + return NULL; +} + +void newsfeed_free(struct newsfeed * feed) +{ + unsigned int i; + + free(feed->feed_url); + free(feed->feed_title); + free(feed->feed_description); + free(feed->feed_language); + free(feed->feed_author); + free(feed->feed_generator); + + for(i = 0 ; i < carray_count(feed->feed_item_list) ; i ++) { + struct newsfeed_item * item; + + item = carray_get(feed->feed_item_list, i); + newsfeed_item_free(item); + } + + free(feed); +} + +int newsfeed_get_response_code(struct newsfeed * feed) +{ + return feed->feed_response_code; +} + +/* URL */ +int newsfeed_set_url(struct newsfeed * feed, const char * url) +{ + if (url != feed->feed_url) { + char * dup_url; + + if (url == NULL) { + dup_url = NULL; + } + else { + dup_url = strdup(url); + if (dup_url == NULL) + return -1; + } + + free(feed->feed_url); + feed->feed_url = dup_url; + } + + return 0; +} + +const char * newsfeed_get_url(struct newsfeed * feed) +{ + return feed->feed_url; +} + +/* Title */ +int newsfeed_set_title(struct newsfeed * feed, const char * title) +{ + if (title != feed->feed_title) { + char * dup_title; + + if (title == NULL) { + dup_title = NULL; + } + else { + dup_title = strdup(title); + if (dup_title == NULL) + return -1; + } + + free(feed->feed_title); + feed->feed_title = dup_title; + } + + return 0; +} + +const char * newsfeed_get_title(struct newsfeed *feed) +{ + return feed->feed_title; +} + +/* Description */ +int newsfeed_set_description(struct newsfeed * feed, const char * description) +{ + if (description != feed->feed_description) { + char * dup_description; + + if (description == NULL) { + dup_description = NULL; + } + else { + dup_description = strdup(description); + if (dup_description == NULL) + return -1; + } + + free(feed->feed_description); + feed->feed_description = dup_description; + } + + return 0; +} + +const char * newsfeed_get_description(struct newsfeed * feed) +{ + return feed->feed_description; +} + +/* Language */ +int newsfeed_set_language(struct newsfeed * feed, const char * language) +{ + if (language != feed->feed_language) { + char * dup_language; + + if (language == NULL) { + dup_language = NULL; + } + else { + dup_language = strdup(language); + if (dup_language == NULL) + return -1; + } + + free(feed->feed_language); + feed->feed_language = dup_language; + } + + return 0; +} + +const char * newsfeed_get_language(struct newsfeed * feed) +{ + return feed->feed_language; +} + +/* Author */ +int newsfeed_set_author(struct newsfeed * feed, const char * author) +{ + if (author != feed->feed_author) { + char * dup_author; + + if (author == NULL) { + dup_author = NULL; + } + else { + dup_author = strdup(author); + if (dup_author == NULL) + return -1; + } + + free(feed->feed_author); + feed->feed_author = dup_author; + } + + return 0; +} + +const char * newsfeed_get_author(struct newsfeed * feed) +{ + return feed->feed_author; +} + +/* Generator */ +int newsfeed_set_generator(struct newsfeed * feed, const char * generator) +{ + if (generator != feed->feed_generator) { + char * dup_generator; + + if (generator == NULL) { + dup_generator = NULL; + } + else { + dup_generator = strdup(generator); + if (dup_generator == NULL) + return -1; + } + + free(feed->feed_generator); + feed->feed_generator = dup_generator; + } + + return 0; +} + +const char * newsfeed_get_generator(struct newsfeed * feed) +{ + return feed->feed_generator; +} + +void newsfeed_set_date(struct newsfeed * feed, time_t date) +{ + feed->feed_date = date; +} + +time_t newsfeed_get_date(struct newsfeed * feed) +{ + return feed->feed_date; +} + +/* Returns nth item from feed. */ +unsigned int newsfeed_item_list_get_count(struct newsfeed * feed) +{ + return carray_count(feed->feed_item_list); +} + +struct newsfeed_item * newsfeed_get_item(struct newsfeed * feed, unsigned int n) +{ + return carray_get(feed->feed_item_list, n); +} + +/* feed_update() + * Takes initialized feed with url set, fetches the feed from this url, + * updates rest of Feed struct members and returns HTTP response code + * we got from url's server. */ +int newsfeed_update(struct newsfeed * feed, time_t last_update) +{ +#if (defined(HAVE_CURL) && defined(HAVE_EXPAT)) + CURL * eh; + CURLcode curl_res; + struct newsfeed_parser_context * feed_ctx; + unsigned int res; + unsigned int timeout_value; + long response_code; + + if (feed->feed_url == NULL) { + res = NEWSFEED_ERROR_BADURL; + goto err; + } + + /* Init curl before anything else. */ + eh = curl_easy_init(); + if (eh == NULL) { + res = NEWSFEED_ERROR_MEMORY; + goto err; + } + + /* Curl initialized, create parser context now. */ + feed_ctx = malloc(sizeof(* feed_ctx)); + if (feed_ctx == NULL) { + res = NEWSFEED_ERROR_MEMORY; + goto free_eh; + } + + feed_ctx->parser = XML_ParserCreate(NULL); + if (feed_ctx->parser == NULL) { + res = NEWSFEED_ERROR_MEMORY; + goto free_ctx; + } + feed_ctx->depth = 0; + feed_ctx->str = mmap_string_sized_new(256); + if (feed_ctx->str == NULL) { + res = NEWSFEED_ERROR_MEMORY; + goto free_praser; + } + feed_ctx->feed = feed; + feed_ctx->location = 0; + feed_ctx->curitem = NULL; + feed_ctx->error = NEWSFEED_NO_ERROR; + + /* Set initial expat handlers, which will take care of choosing + * correct parser later. */ + newsfeed_parser_set_expat_handlers(feed_ctx); + + if (feed->feed_timeout != 0) + timeout_value = feed->feed_timeout; + else + timeout_value = mailstream_network_delay.tv_sec; + + curl_easy_setopt(eh, CURLOPT_URL, feed->feed_url); + curl_easy_setopt(eh, CURLOPT_NOPROGRESS, 1); +#ifdef CURLOPT_MUTE + curl_easy_setopt(eh, CURLOPT_MUTE, 1); +#endif + curl_easy_setopt(eh, CURLOPT_WRITEFUNCTION, newsfeed_writefunc); + curl_easy_setopt(eh, CURLOPT_WRITEDATA, feed_ctx); + curl_easy_setopt(eh, CURLOPT_FOLLOWLOCATION, 1); + curl_easy_setopt(eh, CURLOPT_MAXREDIRS, 3); + curl_easy_setopt(eh, CURLOPT_TIMEOUT, timeout_value); + curl_easy_setopt(eh, CURLOPT_NOSIGNAL, 1); + curl_easy_setopt(eh, CURLOPT_USERAGENT, "libEtPan!"); + + /* Use HTTP's If-Modified-Since feature, if application provided + * the timestamp of last update. */ + if (last_update != -1) { + curl_easy_setopt(eh, CURLOPT_TIMECONDITION, + CURL_TIMECOND_IFMODSINCE); + curl_easy_setopt(eh, CURLOPT_TIMEVALUE, last_update); + } + +#if LIBCURL_VERSION_NUM >= 0x070a00 + curl_easy_setopt(eh, CURLOPT_SSL_VERIFYPEER, 0); + curl_easy_setopt(eh, CURLOPT_SSL_VERIFYHOST, 0); +#endif + + curl_res = curl_easy_perform(eh); + if (curl_res != 0) { + res = curl_error_convert(curl_res); + goto free_str; + } + + curl_easy_getinfo(eh, CURLINFO_RESPONSE_CODE, &response_code); + + curl_easy_cleanup(eh); + + if (feed_ctx->error != NEWSFEED_NO_ERROR) { + res = feed_ctx->error; + goto free_str; + } + + /* Cleanup, we should be done. */ + mmap_string_free(feed_ctx->str); + XML_ParserFree(feed_ctx->parser); + free(feed_ctx); + + feed->feed_response_code = (int) response_code; + + return NEWSFEED_NO_ERROR;; + + free_str: + mmap_string_free(feed_ctx->str); + free_praser: + XML_ParserFree(feed_ctx->parser); + free_ctx: + free(feed_ctx); + free_eh: + curl_easy_cleanup(eh); + err: + return res; +#else + return NEWSFEED_ERROR_INTERNAL; +#endif +} + +int newsfeed_add_item(struct newsfeed * feed, struct newsfeed_item * item) +{ + return carray_add(feed->feed_item_list, item, NULL); +} + +#ifdef HAVE_CURL +static int curl_error_convert(int curl_res) +{ + switch (curl_res) { + case CURLE_OK: + return NEWSFEED_NO_ERROR; + + case CURLE_UNSUPPORTED_PROTOCOL: + return NEWSFEED_ERROR_UNSUPPORTED_PROTOCOL; + + case CURLE_FAILED_INIT: + case CURLE_LIBRARY_NOT_FOUND: + case CURLE_FUNCTION_NOT_FOUND: + case CURLE_BAD_FUNCTION_ARGUMENT: + case CURLE_BAD_CALLING_ORDER: + case CURLE_UNKNOWN_TELNET_OPTION: + case CURLE_TELNET_OPTION_SYNTAX: + case CURLE_OBSOLETE: + case CURLE_GOT_NOTHING: + case CURLE_INTERFACE_FAILED: + case CURLE_SHARE_IN_USE: + case CURL_LAST: + return NEWSFEED_ERROR_INTERNAL; + + case CURLE_URL_MALFORMAT: + case CURLE_URL_MALFORMAT_USER: + case CURLE_MALFORMAT_USER: + return NEWSFEED_ERROR_BADURL; + + case CURLE_COULDNT_RESOLVE_PROXY: + return NEWSFEED_ERROR_RESOLVE_PROXY; + + case CURLE_COULDNT_RESOLVE_HOST: + return NEWSFEED_ERROR_RESOLVE_HOST; + + case CURLE_COULDNT_CONNECT: + return NEWSFEED_ERROR_CONNECT; + + case CURLE_FTP_WEIRD_SERVER_REPLY: + case CURLE_FTP_WEIRD_PASS_REPLY: + case CURLE_FTP_WEIRD_USER_REPLY: + case CURLE_FTP_WEIRD_PASV_REPLY: + case CURLE_FTP_WEIRD_227_FORMAT: + return NEWSFEED_ERROR_PROTOCOL; + + case CURLE_FTP_ACCESS_DENIED: + return NEWSFEED_ERROR_ACCESS; + + case CURLE_FTP_USER_PASSWORD_INCORRECT: + case CURLE_BAD_PASSWORD_ENTERED: + case CURLE_LOGIN_DENIED: + return NEWSFEED_ERROR_AUTHENTICATION; + + case CURLE_FTP_CANT_GET_HOST: + case CURLE_FTP_CANT_RECONNECT: + case CURLE_FTP_COULDNT_SET_BINARY: + case CURLE_FTP_QUOTE_ERROR: + case CURLE_FTP_COULDNT_SET_ASCII: + case CURLE_FTP_PORT_FAILED: + case CURLE_FTP_COULDNT_USE_REST: + case CURLE_FTP_COULDNT_GET_SIZE: + return NEWSFEED_ERROR_FTP; + + case CURLE_PARTIAL_FILE: + return NEWSFEED_ERROR_PARTIAL_FILE; + + case CURLE_FTP_COULDNT_RETR_FILE: + case CURLE_FILE_COULDNT_READ_FILE: + case CURLE_BAD_DOWNLOAD_RESUME: + case CURLE_FILESIZE_EXCEEDED: + return NEWSFEED_ERROR_FETCH; + + case CURLE_FTP_COULDNT_STOR_FILE: + case CURLE_HTTP_POST_ERROR: + return NEWSFEED_ERROR_PUT; + + case CURLE_OUT_OF_MEMORY: + return NEWSFEED_ERROR_MEMORY; + + case CURLE_OPERATION_TIMEOUTED: + return NEWSFEED_ERROR_STREAM; + + case CURLE_HTTP_RANGE_ERROR: + case CURLE_HTTP_RETURNED_ERROR: + case CURLE_TOO_MANY_REDIRECTS: + case CURLE_BAD_CONTENT_ENCODING: + return NEWSFEED_ERROR_HTTP; + + case CURLE_LDAP_CANNOT_BIND: + case CURLE_LDAP_SEARCH_FAILED: + case CURLE_LDAP_INVALID_URL: + return NEWSFEED_ERROR_LDAP; + + case CURLE_ABORTED_BY_CALLBACK: + return NEWSFEED_ERROR_CANCELLED; + + case CURLE_FTP_WRITE_ERROR: + case CURLE_SEND_ERROR: + case CURLE_RECV_ERROR: + case CURLE_READ_ERROR: + case CURLE_WRITE_ERROR: + case CURLE_SEND_FAIL_REWIND: + return NEWSFEED_ERROR_STREAM; + + case CURLE_SSL_CONNECT_ERROR: + case CURLE_SSL_PEER_CERTIFICATE: + case CURLE_SSL_ENGINE_NOTFOUND: + case CURLE_SSL_ENGINE_SETFAILED: + case CURLE_SSL_CERTPROBLEM: + case CURLE_SSL_CIPHER: +#if LIBCURL_VERSION_NUM < 0x073e00 + case CURLE_SSL_CACERT: +#endif + case CURLE_FTP_SSL_FAILED: + case CURLE_SSL_ENGINE_INITFAILED: + return NEWSFEED_ERROR_SSL; + + default: + return NEWSFEED_ERROR_INTERNAL; + } +} +#endif + +void newsfeed_set_timeout(struct newsfeed * feed, unsigned int timeout) +{ + feed->feed_timeout = timeout; +} + +unsigned int newsfeed_get_timeout(struct newsfeed * feed) +{ + return feed->feed_timeout; +} diff --git a/Sources/libetpan/low-level/feed/newsfeed.h b/Sources/libetpan/low-level/feed/newsfeed.h new file mode 100644 index 00000000..c8e4ebcd --- /dev/null +++ b/Sources/libetpan/low-level/feed/newsfeed.h @@ -0,0 +1,76 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * Copyright (C) 2006 Andrej Kacian + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef NEWSFEED_H +#define NEWSFEED_H + +#include +#include +#include + +struct newsfeed * newsfeed_new(void); +void newsfeed_free(struct newsfeed * feed); + +int newsfeed_get_response_code(struct newsfeed * feed); + +int newsfeed_set_url(struct newsfeed * feed, const char * url); +const char * newsfeed_get_url(struct newsfeed * feed); + +int newsfeed_set_title(struct newsfeed * feed, const char * title); +const char * newsfeed_get_title(struct newsfeed * feed); + +int newsfeed_set_description(struct newsfeed * feed, const char * description); +const char * newsfeed_get_description(struct newsfeed * feed); + +int newsfeed_set_language(struct newsfeed * feed, const char * language); +const char * newsfeed_get_language(struct newsfeed * feed); + +int newsfeed_set_author(struct newsfeed * feed, const char * author); +const char * newsfeed_get_author(struct newsfeed * feed); + +int newsfeed_set_generator(struct newsfeed * feed, const char * generator); +const char * newsfeed_get_generator(struct newsfeed * feed); + +unsigned int newsfeed_item_list_get_count(struct newsfeed * feed); +struct newsfeed_item * newsfeed_get_item(struct newsfeed * feed, unsigned int n); + +void newsfeed_set_date(struct newsfeed * feed, time_t date); +time_t newsfeed_get_date(struct newsfeed * feed); + +void newsfeed_set_timeout(struct newsfeed * feed, unsigned int timeout); +unsigned int newsfeed_get_timeout(struct newsfeed * feed); + +int newsfeed_add_item(struct newsfeed * feed, struct newsfeed_item * item); + +int newsfeed_update(struct newsfeed * feed, time_t last_update); + +#endif /* NEWSFEED_H */ diff --git a/Sources/libetpan/low-level/feed/newsfeed_item.c b/Sources/libetpan/low-level/feed/newsfeed_item.c new file mode 100644 index 00000000..ad9e1c6b --- /dev/null +++ b/Sources/libetpan/low-level/feed/newsfeed_item.c @@ -0,0 +1,272 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * Copyright (C) 2006 Andrej Kacian + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "newsfeed_item.h" + +#include "newsfeed.h" +#include "newsfeed_item_enclosure.h" + +#include +#include + +/* newsfeed_item_new() + * Initializes a new empty newsfeed_item struct, setting its parent feed, + * if supplied. */ +struct newsfeed_item * newsfeed_item_new(struct newsfeed * feed) +{ + struct newsfeed_item * item; + + item = malloc(sizeof(* item)); + if (item == NULL) + return NULL; + + item->fi_url = NULL; + item->fi_title = NULL; + item->fi_summary = NULL; + item->fi_text = NULL; + item->fi_author = NULL; + item->fi_id = NULL; + + item->fi_date_published = 0; + item->fi_date_modified = 0; + item->fi_enclosure = NULL; + + item->fi_feed = feed; + + return item; +} + +void newsfeed_item_free(struct newsfeed_item * item) +{ + if (item->fi_enclosure != NULL) + newsfeed_item_enclosure_free(item->fi_enclosure); + free(item->fi_id); + free(item->fi_author); + free(item->fi_text); + free(item->fi_summary); + free(item->fi_title); + free(item->fi_url); + + free(item); +} + +struct newsfeed * newsfeed_item_get_feed(struct newsfeed_item * item) +{ + return item->fi_feed; +} + +const char * newsfeed_item_get_url(struct newsfeed_item * item) +{ + return item->fi_url; +} + +int newsfeed_item_set_url(struct newsfeed_item *item, const char * url) +{ + if (url != item->fi_url) { + char * dup_url; + + if (url == NULL) { + dup_url = NULL; + } + else { + dup_url = strdup(url); + if (dup_url == NULL) + return -1; + } + + free(item->fi_url); + item->fi_url = dup_url; + } + + return 0; +} + +const char * newsfeed_item_get_title(struct newsfeed_item * item) +{ + return item->fi_title; +} + +int newsfeed_item_set_title(struct newsfeed_item * item, const char * title) +{ + if (title != item->fi_title) { + char * dup_title; + + if (title == NULL) { + dup_title = NULL; + } + else { + dup_title = strdup(title); + if (dup_title == NULL) + return -1; + } + + free(item->fi_title); + item->fi_title = dup_title; + } + + return 0; +} + +const char * newsfeed_item_get_summary(struct newsfeed_item * item) +{ + return item->fi_summary; +} + +int newsfeed_item_set_summary(struct newsfeed_item * item, const char * summary) +{ + if (summary != item->fi_summary) { + char * dup_summary; + + if (summary == NULL) { + dup_summary = NULL; + } + else { + dup_summary = strdup(summary); + if (dup_summary == NULL) + return -1; + } + + free(item->fi_summary); + item->fi_summary = dup_summary; + } + + return 0; +} + +const char * newsfeed_item_get_text(struct newsfeed_item * item) +{ + return item->fi_text; +} + +int newsfeed_item_set_text(struct newsfeed_item * item, const char * text) +{ + if (text != item->fi_text) { + char * dup_text; + + if (text == NULL) { + dup_text = NULL; + } + else { + dup_text = strdup(text); + if (dup_text == NULL) + return -1; + } + + free(item->fi_text); + item->fi_text = dup_text; + } + + return 0; +} + +const char * newsfeed_item_get_author(struct newsfeed_item * item) +{ + return item->fi_author; +} + +int newsfeed_item_set_author(struct newsfeed_item * item, const char * author) +{ + if (author != item->fi_author) { + char * dup_author; + + if (author == NULL) { + dup_author = NULL; + } + else { + dup_author = strdup(author); + if (dup_author == NULL) + return -1; + } + + free(item->fi_author); + item->fi_author = dup_author; + } + + return 0; +} + +const char * newsfeed_item_get_id(struct newsfeed_item * item) +{ + return item->fi_id; +} + +int newsfeed_item_set_id(struct newsfeed_item * item, const char * id) +{ + if (id != item->fi_id) { + char * dup_id; + + if (id == NULL) { + dup_id = NULL; + } + else { + dup_id = strdup(id); + if (dup_id == NULL) + return -1; + } + + free(item->fi_id); + item->fi_id = dup_id; + } + + return 0; +} + +time_t newsfeed_item_get_date_published(struct newsfeed_item * item) +{ + return item->fi_date_published; +} + +void newsfeed_item_set_date_published(struct newsfeed_item * item, time_t date) +{ + item->fi_date_published = date; +} + +time_t newsfeed_item_get_date_modified(struct newsfeed_item * item) +{ + return item->fi_date_modified; +} + +void newsfeed_item_set_date_modified(struct newsfeed_item * item, time_t date) +{ + item->fi_date_modified = date; +} + +struct newsfeed_item_enclosure * newsfeed_item_get_enclosure(struct newsfeed_item * item) +{ + return item->fi_enclosure; +} + +void newsfeed_item_set_enclosure(struct newsfeed_item * item, + struct newsfeed_item_enclosure * enclosure) +{ + item->fi_enclosure = enclosure; +} diff --git a/Sources/libetpan/low-level/feed/newsfeed_item.h b/Sources/libetpan/low-level/feed/newsfeed_item.h new file mode 100644 index 00000000..e73371ec --- /dev/null +++ b/Sources/libetpan/low-level/feed/newsfeed_item.h @@ -0,0 +1,71 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * Copyright (C) 2006 Andrej Kacian + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef NEWSFEED_ITEM_H +#define NEWSFEED_ITEM_H + +#include + +struct newsfeed_item * newsfeed_item_new(struct newsfeed * feed); +void newsfeed_item_free(struct newsfeed_item * item); + +struct newsfeed * newsfeed_item_get_feed(struct newsfeed_item * item); + +const char * newsfeed_item_get_url(struct newsfeed_item * item); +int newsfeed_item_set_url(struct newsfeed_item * item, const char * url); + +const char * newsfeed_item_get_title(struct newsfeed_item * item); +int newsfeed_item_set_title(struct newsfeed_item * item, const char * title); + +const char * newsfeed_item_get_summary(struct newsfeed_item * item); +int newsfeed_item_set_summary(struct newsfeed_item * item, const char * summary); + +const char * newsfeed_item_get_text(struct newsfeed_item * item); +int newsfeed_item_set_text(struct newsfeed_item * item, const char * text); + +const char * newsfeed_item_get_author(struct newsfeed_item * item); +int newsfeed_item_set_author(struct newsfeed_item * item, const char * author); + +const char * newsfeed_item_get_id(struct newsfeed_item * item); +int newsfeed_item_set_id(struct newsfeed_item * item, const char * id); + +time_t newsfeed_item_get_date_published(struct newsfeed_item * item); +void newsfeed_item_set_date_published(struct newsfeed_item * item, time_t date); + +time_t newsfeed_item_get_date_modified(struct newsfeed_item * item); +void newsfeed_item_set_date_modified(struct newsfeed_item * item, time_t date); + +struct newsfeed_item_enclosure * newsfeed_item_get_enclosure(struct newsfeed_item * item); +void newsfeed_item_set_enclosure(struct newsfeed_item * item, + struct newsfeed_item_enclosure * enclosure); + +#endif /* __FEEDITEM_H */ diff --git a/Sources/libetpan/low-level/feed/newsfeed_item_enclosure.c b/Sources/libetpan/low-level/feed/newsfeed_item_enclosure.c new file mode 100644 index 00000000..13a8735a --- /dev/null +++ b/Sources/libetpan/low-level/feed/newsfeed_item_enclosure.c @@ -0,0 +1,124 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "newsfeed_item_enclosure.h" + +#include +#include + +struct newsfeed_item_enclosure * newsfeed_item_enclosure_new(void) +{ + struct newsfeed_item_enclosure * enclosure; + + enclosure = malloc(sizeof(* enclosure)); + if (enclosure == NULL) + goto err; + + enclosure->fie_url = NULL; + enclosure->fie_type = NULL; + enclosure->fie_size = 0; + + return enclosure; + + err: + return NULL; +} + +void newsfeed_item_enclosure_free(struct newsfeed_item_enclosure * enclosure) +{ + free(enclosure->fie_url); + free(enclosure->fie_type); + free(enclosure); +} + +char * newsfeed_item_enclosure_get_url(struct newsfeed_item_enclosure * enclosure) +{ + return enclosure->fie_url; +} + +int newsfeed_item_enclosure_set_url(struct newsfeed_item_enclosure * enclosure, + const char * url) +{ + if (url != enclosure->fie_url) { + char * dup_url; + + if (url == NULL) { + dup_url = NULL; + } + else { + dup_url = strdup(url); + if (dup_url == NULL) + return -1; + } + + free(enclosure->fie_url); + enclosure->fie_url = dup_url; + } + + return 0; +} + +char * newsfeed_item_enclosure_get_type(struct newsfeed_item_enclosure * enclosure) +{ + return enclosure->fie_type; +} + +int newsfeed_item_enclosure_set_type(struct newsfeed_item_enclosure * enclosure, + const char * type) +{ + if (type != enclosure->fie_type) { + char * dup_type; + + if (type == NULL) { + dup_type = NULL; + } + else { + dup_type = strdup(type); + if (dup_type == NULL) + return -1; + } + + free(enclosure->fie_type); + enclosure->fie_type = dup_type; + } + + return 0; +} + +size_t newsfeed_item_enclosure_get_size(struct newsfeed_item_enclosure * enclosure) +{ + return enclosure->fie_size; +} + +void newsfeed_item_enclosure_set_size(struct newsfeed_item_enclosure * enclosure, + size_t size) +{ + enclosure->fie_size = size; +} diff --git a/Sources/libetpan/low-level/feed/newsfeed_item_enclosure.h b/Sources/libetpan/low-level/feed/newsfeed_item_enclosure.h new file mode 100644 index 00000000..8c37271f --- /dev/null +++ b/Sources/libetpan/low-level/feed/newsfeed_item_enclosure.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef NEWSFEED_ITEM_ENCLOSURE_H + +#define NEWSFEED_ITEM_ENCLOSURE_H + +#include + +struct newsfeed_item_enclosure * newsfeed_item_enclosure_new(void); +void newsfeed_item_enclosure_free(struct newsfeed_item_enclosure * enclosure); + +char * newsfeed_item_enclosure_get_url(struct newsfeed_item_enclosure * enclosure); +int newsfeed_item_enclosure_set_url(struct newsfeed_item_enclosure * enclosure, + const char * url); + +char * newsfeed_item_enclosure_get_type(struct newsfeed_item_enclosure * enclosure); +int newsfeed_item_enclosure_set_type(struct newsfeed_item_enclosure * enclosure, + const char * type); + +size_t newsfeed_item_enclosure_get_size(struct newsfeed_item_enclosure * enclosure); +void newsfeed_item_enclosure_set_size(struct newsfeed_item_enclosure * enclosure, + size_t size); + +#endif diff --git a/Sources/libetpan/low-level/feed/newsfeed_private.c b/Sources/libetpan/low-level/feed/newsfeed_private.c new file mode 100644 index 00000000..4e849247 --- /dev/null +++ b/Sources/libetpan/low-level/feed/newsfeed_private.c @@ -0,0 +1,79 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "newsfeed_private.h" + +#include + +#include "mailimf.h" +#include "timeutils.h" + +static inline time_t get_date(struct mailimf_date_time * date_time) +{ + struct tm tmval; + time_t timeval; + + tmval.tm_sec = date_time->dt_sec; + tmval.tm_min = date_time->dt_min; + tmval.tm_hour = date_time->dt_hour; + tmval.tm_sec = date_time->dt_sec; + tmval.tm_mday = date_time->dt_day; + tmval.tm_mon = date_time->dt_month - 1; + tmval.tm_year = date_time->dt_year - 1900; + + timeval = mail_mkgmtime(&tmval); + + timeval -= date_time->dt_zone * 36; + + return timeval; +} + +time_t newsfeed_rfc822_date_parse(char * text) +{ + time_t date; + struct mailimf_date_time * date_time; + size_t current_pos; + int r; + + date = (time_t) -1; + current_pos = 0; + r = mailimf_date_time_parse(text, strlen(text), + ¤t_pos, &date_time); + if (r == MAILIMF_NO_ERROR) { + date = get_date(date_time); + mailimf_date_time_free(date_time); + } + + return date; +} diff --git a/Sources/libetpan/low-level/feed/newsfeed_private.h b/Sources/libetpan/low-level/feed/newsfeed_private.h new file mode 100644 index 00000000..2c6ba2c9 --- /dev/null +++ b/Sources/libetpan/low-level/feed/newsfeed_private.h @@ -0,0 +1,59 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef NEWSFEED_PRIVATE_H + +#define NEWSFEED_PRIVATE_H + +#include "newsfeed_types.h" +#include "mmapstring.h" + +#ifdef HAVE_EXPAT +#include +#endif + +struct newsfeed_parser_context { + unsigned int depth; + unsigned int location; + MMAPString *str; + + struct newsfeed * feed; + struct newsfeed_item * curitem; + + int error; + +#ifdef HAVE_EXPAT + void * parser; +#endif +}; + +time_t newsfeed_rfc822_date_parse(char * text); + +#endif diff --git a/Sources/libetpan/low-level/feed/newsfeed_types.h b/Sources/libetpan/low-level/feed/newsfeed_types.h new file mode 100644 index 00000000..0ffe71af --- /dev/null +++ b/Sources/libetpan/low-level/feed/newsfeed_types.h @@ -0,0 +1,96 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef NEWSFEED_TYPES_H + +#define NEWSFEED_TYPES_H + +#include +#include + +enum { + NEWSFEED_NO_ERROR = 0, + NEWSFEED_ERROR_CANCELLED, + NEWSFEED_ERROR_INTERNAL, + NEWSFEED_ERROR_BADURL, + NEWSFEED_ERROR_RESOLVE_PROXY, + NEWSFEED_ERROR_RESOLVE_HOST, + NEWSFEED_ERROR_CONNECT, + NEWSFEED_ERROR_STREAM, + NEWSFEED_ERROR_PROTOCOL, + NEWSFEED_ERROR_PARSE, + NEWSFEED_ERROR_ACCESS, + NEWSFEED_ERROR_AUTHENTICATION, + NEWSFEED_ERROR_FTP, + NEWSFEED_ERROR_PARTIAL_FILE, + NEWSFEED_ERROR_FETCH, + NEWSFEED_ERROR_HTTP, + NEWSFEED_ERROR_FILE, + NEWSFEED_ERROR_PUT, + NEWSFEED_ERROR_MEMORY, + NEWSFEED_ERROR_SSL, + NEWSFEED_ERROR_LDAP, + NEWSFEED_ERROR_UNSUPPORTED_PROTOCOL +}; + +struct newsfeed { + char * feed_url; + char * feed_title; + char * feed_description; + char * feed_language; + char * feed_author; + char * feed_generator; + time_t feed_date; + carray * feed_item_list; + int feed_response_code; + + unsigned int feed_timeout; +}; + +struct newsfeed_item { + char * fi_url; + char * fi_title; + char * fi_summary; + char * fi_text; + char * fi_author; + char * fi_id; + time_t fi_date_published; + time_t fi_date_modified; + struct newsfeed * fi_feed; /* owner */ + struct newsfeed_item_enclosure * fi_enclosure; +}; + +struct newsfeed_item_enclosure { + char * fie_url; + char * fie_type; + size_t fie_size; +}; + +#endif diff --git a/Sources/libetpan/low-level/feed/parser.c b/Sources/libetpan/low-level/feed/parser.c new file mode 100644 index 00000000..99177962 --- /dev/null +++ b/Sources/libetpan/low-level/feed/parser.c @@ -0,0 +1,451 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * Copyright (C) 2006 Andrej Kacian + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "parser.h" + +#include +#include +#include +#include + +#ifdef HAVE_ICONV +#include +#endif + +#include "newsfeed.h" + +#include "newsfeed_private.h" +#include "parser_rss20.h" +#include "parser_rdf.h" +#include "parser_atom10.h" +#include "parser_atom03.h" + +enum { + FEED_TYPE_NONE, + FEED_TYPE_RDF, + FEED_TYPE_RSS_20, + FEED_TYPE_ATOM_03, + FEED_TYPE_ATOM_10 +}; + +#ifdef HAVE_EXPAT +static void handler_set(XML_Parser parser, unsigned int type) +{ + if (parser == NULL) + return; + + switch(type) { + case FEED_TYPE_RSS_20: + XML_SetElementHandler(parser, + newsfeed_parser_rss20_start, + newsfeed_parser_rss20_end); + break; + + case FEED_TYPE_RDF: + XML_SetElementHandler(parser, + newsfeed_parser_rdf_start, + newsfeed_parser_rdf_end); + break; + + case FEED_TYPE_ATOM_10: + XML_SetElementHandler(parser, + newsfeed_parser_atom10_start, + newsfeed_parser_atom10_end); + break; + + case FEED_TYPE_ATOM_03: + XML_SetElementHandler(parser, + newsfeed_parser_atom03_start, + newsfeed_parser_atom03_end); + break; + } +} + +static void elparse_start_chooser(void * data, + const char * el, const char ** attr) +{ + struct newsfeed_parser_context * ctx; + unsigned int feedtype; + XML_Parser parser; + + ctx = (struct newsfeed_parser_context *) data; + feedtype = FEED_TYPE_NONE; + + if (ctx->depth == 0) { + /* RSS 2.0 detected */ + if (strcasecmp(el, "rss") == 0) { + feedtype = FEED_TYPE_RSS_20; + } + else if (strcasecmp(el, "rdf:RDF") == 0) { + feedtype = FEED_TYPE_RDF; + } + else if (strcasecmp(el, "feed") == 0) { + const char * version; + + /* ATOM feed detected, let's check version */ + version = newsfeed_parser_get_attribute_value(attr, "xmlns"); + if (version != NULL) { + if (strcmp(version, "http://www.w3.org/2005/Atom") == 0) + feedtype = FEED_TYPE_ATOM_10; + else + feedtype = FEED_TYPE_ATOM_03; + } + } + } + + parser = ctx->parser; + handler_set(parser, feedtype); + + ctx->depth ++; +} + +static void elparse_end_dummy(void * data, const char * el) +{ + struct newsfeed_parser_context * ctx; + + ctx = (struct newsfeed_parser_context *) data; + + mmap_string_truncate(ctx->str, 0); + + ctx->depth --; +} + +static void chparse(void * data, const char * s, int len) +{ + struct newsfeed_parser_context * ctx; + char * pt; + int i; + int blank; + + blank = 1; + ctx = (struct newsfeed_parser_context *) data; + + /* check if the string is blank, ... */ + for(i = 0, pt = (XML_Char *) s ; i < len ; i ++) { + if ((* pt != ' ') && (* pt != '\t')) + blank = 0; + pt ++; + } + + /* ... because we do not want to deal with blank strings */ + if (blank) + return; + + for(i = 0, pt = (XML_Char *) s ; i < len ; i ++) { + /* do not append newline as first char of our string */ + if ((* pt != '\n') || (ctx->str->len != 0)) { + if (mmap_string_append_c(ctx->str, * pt) == NULL) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + pt ++; + } + } +} + +#define CHARSIZEUTF32 4 + +enum { + LEP_ICONV_OK, + LEP_ICONV_FAILED, + LEP_ICONV_ILSEQ, + LEP_ICONV_INVAL, + LEP_ICONV_UNKNOWN +}; + +static int iconv_utf32_char(iconv_t cd, const char * inbuf, size_t insize, + uint32_t * p_value) +{ +#ifdef HAVE_ICONV + size_t outsize; + unsigned char outbuf[CHARSIZEUTF32]; + char * outbufp; + int r; + + outsize = sizeof(outbuf); + outbufp = (char *) outbuf; +#ifdef HAVE_ICONV_PROTO_CONST + r = iconv(cd, (const char **) &inbuf, &insize, + &outbufp, &outsize); +#else + r = iconv(cd, (char **) &inbuf, &insize, &outbufp, &outsize); +#endif + if (r == -1) { + iconv (cd, 0, 0, 0, 0); + switch (errno) { + case EILSEQ: + return LEP_ICONV_ILSEQ; + case EINVAL: + return LEP_ICONV_INVAL; + default: + return LEP_ICONV_UNKNOWN; + } + } + else { + uint32_t value; + unsigned int i; + + if ((insize > 0) || (outsize > 0)) + return LEP_ICONV_FAILED; + + value = 0; + for(i = 0 ; i < sizeof(outbuf) ; i ++) { + value = (value << 8) + outbuf[i]; + } + + * p_value = value; + return LEP_ICONV_OK; + } +#else + return LEP_ICONV_FAILED; +#endif +} + +/* return 1 if conversion function is needed */ +static int setup_unknown_encoding(const char * charset, XML_Encoding * info) +{ + iconv_t cd; + int flag; + char buf[4]; + unsigned int i; + int r; + + cd = iconv_open("UTF-32BE", charset); + if (cd == (iconv_t) (-1)) { + return -1; + } + + flag = 0; + for (i = 0; i < 256; i++) { + /* *** first char *** */ + uint32_t value; + + buf[0] = i; + info->map[i] = 0; + r = iconv_utf32_char(cd, buf, 1, &value); + if (r == LEP_ICONV_OK) { + info->map[i] = value; + } + else if (r != LEP_ICONV_INVAL) { + /* do nothing */ + } + else /* r == LEP_ICONV_INVAL */ { + unsigned int j; + + for (j = 0; j < 256; j++) { + /* *** second char *** */ + buf[1] = j; + r = iconv_utf32_char(cd, buf, 2, &value); + if (r == LEP_ICONV_OK) { + flag = 1; + info->map[i] = -2; + break; + } + else if (r != LEP_ICONV_INVAL) { + /* do nothing */ + } + else /* r == LEP_ICONV_INVAL */ { + unsigned int k; + + for (k = 0; k < 256; k++) { + /* *** third char *** */ + buf[2] = k; + r = iconv_utf32_char(cd, buf, 3, &value); + if (r == LEP_ICONV_OK) { + flag = 1; + info->map[i] = -3; + break; + } + } + } + } + } + } + + iconv_close(cd); + + return flag; +} + +struct unknown_encoding_data { + char * charset; + iconv_t cd; + char map[256]; +}; + +static int unknown_encoding_convert(void * data, const char * s) +{ + int r; + struct unknown_encoding_data * enc_data; + size_t insize; + uint32_t value; + + enc_data = data; + + if (s == NULL) + goto err; + + insize = -enc_data->map[(unsigned char) s[0]]; + r = iconv_utf32_char(enc_data->cd, s, insize, &value); + if (r != LEP_ICONV_OK) + return -1; + + return value; + + err: + return -1; +} + +static void unknown_encoding_data_free(void * data) +{ + struct unknown_encoding_data * enc_data; + + enc_data = data; + free(enc_data->charset); + iconv_close(enc_data->cd); + free(enc_data); +} + +static int unknown_encoding_handler(void * encdata, const XML_Char * name, + XML_Encoding * info) +{ + iconv_t cd; + struct unknown_encoding_data * data; + int result; + unsigned int i; + + result = setup_unknown_encoding(name, info); + if (result == 0) { + info->data = NULL; + info->convert = NULL; + info->release = NULL; + return XML_STATUS_OK; + } + + cd = iconv_open("UTF-32BE", name); + if (cd == (iconv_t) -1) { + goto err; + } + + data = malloc(sizeof(* data)); + if (data == NULL) + goto close_iconv; + + data->charset = strdup(name); + if (data->charset == NULL) + goto free_data; + + data->cd = cd; + for(i = 0 ; i < 256 ; i ++) { + data->map[i] = info->map[i]; + } + info->data = data; + info->convert = unknown_encoding_convert; + info->release = unknown_encoding_data_free; + + return XML_STATUS_OK; + + free_data: + free(data); + close_iconv: + iconv_close(cd); + err: + return XML_STATUS_ERROR; +} +#endif + +void newsfeed_parser_set_expat_handlers(struct newsfeed_parser_context * ctx) +{ +#ifdef HAVE_EXPAT + XML_Parser parser; + + parser = ctx->parser; + + XML_SetUserData(parser, (void *) ctx); + + XML_SetElementHandler(parser, + elparse_start_chooser, + elparse_end_dummy); + + XML_SetCharacterDataHandler(parser, + chparse); + + XML_SetUnknownEncodingHandler(parser, unknown_encoding_handler, NULL); +#endif +} + +size_t newsfeed_writefunc(void * ptr, size_t size, size_t nmemb, void * data) +{ +#ifdef HAVE_EXPAT + unsigned int len; + struct newsfeed_parser_context * ctx; + XML_Parser parser; + + ctx = data; + len = size * nmemb; + + if (ctx->error != NEWSFEED_NO_ERROR) { + return 0; + } + + parser = ctx->parser; + XML_Parse(parser, ptr, len, 0); + + if (ctx->error != NEWSFEED_NO_ERROR) { + return 0; + } + + return len; +#endif + return 0; +} + +const char * newsfeed_parser_get_attribute_value(const char ** attr, + const char * name) +{ + unsigned int i; + + if ((attr == NULL) || (name == NULL)) + return NULL; + + for(i = 0 ; attr[i] != NULL && attr[i + 1] != NULL ; i += 2 ) { + if (strcmp(attr[i], name) == 0) + return attr[i + 1]; + } + + /* We haven't found anything. */ + return NULL; +} diff --git a/Sources/libetpan/low-level/feed/parser.h b/Sources/libetpan/low-level/feed/parser.h new file mode 100644 index 00000000..eb29dcd6 --- /dev/null +++ b/Sources/libetpan/low-level/feed/parser.h @@ -0,0 +1,42 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef PARSER_H + +#define PARSER_H + +#include "newsfeed_private.h" + +void newsfeed_parser_set_expat_handlers(struct newsfeed_parser_context * ctx); +size_t newsfeed_writefunc(void * ptr, size_t size, size_t nmemb, void * stream); +const char * newsfeed_parser_get_attribute_value(const char ** attr, + const char * name); + +#endif /* __PARSER_H */ diff --git a/Sources/libetpan/low-level/feed/parser_atom03.c b/Sources/libetpan/low-level/feed/parser_atom03.c new file mode 100644 index 00000000..8e86608c --- /dev/null +++ b/Sources/libetpan/low-level/feed/parser_atom03.c @@ -0,0 +1,260 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * Copyright (C) 2006 Andrej Kacian + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "parser_atom03.h" + +#include + +#include "newsfeed.h" +#include "newsfeed_item.h" +#include "newsfeed_private.h" +#include "date.h" +#include "parser.h" + +enum { + FEED_LOC_ATOM03_NONE, + FEED_LOC_ATOM03_ENTRY, + FEED_LOC_ATOM03_AUTHOR +}; + +void newsfeed_parser_atom03_start(void * data, const char * el, const char ** attr) +{ + struct newsfeed_parser_context * ctx; + int r; + + ctx = data; + + if (ctx->depth == 1) { + if (strcasecmp(el, "entry") == 0) { + /* Start of new feed item found. + * Create a new FeedItem, freeing the one we already have, if any. */ + if( ctx->curitem != NULL ) + newsfeed_item_free(ctx->curitem); + + ctx->curitem = newsfeed_item_new(ctx->feed); + if (ctx->curitem == NULL) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + + ctx->location = FEED_LOC_ATOM03_ENTRY; + } + else if (strcasecmp(el, "author") == 0) { + /* Start of author info for the feed found. + * Set correct location. */ + ctx->location = FEED_LOC_ATOM03_AUTHOR; + } + else { + ctx->location = FEED_LOC_ATOM03_NONE; + } + } + else if (ctx->depth == 2) { + if (strcasecmp(el, "author") == 0) { + /* Start of author info for current feed item. + * Set correct location. */ + ctx->location = FEED_LOC_ATOM03_AUTHOR; + } + else if (strcasecmp(el, "link") == 0) { + const char * url; + + /* Capture item URL, from the "url" XML attribute. */ + url = newsfeed_parser_get_attribute_value(attr, "href"); + r = newsfeed_item_set_url(ctx->curitem, url); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + ctx->location = FEED_LOC_ATOM03_ENTRY; + } + else { + ctx->location = FEED_LOC_ATOM03_ENTRY; + } + } + + ctx->depth ++; +} + +void newsfeed_parser_atom03_end(void *data, const char * el) +{ + struct newsfeed_parser_context * ctx; + struct newsfeed * feed; + char * text; + int r; + + ctx = data; + feed = ctx->feed; + text = ctx->str->str; + + ctx->depth --; + + switch (ctx->depth) { + case 0: + if (strcasecmp(el, "feed") == 0) { + /* We have finished parsing the feed. */ + } + break; + + case 1: + /* decide if we just received , so we can + * add a complete item to feed */ + if (strcasecmp(el, "entry") == 0) { + /* append the complete feed item */ + r = newsfeed_add_item(ctx->feed, ctx->curitem); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + + /* since it's in the linked list, lose this pointer */ + ctx->curitem = NULL; + } + else if (strcasecmp(el, "title") == 0) { + /* so it wasn't end of item */ + r = newsfeed_set_title(feed, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "summary") == 0) { + r = newsfeed_set_description(feed, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "tagline") == 0) { + r = newsfeed_set_description(feed, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "modified") == 0) { + time_t date; + + date = newsfeed_iso8601_date_parse(text); + newsfeed_set_date(feed, date); + } + /* TODO: add more later */ + break; + + case 2: + if( ctx->curitem == NULL ) + break; + + switch(ctx->location) { + case FEED_LOC_ATOM03_ENTRY: + /* We're in feed/entry */ + if (strcasecmp(el, "title") == 0) { + r = newsfeed_item_set_title(ctx->curitem, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "summary") == 0) { + r = newsfeed_item_set_summary(ctx->curitem, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "content") == 0) { + r = newsfeed_item_set_text(ctx->curitem, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "id") == 0) { + r = newsfeed_item_set_id(ctx->curitem, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "issued") == 0) { + time_t date; + + date = newsfeed_iso8601_date_parse(text); + newsfeed_item_set_date_published(ctx->curitem, date); + } + else if (strcasecmp(el, "modified") == 0) { + time_t date; + + date = newsfeed_iso8601_date_parse(text); + newsfeed_item_set_date_modified(ctx->curitem, date); + } + break; + + case FEED_LOC_ATOM03_AUTHOR: + /* We're in feed/author */ + if (strcasecmp(el, "name") == 0) { + r = newsfeed_item_set_author(ctx->curitem, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + /* TODO: construct a "Na Me " string + * from available tags */ + + break; + } + + break; + + case 3: + if (ctx->curitem == NULL) + break; + + if (ctx->location == FEED_LOC_ATOM03_AUTHOR) { + /* We're in feed/entry/author */ + if (strcasecmp(el, "name") == 0) { + r = newsfeed_item_set_author(ctx->curitem, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + } + + break; + } + + mmap_string_truncate(ctx->str, 0); +} diff --git a/Sources/libetpan/low-level/feed/parser_atom03.h b/Sources/libetpan/low-level/feed/parser_atom03.h new file mode 100644 index 00000000..974b943e --- /dev/null +++ b/Sources/libetpan/low-level/feed/parser_atom03.h @@ -0,0 +1,39 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * Copyright (C) 2006 Andrej Kacian + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef PARSER_ATOM03_H +#define PARSER_ATOM03_H + +void newsfeed_parser_atom03_start(void * data, const char * el, const char ** attr); +void newsfeed_parser_atom03_end(void * data, const char * el); + +#endif /* PARSER_ATOM03_H */ diff --git a/Sources/libetpan/low-level/feed/parser_atom10.c b/Sources/libetpan/low-level/feed/parser_atom10.c new file mode 100644 index 00000000..3bf0931c --- /dev/null +++ b/Sources/libetpan/low-level/feed/parser_atom10.c @@ -0,0 +1,253 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * Copyright (C) 2006 Andrej Kacian + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "parser_atom10.h" + +#include + +#include "newsfeed.h" +#include "newsfeed_item.h" +#include "newsfeed_private.h" +#include "date.h" +#include "parser.h" + +enum { + FEED_LOC_ATOM10_NONE, + FEED_LOC_ATOM10_ENTRY, + FEED_LOC_ATOM10_AUTHOR +}; + +void newsfeed_parser_atom10_start(void * data, const char * el, const char ** attr) +{ + struct newsfeed_parser_context * ctx; + int r; + + ctx = data; + + if (ctx->depth == 1) { + if (strcasecmp(el, "entry") == 0) { + /* Start of new feed item found. + * Create a new FeedItem, freeing the one we already have, if any. */ + if( ctx->curitem != NULL ) + newsfeed_item_free(ctx->curitem); + + ctx->curitem = newsfeed_item_new(ctx->feed); + if (ctx->curitem == NULL) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + + ctx->location = FEED_LOC_ATOM10_ENTRY; + } + else if (strcasecmp(el, "author") == 0) { + /* Start of author info for the feed found. + * Set correct location. */ + ctx->location = FEED_LOC_ATOM10_AUTHOR; + } + else { + ctx->location = FEED_LOC_ATOM10_NONE; + } + } + else if (ctx->depth == 2) { + if (strcasecmp(el, "author") == 0) { + /* Start of author info for current feed item. + * Set correct location. */ + ctx->location = FEED_LOC_ATOM10_AUTHOR; + } + else if (strcasecmp(el, "link") == 0) { + const char * url; + + /* Capture item URL, from the "url" XML attribute. */ + url = newsfeed_parser_get_attribute_value(attr, "href"); + r = newsfeed_item_set_url(ctx->curitem, url); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + ctx->location = FEED_LOC_ATOM10_ENTRY; + } + else { + ctx->location = FEED_LOC_ATOM10_ENTRY; + } + } + + ctx->depth ++; +} + +void newsfeed_parser_atom10_end(void *data, const char * el) +{ + struct newsfeed_parser_context * ctx; + struct newsfeed * feed; + char * text; + int r; + + ctx = data; + feed = ctx->feed; + text = ctx->str->str; + + ctx->depth --; + + switch (ctx->depth) { + case 0: + if (strcasecmp(el, "feed") == 0) { + /* We have finished parsing the feed. */ + } + break; + + case 1: + /* decide if we just received , so we can + * add a complete item to feed */ + if (strcasecmp(el, "entry") == 0) { + /* append the complete feed item */ + r = newsfeed_add_item(ctx->feed, ctx->curitem); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + + /* since it's in the linked list, lose this pointer */ + ctx->curitem = NULL; + } + else if (strcasecmp(el, "title") == 0) { + /* so it wasn't end of item */ + r = newsfeed_set_title(feed, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "summary") == 0) { + r = newsfeed_set_description(feed, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "updated") == 0) { + time_t date; + + date = newsfeed_iso8601_date_parse(text); + newsfeed_set_date(feed, date); + } + /* TODO: add more later */ + break; + + case 2: + if( ctx->curitem == NULL ) + break; + + switch(ctx->location) { + case FEED_LOC_ATOM10_ENTRY: + /* We're in feed/entry */ + if (strcasecmp(el, "title") == 0) { + r = newsfeed_item_set_title(ctx->curitem, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "summary") == 0) { + r = newsfeed_item_set_summary(ctx->curitem, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "content") == 0) { + r = newsfeed_item_set_text(ctx->curitem, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "id") == 0) { + r = newsfeed_item_set_id(ctx->curitem, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "issued") == 0) { + time_t date; + + date = newsfeed_iso8601_date_parse(text); + newsfeed_item_set_date_published(ctx->curitem, date); + } + else if (strcasecmp(el, "updated") == 0) { + time_t date; + + date = newsfeed_iso8601_date_parse(text); + newsfeed_item_set_date_modified(ctx->curitem, date); + } + break; + + case FEED_LOC_ATOM10_AUTHOR: + /* We're in feed/author */ + if (strcasecmp(el, "name") == 0) { + r = newsfeed_item_set_author(ctx->curitem, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + /* TODO: construct a "Na Me " string + * from available tags */ + + break; + } + + break; + + case 3: + if (ctx->curitem == NULL) + break; + + if (ctx->location == FEED_LOC_ATOM10_AUTHOR) { + /* We're in feed/entry/author */ + if (strcasecmp(el, "name") == 0) { + r = newsfeed_item_set_author(ctx->curitem, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + } + + break; + } + + mmap_string_truncate(ctx->str, 0); +} diff --git a/Sources/libetpan/low-level/feed/parser_atom10.h b/Sources/libetpan/low-level/feed/parser_atom10.h new file mode 100644 index 00000000..a8bad78d --- /dev/null +++ b/Sources/libetpan/low-level/feed/parser_atom10.h @@ -0,0 +1,39 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * Copyright (C) 2006 Andrej Kacian + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef PARSER_ATOM10_H +#define PARSER_ATOM10_H + +void newsfeed_parser_atom10_start(void * data, const char * el, const char ** attr); +void newsfeed_parser_atom10_end(void * data, const char * el); + +#endif /* PARSER_ATOM10_H */ diff --git a/Sources/libetpan/low-level/feed/parser_rdf.c b/Sources/libetpan/low-level/feed/parser_rdf.c new file mode 100644 index 00000000..b55ea25e --- /dev/null +++ b/Sources/libetpan/low-level/feed/parser_rdf.c @@ -0,0 +1,218 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * Copyright (C) 2006 Andrej Kacian + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "parser_rdf.h" + +#include +#include + +#include "mailimf.h" +#include "newsfeed.h" +#include "newsfeed_item.h" +#include "newsfeed_private.h" +#include "date.h" + +void newsfeed_parser_rdf_start(void * data, const char * el, const char ** attr) +{ + struct newsfeed_parser_context * ctx; + + ctx = data; + if (ctx->depth == 1) { + if (strcasecmp(el, "channel") == 0) { + ctx->location = FEED_LOC_RDF_CHANNEL; + } + else if (strcasecmp(el, "item") == 0) { + if (ctx->curitem != NULL) + newsfeed_item_free(ctx->curitem); + + ctx->curitem = newsfeed_item_new(ctx->feed); + if (ctx->curitem == NULL) { + ctx->error = NEWSFEED_ERROR_MEMORY; + } + ctx->location = FEED_LOC_RDF_ITEM; + } + else { + ctx->location = 0; + } + } + + ctx->depth ++; +} + +void newsfeed_parser_rdf_end(void *data, const char *el) +{ + struct newsfeed_parser_context * ctx; + struct newsfeed * feed; + char * text; + int r; + + ctx = data; + feed = ctx->feed; + text = ctx->str->str; + + ctx->depth --; + + switch (ctx->depth) { + case 0: + if (strcasecmp(el, "rdf") == 0) { + /* we finished parsing the feed */ + } + break; + + case 1: + /* block just ended, so ... */ + if (strcasecmp(el, "item") == 0) { + /* add the complete feed item to our feed struct */ + r = newsfeed_add_item(feed, ctx->curitem); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + + /* since it's in the linked list, lose this pointer */ + ctx->curitem = NULL; + } + break; + + case 2: + switch(ctx->location) { + case FEED_LOC_RDF_CHANNEL: + /* We're inside introductory */ + if (strcasecmp(el, "title") == 0) { + r = newsfeed_set_title(feed, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "description") == 0) { + r = newsfeed_set_description(feed, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "dc:language") == 0) { + r = newsfeed_set_language(feed, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "dc:creator") == 0) { + r = newsfeed_set_author(feed, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "dc:date") == 0) { + time_t date; + + date = newsfeed_iso8601_date_parse(text); + newsfeed_set_date(feed, date); + } + else if (strcasecmp(el, "pubDate") == 0) { + time_t date; + + date = newsfeed_rfc822_date_parse(text); + newsfeed_set_date(feed, date); + } + break; + + case FEED_LOC_RDF_ITEM: + /* We're inside an */ + if (ctx->curitem == NULL) { + break; + } + + /* decide which field did we just get */ + if (strcasecmp(el, "title") == 0) { + r = newsfeed_item_set_title(ctx->curitem, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "dc:creator") == 0) { + r = newsfeed_item_set_author(ctx->curitem, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "description") == 0) { + r = newsfeed_item_set_text(ctx->curitem, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "content:encoded") == 0) { + r = newsfeed_item_set_text(ctx->curitem, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "link") == 0) { + r = newsfeed_item_set_url(ctx->curitem, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "dc:date") == 0) { + time_t date; + + date = newsfeed_iso8601_date_parse(text); + newsfeed_item_set_date_modified(ctx->curitem, date); + } + else if (strcasecmp(el, "pubDate") == 0) { + time_t date; + + date = newsfeed_rfc822_date_parse(text); + newsfeed_item_set_date_modified(ctx->curitem, date); + } + break; + } + + break; + + } + + mmap_string_truncate(ctx->str, 0); +} diff --git a/Sources/libetpan/low-level/feed/parser_rdf.h b/Sources/libetpan/low-level/feed/parser_rdf.h new file mode 100644 index 00000000..857e6a00 --- /dev/null +++ b/Sources/libetpan/low-level/feed/parser_rdf.h @@ -0,0 +1,45 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * Copyright (C) 2006 Andrej Kacian + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef PARSER_RDF_H +#define PARSER_RDF_H + +void newsfeed_parser_rdf_start(void * data, const char * el, const char ** attr); +void newsfeed_parser_rdf_end(void * data, const char * el); + +enum { + FEED_LOC_RDF_NONE, + FEED_LOC_RDF_CHANNEL, + FEED_LOC_RDF_ITEM +}; + +#endif /* __PARSER_RDF_H */ diff --git a/Sources/libetpan/low-level/feed/parser_rss20.c b/Sources/libetpan/low-level/feed/parser_rss20.c new file mode 100644 index 00000000..e8a59883 --- /dev/null +++ b/Sources/libetpan/low-level/feed/parser_rss20.c @@ -0,0 +1,262 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * Copyright (C) 2006 Andrej Kacian + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "parser_rss20.h" + +#include +#include + +#include "newsfeed.h" +#include "newsfeed_item.h" +#include "newsfeed_item_enclosure.h" +#include "date.h" +#include "mailimf.h" +#include "parser.h" +#include "newsfeed_private.h" + +void newsfeed_parser_rss20_start(void *data, const char * el, const char ** attr) +{ + struct newsfeed_parser_context * ctx; + int r; + + ctx = data; + + if (ctx->depth == 2) { + if (strcasecmp(el, "item") == 0) { + if (ctx->curitem != NULL) + newsfeed_item_free(ctx->curitem); + + ctx->curitem = newsfeed_item_new(ctx->feed); + if (ctx->curitem == NULL) { + ctx->error = NEWSFEED_ERROR_MEMORY; + } + } + else { + ctx->location = 0; + } + } + else if (ctx->depth == 3) { + if (strcasecmp(el, "enclosure") == 0) { /* Media enclosure */ + const char * strsize; + const char * url; + const char * type; + struct newsfeed_item_enclosure * enclosure; + size_t size; + + url = newsfeed_parser_get_attribute_value(attr, "url"); + type = newsfeed_parser_get_attribute_value(attr, "type"); + strsize = newsfeed_parser_get_attribute_value(attr, "length"); + size = 0; + if (strsize != NULL ) + size = strtoul(strsize, NULL, 10); + + enclosure = newsfeed_item_enclosure_new(); + r = newsfeed_item_enclosure_set_url(enclosure, url); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + r = newsfeed_item_enclosure_set_type(enclosure, type); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + newsfeed_item_enclosure_set_size(enclosure, size); + + newsfeed_item_set_enclosure(ctx->curitem, enclosure); + } + } + else { + ctx->location = 0; + } + + ctx->depth ++; +} + +void newsfeed_parser_rss20_end(void * data, const char * el) +{ + struct newsfeed_parser_context * ctx; + struct newsfeed * feed; + char * text; + int r; + + ctx = data; + feed = ctx->feed; + text = ctx->str->str; + + ctx->depth--; + + switch (ctx->depth) { + case 0: + if (strcasecmp(el, "rss") == 0) { + /* we finished parsing the feed */ + } + break; + + case 2: + /* decide if we just received , so we can + * add a complete item to feed */ + if (strcasecmp(el, "item") == 0) { + /* append the complete feed item */ + r = newsfeed_add_item(ctx->feed, ctx->curitem); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + } + /* since it's in the linked list, lose this pointer */ + ctx->curitem = NULL; + } + else if (strcasecmp(el, "title") == 0) { + /* so it wasn't end of item */ + r = newsfeed_set_title(feed, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "description") == 0) { + r = newsfeed_set_description(feed, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "dc:language") == 0) { + r = newsfeed_set_language(feed, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "dc:creator") == 0) { + r = newsfeed_set_author(feed, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "admin:generatorAgent") == 0) { + r = newsfeed_set_generator(feed, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "dc:date") == 0) { + time_t date; + + date = newsfeed_iso8601_date_parse(text); + newsfeed_set_date(feed, date); + } + else if (strcasecmp(el, "pubDate") == 0) { + time_t date; + + date = newsfeed_rfc822_date_parse(text); + newsfeed_set_date(feed, date); + } + break; + + case 3: + if ( ctx->curitem == NULL) { + break; + } + + /* decide which field did we just get */ + if (strcasecmp(el, "title") == 0) { + r = newsfeed_item_set_title(ctx->curitem, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "dc:creator") == 0) { + r = newsfeed_item_set_author(ctx->curitem, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "author") == 0) { + r = newsfeed_item_set_author(ctx->curitem, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "description") == 0) { + r = newsfeed_item_set_text(ctx->curitem, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "content:encoded") == 0) { + r = newsfeed_item_set_text(ctx->curitem, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "link") == 0) { + r = newsfeed_item_set_url(ctx->curitem, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "guid") == 0) { + r = newsfeed_item_set_id(ctx->curitem, text); + if (r < 0) { + ctx->error = NEWSFEED_ERROR_MEMORY; + return; + } + } + else if (strcasecmp(el, "dc:date") == 0) { + time_t date; + + date = newsfeed_iso8601_date_parse(text); + newsfeed_item_set_date_modified(ctx->curitem, date); + } + else if (strcasecmp(el, "pubDate") == 0) { + time_t date; + + date = newsfeed_rfc822_date_parse(text); + newsfeed_item_set_date_modified(ctx->curitem, date); + } + break; + } + + mmap_string_truncate(ctx->str, 0); +} diff --git a/Sources/libetpan/low-level/feed/parser_rss20.h b/Sources/libetpan/low-level/feed/parser_rss20.h new file mode 100644 index 00000000..12c3ee67 --- /dev/null +++ b/Sources/libetpan/low-level/feed/parser_rss20.h @@ -0,0 +1,39 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * Copyright (C) 2006 Andrej Kacian + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef PARSER_RSS20_H +#define PARSER_RSS20_H + +void newsfeed_parser_rss20_start(void * data, const char * el, const char ** attr); +void newsfeed_parser_rss20_end(void * data, const char * el); + +#endif /* PARSER_RSS20_H */ diff --git a/Sources/libetpan/low-level/imap/Makefile.am b/Sources/libetpan/low-level/imap/Makefile.am new file mode 100644 index 00000000..9c640378 --- /dev/null +++ b/Sources/libetpan/low-level/imap/Makefile.am @@ -0,0 +1,108 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +EXTRA_DIST = TODO + +etpaninclude_HEADERS = \ + mailimap_helper.h mailimap.h \ + mailimap_types.h mailimap_types_helper.h \ + mailimap_socket.h mailimap_ssl.h \ + mailimap_parser.h \ + mailimap_extension.h mailimap_extension_types.h \ + annotatemore.h annotatemore_types.h \ + acl.h acl_types.h \ + uidplus.h uidplus_types.h \ + quota.h quota_parser.h quota_sender.h quota_types.h \ + idle.h \ + namespace.h namespace_parser.h namespace_sender.h namespace_types.h \ + xlist.h xgmlabels.h xgmmsgid.h xgmthrid.h \ + mailimap_id.h mailimap_id_types.h \ + enable.h condstore.h condstore_types.h \ + qresync.h qresync_types.h \ + mailimap_sort.h mailimap_sort_types.h \ + mailimap_compress.h \ + mailimap_oauth2.h \ + clientid.h + +AM_CPPFLAGS = -I$(top_builddir)/include \ + -I$(top_srcdir)/src/data-types + +noinst_LTLIBRARIES = libimap.la + +libimap_la_SOURCES = \ + mailimap_types.c mailimap_types_helper.c \ + mailimap_sender.h mailimap_sender.c \ + mailimap_keywords.h mailimap_keywords.c \ + mailimap_parser.h mailimap_parser.c \ + mailimap.c \ + mailimap_helper.c \ + mailimap_socket.c \ + mailimap_ssl.c \ + mailimap_print.h mailimap_print.c \ + mailimap_extension.c \ + annotatemore.c \ + annotatemore_parser.h annotatemore_parser.c \ + annotatemore_sender.h annotatemore_sender.c \ + annotatemore_types.c \ + acl.c \ + acl_parser.h acl_parser.c \ + acl_sender.h acl_sender.c \ + acl_types.c \ + uidplus.c \ + uidplus_sender.h uidplus_sender.c \ + uidplus_types.c \ + uidplus_parser.h uidplus_parser.c \ + idle.c idle.h\ + quota.c quota.h \ + quota_parser.c quota_parser.h \ + quota_sender.c quota_sender.h \ + quota_types.c quota_types.h \ + namespace.c namespace.h \ + namespace_parser.c namespace_parser.h \ + namespace_sender.c namespace_sender.h \ + namespace_types.c namespace_types.h \ + xlist.c xlist.h \ + xgmlabels.c xgmlabels.h \ + xgmmsgid.c xgmmsgid.h \ + xgmthrid.c xgmthrid.h \ + mailimap_id.h mailimap_id.c \ + mailimap_id_types.h mailimap_id_types.c \ + mailimap_id_sender.h mailimap_id_sender.c \ + mailimap_id_parser.h mailimap_id_parser.c \ + enable.h enable.c \ + condstore.h condstore.c condstore_types.h condstore_types.c condstore_private.h \ + qresync.h qresync.c qresync_types.h qresync_types.c qresync_private.h \ + mailimap_sort.c mailimap_sort.h \ + mailimap_sort_types.c mailimap_sort_types.h \ + mailimap_compress.c mailimap_compress.h \ + mailimap_oauth2.c mailimap_oauth2.h \ + clientid_sender.c clientid_sender.h \ + clientid.c clientid.h diff --git a/Sources/libetpan/low-level/imap/TODO b/Sources/libetpan/low-level/imap/TODO new file mode 100644 index 00000000..a787a3bc --- /dev/null +++ b/Sources/libetpan/low-level/imap/TODO @@ -0,0 +1,4 @@ +- literal data send progress +- implement draft-16 (rfc 2822 things) +- more efficient parser + diff --git a/Sources/libetpan/low-level/imap/acl.c b/Sources/libetpan/low-level/imap/acl.c new file mode 100644 index 00000000..e896b653 --- /dev/null +++ b/Sources/libetpan/low-level/imap/acl.c @@ -0,0 +1,383 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailimap.h" +#include "mailimap_extension.h" +#include "acl.h" +#include "acl_types.h" +#include "acl_parser.h" +#include "acl_sender.h" + +#include + +LIBETPAN_EXPORT +struct mailimap_extension_api mailimap_extension_acl = { + /* name */ "ACL", + /* extension_id */ MAILIMAP_EXTENSION_ACL, + /* parser */ mailimap_acl_parse, + /* free */ mailimap_acl_free +}; + +LIBETPAN_EXPORT +int mailimap_acl_setacl(mailimap * session, + const char * mailbox, + const char * identifier, + const char * mod_rights) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_AUTHENTICATED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_acl_setacl_send(session->imap_stream, + mailbox, identifier, mod_rights); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_EXTENSION; + } +} + +LIBETPAN_EXPORT +int mailimap_acl_deleteacl(mailimap * session, + const char * mailbox, + const char * identifier) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_AUTHENTICATED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_acl_deleteacl_send(session->imap_stream, + mailbox, identifier); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_EXTENSION; + } +} + +LIBETPAN_EXPORT +int mailimap_acl_getacl(mailimap * session, + const char * mailbox, + clist ** result) +{ + struct mailimap_response * response; + struct mailimap_extension_data * ext_data; + clistiter * cur; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_AUTHENTICATED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_acl_getacl_send(session->imap_stream, + mailbox); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = clist_new(); + if (* result == NULL) + return MAILIMAP_ERROR_MEMORY; + + /* get all acl_data received and copy it to result */ + for (cur = clist_begin(session->imap_response_info->rsp_extension_list); + cur != NULL; cur = clist_next(cur)) { + ext_data = (struct mailimap_extension_data *) clist_content(cur); + if ( + ext_data->ext_extension->ext_id == MAILIMAP_EXTENSION_ACL && + ext_data->ext_type == MAILIMAP_ACL_TYPE_ACL_DATA) { + r = clist_append((* result), ext_data->ext_data); + if (r != 0) + return MAILIMAP_ERROR_MEMORY; + + ext_data->ext_data = NULL; + ext_data->ext_type = -1; + } + } + + clist_foreach(session->imap_response_info->rsp_extension_list, + (clist_func) mailimap_extension_data_free, NULL); + clist_free(session->imap_response_info->rsp_extension_list); + session->imap_response_info->rsp_extension_list = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_EXTENSION; + } +} + +LIBETPAN_EXPORT +int mailimap_acl_listrights(mailimap * session, + const char * mailbox, + const char * identifier, + struct mailimap_acl_listrights_data ** result) +{ + struct mailimap_response * response; + struct mailimap_extension_data * ext_data; + clistiter * cur; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_AUTHENTICATED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_acl_listrights_send(session->imap_stream, + mailbox, identifier); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = NULL; + + /* in rsp_extension_list there is at most one listrights_data */ + for (cur = clist_begin(session->imap_response_info->rsp_extension_list); + cur != NULL; cur = clist_next(cur)) { + ext_data = (struct mailimap_extension_data *) clist_content(cur); + if ( + ext_data->ext_extension->ext_id == MAILIMAP_EXTENSION_ACL && + ext_data->ext_type == MAILIMAP_ACL_TYPE_LISTRIGHTS_DATA) { + * result = (struct mailimap_acl_listrights_data *)ext_data->ext_data; + /* remove the element from rsp_extension_list */ + clist_delete(session->imap_response_info->rsp_extension_list, cur); + + break; + } + } + + clist_foreach(session->imap_response_info->rsp_extension_list, + (clist_func) mailimap_extension_data_free, NULL); + clist_free(session->imap_response_info->rsp_extension_list); + session->imap_response_info->rsp_extension_list = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + /* if there is no data to be returned, return MAILIMAP_ERROR_EXTENSION */ + if (* result == NULL) + return MAILIMAP_ERROR_EXTENSION; + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_EXTENSION; + } +} + +LIBETPAN_EXPORT +int mailimap_acl_myrights(mailimap * session, + const char * mailbox, + struct mailimap_acl_myrights_data ** result) +{ + struct mailimap_response * response; + struct mailimap_extension_data * ext_data; + clistiter * cur; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_AUTHENTICATED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_acl_myrights_send(session->imap_stream, mailbox); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = NULL; + + /* in rsp_extension_list there is at most one myrights_data */ + for (cur = clist_begin(session->imap_response_info->rsp_extension_list); + cur != NULL; cur = clist_next(cur)) { + ext_data = (struct mailimap_extension_data *) clist_content(cur); + if ( + ext_data->ext_extension->ext_id == MAILIMAP_EXTENSION_ACL && + ext_data->ext_type == MAILIMAP_ACL_TYPE_MYRIGHTS_DATA) { + * result = (struct mailimap_acl_myrights_data *)ext_data->ext_data; + ext_data->ext_data = NULL; + /* remove the element from rsp_extension_list */ + clist_delete(session->imap_response_info->rsp_extension_list, cur); + mailimap_extension_data_free(ext_data); + + break; + } + } + + clist_foreach(session->imap_response_info->rsp_extension_list, + (clist_func) mailimap_extension_data_free, NULL); + clist_free(session->imap_response_info->rsp_extension_list); + session->imap_response_info->rsp_extension_list = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + /* if there is no data to be returned, return MAILIMAP_ERROR_EXTENSION */ + if (* result == NULL) + return MAILIMAP_ERROR_EXTENSION; + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_EXTENSION; + } +} + +LIBETPAN_EXPORT +int mailimap_has_acl(mailimap * session) +{ + return mailimap_has_extension(session, "ACL"); +} diff --git a/Sources/libetpan/low-level/imap/acl.h b/Sources/libetpan/low-level/imap/acl.h new file mode 100644 index 00000000..5f8f77a3 --- /dev/null +++ b/Sources/libetpan/low-level/imap/acl.h @@ -0,0 +1,165 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + TODO: parse extension to capability as defined in [rfc4314]. + capability =/ rights-capa + + This should actually be automatically parsed by parse_capability_data, + so maybe it's sufficient to code a higher-level (not mailimap) function + that returns a list of extra-rights as defined in rights-capa. +*/ + +#ifndef ACL_H + +#define ACL_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +LIBETPAN_EXPORT +extern struct mailimap_extension_api mailimap_extension_acl; + +/* + mailimap_acl_setacl() + + This will set access for an identifier on the mailbox specified. + + @param session the IMAP session + @param mailbox the mailbox to modify + @param identifier the identifier to set access-rights for + @param mod_rights the modification to make to the rights + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + +*/ + +LIBETPAN_EXPORT +int mailimap_acl_setacl(mailimap * session, + const char * mailbox, + const char * identifier, + const char * mod_rights); + +/* + mailimap_acl_deleteacl() + + This will remove the acl on the mailbox for the identifier specified. + + @param session the IMAP session + @param mailbox the mailbox to modify + @param identifier the identifier to remove acl for + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + +*/ + +LIBETPAN_EXPORT +int mailimap_acl_deleteacl(mailimap * session, + const char * mailbox, + const char * identifier); + +/* + mailimap_acl_getacl() + + This will get a list of acls for the mailbox + + @param session the IMAP session + @param mailbox the mailbox to get the acls for + @param result this will store a clist of (struct mailimap_acl_acl_data *) + in (* result) + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + +*/ + +LIBETPAN_EXPORT +int mailimap_acl_getacl(mailimap * session, + const char * mailbox, + clist ** result); + +/* + mailimap_acl_listrights() + + The LISTRIGHTS command takes a mailbox name and an identifier and + returns information about what rights can be granted to the + identifier in the ACL for the mailbox. + + @param session the IMAP session + @param mailbox the mailbox to get the acls for + @param identifier the identifier to query the acls for + @param result this will store a (struct mailimap_acl_listrights_data *) + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + +*/ + +LIBETPAN_EXPORT +int mailimap_acl_listrights(mailimap * session, + const char * mailbox, + const char * identifier, + struct mailimap_acl_listrights_data ** result); + +/* + mailimap_acl_myrights() + + This will list the rights for the querying user on the mailbox + + @param session the IMAP session + @param mailbox the mailbox to get the acls for + @param result this will store a (struct mailimap_acl_myrights_data *) + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + +*/ + +LIBETPAN_EXPORT +int mailimap_acl_myrights(mailimap * session, + const char * mailbox, + struct mailimap_acl_myrights_data ** result); + +LIBETPAN_EXPORT +int mailimap_has_acl(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/acl_parser.c b/Sources/libetpan/low-level/imap/acl_parser.c new file mode 100644 index 00000000..8781f5ba --- /dev/null +++ b/Sources/libetpan/low-level/imap/acl_parser.c @@ -0,0 +1,460 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "acl_parser.h" +#include "mailimap_keywords.h" +#include "mailimap_extension.h" +#include "acl.h" + +#include + +int +mailimap_acl_acl_data_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_acl_acl_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * mailbox; + clist * ir_list; + struct mailimap_acl_acl_data * acl_data; + int r; + int res; + + cur_token = * indx; + + mailbox = NULL; /* XXX - removes a gcc warning */ + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "ACL"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_mailbox_parse(fd, buffer, parser_ctx, &cur_token, &mailbox, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto mailbox_free; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, + &cur_token, &ir_list, + (mailimap_struct_parser * ) + mailimap_acl_identifier_rights_parse, + (mailimap_struct_destructor * ) + mailimap_acl_identifier_rights_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto mailbox_free; + } + + acl_data = mailimap_acl_acl_data_new(mailbox, + ir_list); + if (acl_data == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto ir_list_free; + } + + * result = acl_data; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + ir_list_free: + if (ir_list != NULL) { + clist_foreach(ir_list, + (clist_func) mailimap_acl_identifier_rights_free, NULL); + clist_free(ir_list); + } + mailbox_free: + mailimap_mailbox_free(mailbox); + err: + return res; +} + +int +mailimap_acl_listrights_data_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_acl_listrights_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * mailbox; + char * identifier; + clist * rights_list; + struct mailimap_acl_listrights_data * lr_data; + int r; + int res; + + cur_token = * indx; + + mailbox = NULL; /* XXX - removes a gcc warning */ + identifier = NULL; + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "LISTRIGHTS"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_mailbox_parse(fd, buffer, parser_ctx, &cur_token, &mailbox, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto mailbox_free; + } + + r = mailimap_acl_identifier_parse(fd, buffer, parser_ctx, &cur_token, &identifier, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto mailbox_free; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto identifier_free; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, + &cur_token, &rights_list, + (mailimap_struct_parser * ) + mailimap_acl_rights_parse, + (mailimap_struct_destructor * ) + mailimap_acl_rights_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto identifier_free; + } + + lr_data = mailimap_acl_listrights_data_new(mailbox, identifier, + rights_list); + if (lr_data == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto rights_list_free; + } + + * result = lr_data; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + rights_list_free: + if (rights_list != NULL) { + clist_foreach(rights_list, + (clist_func) mailimap_acl_rights_free, NULL); + clist_free(rights_list); + } + identifier_free: + mailimap_acl_identifier_free(identifier); + mailbox_free: + mailimap_mailbox_free(mailbox); + err: + return res; +} + +int +mailimap_acl_myrights_data_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_acl_myrights_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * mailbox; + char * rights; + struct mailimap_acl_myrights_data * mr_data; + int r; + int res; + + cur_token = * indx; + + mailbox = NULL; /* XXX - removes a gcc warning */ + rights = NULL; + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "MYRIGHTS"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_mailbox_parse(fd, buffer, parser_ctx, &cur_token, &mailbox, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto mailbox_free; + } + + r = mailimap_acl_rights_parse(fd, buffer, parser_ctx, &cur_token, &rights, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto mailbox_free; + } + + mr_data = mailimap_acl_myrights_data_new(mailbox, rights); + if (mr_data == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto rights_free; + } + + * result = mr_data; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + rights_free: + mailimap_acl_rights_free(rights); + mailbox_free: + mailimap_mailbox_free(mailbox); + err: + return res; +} + +int +mailimap_acl_identifier_rights_parse(mailstream * fd, + MMAPString *buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_acl_identifier_rights ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * identifier; + char * rights; + struct mailimap_acl_identifier_rights * id_rights; + int r; + int res; + + cur_token = * indx; + + identifier = NULL; /* XXX - removes a gcc warning */ + rights = NULL; + + r = mailimap_acl_identifier_parse(fd, buffer, parser_ctx, &cur_token, &identifier, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto identifier_free; + } + + r = mailimap_acl_rights_parse(fd, buffer, parser_ctx, &cur_token, &rights, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto identifier_free; + } + + id_rights = mailimap_acl_identifier_rights_new(identifier, rights); + if (id_rights == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto rights_free; + } + + * result = id_rights; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + rights_free: + mailimap_acl_rights_free(rights); + identifier_free: + mailimap_acl_identifier_free(identifier); + err: + return res; +} + +int +mailimap_acl_identifier_parse(mailstream * fd, + MMAPString *buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + char ** result, size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_astring_parse(fd, buffer, parser_ctx, indx, result, + progr_rate, progr_fun); +} + +int mailimap_acl_rights_parse(mailstream * fd, + MMAPString *buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + char ** result, size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_astring_parse(fd, buffer, parser_ctx, indx, result, + progr_rate, progr_fun); +} + +/* + this is the extension's initial parser. it switches on calling_parser + and calls the corresponding actual parser. acl extends + imap as follows: + mailbox-data =/ acl-data / listrights-data / myrights-data + ;;mailbox-data is defined in [IMAP4] + capability =/ rights-capa + ;;capability is defined in [IMAP4] + + the extension to capability is omitted so far. +*/ + +int mailimap_acl_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int r; + int res; + + struct mailimap_acl_acl_data * acl_data; + struct mailimap_acl_listrights_data * lr_data; + struct mailimap_acl_myrights_data * mr_data; + + void * data; + + int type; + + acl_data = NULL; + lr_data = NULL; + mr_data = NULL; + + switch (calling_parser) + { + case MAILIMAP_EXTENDED_PARSER_MAILBOX_DATA: + r = mailimap_acl_acl_data_parse(fd, buffer, parser_ctx, indx, + &acl_data, progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) { + type = MAILIMAP_ACL_TYPE_ACL_DATA; + data = acl_data; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_acl_listrights_data_parse(fd, buffer, parser_ctx, indx, + &lr_data, progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) { + type = MAILIMAP_ACL_TYPE_LISTRIGHTS_DATA; + data = lr_data; + } + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_acl_myrights_data_parse(fd, buffer, parser_ctx, indx, + &mr_data, progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) { + type = MAILIMAP_ACL_TYPE_MYRIGHTS_DATA; + data = mr_data; + } + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + * result = mailimap_extension_data_new(&mailimap_extension_acl, + type, data); + if (*result == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto data_free; + } + break; + default: + /* return a MAILIMAP_ERROR_PARSE if the extension + doesn't extend calling_parser. */ + return MAILIMAP_ERROR_PARSE; + break; + } + + return MAILIMAP_NO_ERROR; + + data_free: + if (acl_data != NULL) + mailimap_acl_acl_data_free(acl_data); + if (lr_data != NULL) + mailimap_acl_listrights_data_free(lr_data); + if (mr_data != NULL) + mailimap_acl_myrights_data_free(mr_data); + err: + return res; +} + diff --git a/Sources/libetpan/low-level/imap/acl_parser.h b/Sources/libetpan/low-level/imap/acl_parser.h new file mode 100644 index 00000000..061cc4a9 --- /dev/null +++ b/Sources/libetpan/low-level/imap/acl_parser.h @@ -0,0 +1,92 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ACL_PARSER_H + +#define ACL_PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_parser.h" +#include "acl_types.h" + +int +mailimap_acl_acl_data_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_acl_acl_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_acl_listrights_data_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_acl_listrights_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_acl_myrights_data_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_acl_myrights_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_acl_identifier_rights_parse(mailstream * fd, + MMAPString *buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_acl_identifier_rights ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_acl_identifier_parse(mailstream * fd, + MMAPString *buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + char ** result, size_t progr_rate, + progress_function * progr_fun); + +int mailimap_acl_rights_parse(mailstream * fd, + MMAPString *buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + char ** result, size_t progr_rate, + progress_function * progr_fun); + +int mailimap_acl_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/acl_sender.c b/Sources/libetpan/low-level/imap/acl_sender.c new file mode 100644 index 00000000..ec8c6399 --- /dev/null +++ b/Sources/libetpan/low-level/imap/acl_sender.c @@ -0,0 +1,185 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailimap_sender.h" +#include "acl_types.h" + +static int mailimap_acl_identifier_send(mailstream * fd, + const char * identifier) +{ + return mailimap_astring_send(fd, identifier); +} + +static int mailimap_acl_mod_rights_send(mailstream * fd, + const char * mod_rights) +{ + return mailimap_astring_send(fd, mod_rights); +} + +int mailimap_acl_setacl_send(mailstream * fd, + const char * mailbox, + const char * identifier, + const char * mod_rights) +{ + int r; + + r = mailimap_token_send(fd, "SETACL"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mailbox); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_acl_identifier_send(fd, identifier); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_acl_mod_rights_send(fd, mod_rights); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_acl_deleteacl_send(mailstream * fd, + const char * mailbox, + const char * identifier) +{ + int r; + + r = mailimap_token_send(fd, "DELETEACL"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mailbox); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_acl_identifier_send(fd, identifier); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_acl_getacl_send(mailstream * fd, + const char * mailbox) +{ + int r; + + r = mailimap_token_send(fd, "GETACL"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mailbox); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_acl_listrights_send(mailstream * fd, + const char * mailbox, + const char * identifier) +{ + int r; + + r = mailimap_token_send(fd, "LISTRIGHTS"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mailbox); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_acl_identifier_send(fd, identifier); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_acl_myrights_send(mailstream * fd, + const char * mailbox) +{ + int r; + + r = mailimap_token_send(fd, "MYRIGHTS"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mailbox); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} diff --git a/Sources/libetpan/low-level/imap/acl_sender.h b/Sources/libetpan/low-level/imap/acl_sender.h new file mode 100644 index 00000000..9796a7d4 --- /dev/null +++ b/Sources/libetpan/low-level/imap/acl_sender.h @@ -0,0 +1,66 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ACL_SENDER_H + +#define ACL_SENDER_H + +#include "mailimap_sender.h" +#include "acl_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int mailimap_acl_setacl_send(mailstream * fd, + const char * mailbox, + const char * identifier, + const char * mod_rights); + +int mailimap_acl_deleteacl_send(mailstream * fd, + const char * mailbox, + const char * identifier); + +int mailimap_acl_getacl_send(mailstream * fd, + const char * mailbox); + +int mailimap_acl_listrights_send(mailstream * fd, + const char * mailbox, + const char * identifier); + +int mailimap_acl_myrights_send(mailstream * fd, + const char * mailbox); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/acl_types.c b/Sources/libetpan/low-level/imap/acl_types.c new file mode 100644 index 00000000..3f9718f2 --- /dev/null +++ b/Sources/libetpan/low-level/imap/acl_types.c @@ -0,0 +1,173 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailimap_types.h" +#include "acl_types.h" +#include "mailimap_extension.h" + +#include +#include + +void mailimap_acl_identifier_free(char * identifier) +{ + mailimap_astring_free(identifier); +} + +void mailimap_acl_rights_free(char * rights) +{ + mailimap_astring_free(rights); +} + +struct mailimap_acl_identifier_rights * +mailimap_acl_identifier_rights_new(char * identifier, char * rights) +{ + struct mailimap_acl_identifier_rights * id_rights; + + id_rights = malloc(sizeof(* id_rights)); + if (id_rights == NULL) + return NULL; + + id_rights->identifer = identifier; + id_rights->rights = rights; + + return id_rights; +} + +void mailimap_acl_identifier_rights_free( + struct mailimap_acl_identifier_rights * id_rights) +{ + mailimap_acl_identifier_free(id_rights->identifer); + mailimap_acl_rights_free(id_rights->rights); + + free(id_rights); +} + +struct mailimap_acl_acl_data * +mailimap_acl_acl_data_new(char * mailbox, clist * idrights_list) +{ + struct mailimap_acl_acl_data * acl_data; + + acl_data = malloc(sizeof(* acl_data)); + if (acl_data == NULL) + return NULL; + + acl_data->mailbox = mailbox; + acl_data->idrights_list = idrights_list; + + return acl_data; +} + +LIBETPAN_EXPORT +void mailimap_acl_acl_data_free(struct + mailimap_acl_acl_data * acl_data) +{ + mailimap_mailbox_free(acl_data->mailbox); + clist_foreach(acl_data->idrights_list, + (clist_func) mailimap_acl_identifier_rights_free, NULL); + clist_free(acl_data->idrights_list); + free(acl_data); +} + +struct mailimap_acl_listrights_data * +mailimap_acl_listrights_data_new(char * mailbox, + char * identifier, clist * rights_list) +{ + struct mailimap_acl_listrights_data * lr_data; + + lr_data = malloc(sizeof(* lr_data)); + if (lr_data == NULL) + return NULL; + + lr_data->mailbox = mailbox; + lr_data->identifier = identifier; + lr_data->rights_list = rights_list; + + return lr_data; +} + +LIBETPAN_EXPORT +void mailimap_acl_listrights_data_free(struct + mailimap_acl_listrights_data * lr_data) +{ + mailimap_mailbox_free(lr_data->mailbox); + mailimap_acl_identifier_free(lr_data->identifier); + clist_foreach(lr_data->rights_list, + (clist_func) mailimap_acl_rights_free, NULL); + clist_free(lr_data->rights_list); + free(lr_data); +} + +struct mailimap_acl_myrights_data * +mailimap_acl_myrights_data_new(char * mailbox, char * rights) +{ + struct mailimap_acl_myrights_data * mr_data; + + mr_data = malloc(sizeof(* mr_data)); + if (mr_data == NULL) + return NULL; + + mr_data->mailbox = mailbox; + mr_data->rights = rights; + + return mr_data; +} + +LIBETPAN_EXPORT +void mailimap_acl_myrights_data_free(struct + mailimap_acl_myrights_data * mr_data) +{ + mailimap_mailbox_free(mr_data->mailbox); + mailimap_acl_rights_free(mr_data->rights); + free(mr_data); +} + +void +mailimap_acl_free(struct mailimap_extension_data * ext_data) +{ + switch (ext_data->ext_type) + { + case MAILIMAP_ACL_TYPE_ACL_DATA: + mailimap_acl_acl_data_free(ext_data->ext_data); + break; + case MAILIMAP_ACL_TYPE_LISTRIGHTS_DATA: + mailimap_acl_listrights_data_free(ext_data->ext_data); + break; + case MAILIMAP_ACL_TYPE_MYRIGHTS_DATA: + mailimap_acl_myrights_data_free(ext_data->ext_data); + break; + } + + free (ext_data); +} diff --git a/Sources/libetpan/low-level/imap/acl_types.h b/Sources/libetpan/low-level/imap/acl_types.h new file mode 100644 index 00000000..9861b7e8 --- /dev/null +++ b/Sources/libetpan/low-level/imap/acl_types.h @@ -0,0 +1,169 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ACL_TYPES_H + +#define ACL_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +/* + ACL grammar + see [rfc4314] for further information + + LOWER-ALPHA = %x61-7A ;; a-z + + acl-data = "ACL" SP mailbox *(SP identifier SP + rights) + + capability =/ rights-capa + ;;capability is defined in [IMAP4] + + command-auth =/ setacl / deleteacl / getacl / + listrights / myrights + ;;command-auth is defined in [IMAP4] + + deleteacl = "DELETEACL" SP mailbox SP identifier + + getacl = "GETACL" SP mailbox + + identifier = astring + + listrights = "LISTRIGHTS" SP mailbox SP identifier + + listrights-data = "LISTRIGHTS" SP mailbox SP identifier + SP rights *(SP rights) + + mailbox-data =/ acl-data / listrights-data / myrights-data + ;;mailbox-data is defined in [IMAP4] + + mod-rights = astring + ;; +rights to add, -rights to remove + ;; rights to replace + + myrights = "MYRIGHTS" SP mailbox + + myrights-data = "MYRIGHTS" SP mailbox SP rights + + new-rights = 1*LOWER-ALPHA + ;; MUST include "t", "e", "x", and "k". + ;; MUST NOT include standard rights listed + ;; in section 2.2 + + rights = astring + ;; only lowercase ASCII letters and digits + ;; are allowed. + + rights-capa = "RIGHTS=" new-rights + ;; RIGHTS=... capability + + setacl = "SETACL" SP mailbox SP identifier + SP mod-rights +*/ + +/* + only need to recognize types that can be "embedded" into main + IMAPrev1 types. +*/ +enum { + MAILIMAP_ACL_TYPE_ACL_DATA, /* child of mailbox-data */ + MAILIMAP_ACL_TYPE_LISTRIGHTS_DATA, /* child of mailbox-data */ + MAILIMAP_ACL_TYPE_MYRIGHTS_DATA /* child of mailbox-data */ +}; + +void mailimap_acl_identifier_free(char * identifier); + +void mailimap_acl_rights_free(char * rights); + +struct mailimap_acl_identifier_rights { + char * identifer; + char * rights; +}; + +struct mailimap_acl_identifier_rights * +mailimap_acl_identifier_rights_new(char * identifier, char * rights); + +void mailimap_acl_identifier_rights_free( + struct mailimap_acl_identifier_rights * id_rights); + +struct mailimap_acl_acl_data { + char * mailbox; + clist * idrights_list; + /* list of (struct mailimap_acl_identifier_rights *) */ +}; + +struct mailimap_acl_acl_data * +mailimap_acl_acl_data_new(char * mailbox, clist * idrights_list); + +LIBETPAN_EXPORT +void mailimap_acl_acl_data_free(struct + mailimap_acl_acl_data * acl_data); + +struct mailimap_acl_listrights_data { + char * mailbox; + char * identifier; + clist * rights_list; /* list of (char *) */ +}; + +struct mailimap_acl_listrights_data * +mailimap_acl_listrights_data_new(char * mailbox, + char * identifier, clist * rights_list); + +LIBETPAN_EXPORT +void mailimap_acl_listrights_data_free(struct + mailimap_acl_listrights_data * listrights_data); + +struct mailimap_acl_myrights_data { + char * mailbox; + char * rights; +}; + +struct mailimap_acl_myrights_data * +mailimap_acl_myrights_data_new(char * mailbox, char * rights); + +LIBETPAN_EXPORT +void mailimap_acl_myrights_data_free(struct + mailimap_acl_myrights_data * myrights_data); + +void +mailimap_acl_free(struct mailimap_extension_data * ext_data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/annotatemore.c b/Sources/libetpan/low-level/imap/annotatemore.c new file mode 100644 index 00000000..8f4f7464 --- /dev/null +++ b/Sources/libetpan/low-level/imap/annotatemore.c @@ -0,0 +1,208 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailimap.h" +#include "mailimap_extension.h" +#include "annotatemore.h" +#include "annotatemore_types.h" +#include "annotatemore_parser.h" +#include "annotatemore_sender.h" + +#include + +LIBETPAN_EXPORT +struct mailimap_extension_api mailimap_extension_annotatemore = { + /* name */ "ANNOTATEMORE", + /* extension_id */ MAILIMAP_EXTENSION_ANNOTATEMORE, + /* parser */ mailimap_annotatemore_parse, + /* free */ mailimap_annotatemore_free +}; + +/* + this is one of the imap commands annotatemore adds. setannotation is + yet to be implemented. +*/ +LIBETPAN_EXPORT +int mailimap_annotatemore_getannotation(mailimap * session, + const char * list_mb, + struct mailimap_annotatemore_entry_match_list * entries, + struct mailimap_annotatemore_attrib_match_list * attribs, + clist ** result) +{ + struct mailimap_response * response; + struct mailimap_extension_data * ext_data; + clistiter * cur; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_AUTHENTICATED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_annotatemore_getannotation_send(session->imap_stream, + list_mb, entries, attribs); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = clist_new(); + if (* result == NULL) + return MAILIMAP_ERROR_MEMORY; + + /* copy all annotate_data to the result-list */ + for (cur = clist_begin(session->imap_response_info->rsp_extension_list); + cur != NULL; cur = clist_next(cur)) { + ext_data = (struct mailimap_extension_data *) clist_content(cur); + if ( + ext_data->ext_extension->ext_id == MAILIMAP_EXTENSION_ANNOTATEMORE && + ext_data->ext_type == MAILIMAP_ANNOTATEMORE_TYPE_ANNOTATE_DATA) { + r = clist_append((* result), ext_data->ext_data); + if (r != 0) + return MAILIMAP_ERROR_MEMORY; + + ext_data->ext_data = NULL; + ext_data->ext_type = -1; + } + } + + clist_foreach(session->imap_response_info->rsp_extension_list, + (clist_func) mailimap_extension_data_free, NULL); + clist_free(session->imap_response_info->rsp_extension_list); + session->imap_response_info->rsp_extension_list = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_EXTENSION; + } +} + +LIBETPAN_EXPORT +int mailimap_annotatemore_setannotation(mailimap * session, + const char * list_mb, + struct mailimap_annotatemore_entry_att_list * en_att, + int * result) +{ + struct mailimap_response * response; + int r; + int error_code; + clistiter * cur; + struct mailimap_extension_data * ext_data; + + if (session->imap_state != MAILIMAP_STATE_AUTHENTICATED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_annotatemore_setannotation_send(session->imap_stream, + list_mb, en_att); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + break; + case MAILIMAP_RESP_COND_STATE_NO: + * result = MAILIMAP_ANNOTATEMORE_RESP_TEXT_CODE_UNSPECIFIED; + if (session->imap_response_info->rsp_extension_list != NULL) { + for (cur = clist_begin(session->imap_response_info->rsp_extension_list); + cur != NULL; cur = clist_next(cur)) { + ext_data = clist_content(cur); + if ((ext_data->ext_extension->ext_id == + MAILIMAP_EXTENSION_ANNOTATEMORE) && + (ext_data->ext_type == + MAILIMAP_ANNOTATEMORE_TYPE_RESP_TEXT_CODE)) + { + * result = * ((int *)ext_data->ext_data); + } + } + } + return MAILIMAP_ERROR_EXTENSION; + break; + default: + * result = MAILIMAP_ANNOTATEMORE_RESP_TEXT_CODE_UNSPECIFIED; + return MAILIMAP_ERROR_EXTENSION; + break; + } +} + +LIBETPAN_EXPORT +int mailimap_has_annotatemore(mailimap * session) +{ + return mailimap_has_extension(session, "ANNOTATEMORE"); +} diff --git a/Sources/libetpan/low-level/imap/annotatemore.h b/Sources/libetpan/low-level/imap/annotatemore.h new file mode 100644 index 00000000..d31da593 --- /dev/null +++ b/Sources/libetpan/low-level/imap/annotatemore.h @@ -0,0 +1,103 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ANNOTATEMORE_H + +#define ANNOTATEMORE_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +LIBETPAN_EXPORT +extern struct mailimap_extension_api mailimap_extension_annotatemore; + +/* + mailimap_annotatemore_getannotation() + + This function will get annotations from given mailboxes or the server. + + @param session the IMAP session + @param list_mb mailbox name with possible wildcard, + empty string implies server annotation + @param entries entry specifier with possible wildcards + @param attribs attribute specifier with possible wildcards + @param result This will store a clist of (struct mailimap_annotate_data *) + in (* result) + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + +*/ + +LIBETPAN_EXPORT +int mailimap_annotatemore_getannotation(mailimap * session, + const char * list_mb, + struct mailimap_annotatemore_entry_match_list * entries, + struct mailimap_annotatemore_attrib_match_list * attribs, + clist ** result); + +/* + mailimap_annotatemore_setannotation() + + This function will set annotations on given mailboxes or the server. + + @param session the IMAP session + @param list_mb mailbox name with possible wildcard, + empty string implies server annotation + @param en_att a list of entries/attributes to set + @param result if return is MAILIMAP_ERROR_EXTENSION result + is MAILIMAP_ANNOTATEMORE_RESP_TEXT_CODE_TOOBIG or + MAILIMAP_ANNOTATEMORE_RESP_TEXT_CODE_TOOMANY for + extra information about the error. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_annotatemore_setannotation(mailimap * session, + const char * list_mb, + struct mailimap_annotatemore_entry_att_list * en_att, + int * result); + +LIBETPAN_EXPORT +int mailimap_has_annotatemore(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/annotatemore_parser.c b/Sources/libetpan/low-level/imap/annotatemore_parser.c new file mode 100644 index 00000000..aeb761b8 --- /dev/null +++ b/Sources/libetpan/low-level/imap/annotatemore_parser.c @@ -0,0 +1,461 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "annotatemore_parser.h" +#include "mailimap_keywords.h" +#include "mailimap_extension.h" +#include "annotatemore.h" + +#include + +int +mailimap_annotatemore_annotate_data_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_annotatemore_annotate_data ** result, + size_t progr_rate, progress_function * progr_fun) +{ + size_t cur_token; + char * mailbox; + struct mailimap_annotatemore_entry_list * entry_list; + struct mailimap_annotatemore_annotate_data * annotate_data; + int r; + int res; + + cur_token = * indx; + + mailbox = NULL; /* XXX - removes a gcc warning */ + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "ANNOTATION"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_mailbox_parse(fd, buffer, parser_ctx, &cur_token, &mailbox, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto mailbox_free; + } + + r = mailimap_annotatemore_entry_list_parse(fd, buffer, parser_ctx, &cur_token, + &entry_list, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto mailbox_free; + } + + annotate_data = mailimap_annotatemore_annotate_data_new(mailbox, + entry_list); + if (annotate_data == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto entry_list_free; + } + + * result = annotate_data; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + entry_list_free: + mailimap_annotatemore_entry_list_free(entry_list); + mailbox_free: + mailimap_mailbox_free(mailbox); + err: + return res; +} + +int +mailimap_annotatemore_entry_list_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_annotatemore_entry_list ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * en_att_list; + clist * en_list; + int type; + struct mailimap_annotatemore_entry_list * entry_list; + int r; + int res; + + cur_token = * indx; + + /* XXX - removes a gcc warning */ + type = MAILIMAP_ANNOTATEMORE_ENTRY_LIST_TYPE_ERROR; + en_list = NULL; + en_att_list = NULL; + + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, + &cur_token, &en_att_list, + (mailimap_struct_parser * ) + mailimap_annotatemore_entry_att_parse, + (mailimap_struct_destructor * ) + mailimap_annotatemore_entry_att_free, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_ANNOTATEMORE_ENTRY_LIST_TYPE_ENTRY_ATT_LIST; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, + &cur_token, &en_list, + (mailimap_struct_parser * ) + mailimap_annotatemore_entry_parse, + (mailimap_struct_destructor * ) + mailimap_annotatemore_entry_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto en_list_free; + } + + type = MAILIMAP_ANNOTATEMORE_ENTRY_LIST_TYPE_ENTRY_LIST; + } + + entry_list = mailimap_annotatemore_entry_list_new(type, en_att_list, en_list); + if (entry_list == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto list_free; + } + + * result = entry_list; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + list_free: + if (en_att_list != NULL) { + clist_foreach(en_att_list, + (clist_func) mailimap_annotatemore_entry_att_free, NULL); + clist_free(en_att_list); + } + en_list_free: + if (en_list != NULL) { + clist_foreach(en_list, + (clist_func) mailimap_annotatemore_entry_free, NULL); + clist_free(en_list); + } + err: + return res; +} + +int +mailimap_annotatemore_entry_att_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_annotatemore_entry_att ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * entry; + clist * list; + struct mailimap_annotatemore_entry_att * entry_att; + int r; + int res; + + cur_token = * indx; + entry = NULL; + + r = mailimap_annotatemore_entry_parse(fd, buffer, parser_ctx, &cur_token, &entry, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto entry_free; + } + + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto entry_free; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, + &cur_token, &list, + (mailimap_struct_parser * ) + mailimap_annotatemore_att_value_parse, + (mailimap_struct_destructor * ) + mailimap_annotatemore_att_value_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto entry_free; + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto list_free; + } + + entry_att = mailimap_annotatemore_entry_att_new(entry, list); + if (entry_att == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto list_free; + } + + * result = entry_att; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + list_free: + clist_foreach(list, + (clist_func) mailimap_annotatemore_att_value_free, NULL); + clist_free(list); + entry_free: + mailimap_annotatemore_entry_free(entry); + err: + return res; +} + +int +mailimap_annotatemore_att_value_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_annotatemore_att_value ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * attrib; + char * value; + struct mailimap_annotatemore_att_value * att_value; + int r; + int res; + + cur_token = * indx; + attrib = NULL; + value = NULL; + + r = mailimap_annotatemore_attrib_parse(fd, buffer, parser_ctx, &cur_token, &attrib, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto attrib_free; + } + + r = mailimap_annotatemore_value_parse(fd, buffer, parser_ctx, &cur_token, &value, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto attrib_free; + } + + att_value = mailimap_annotatemore_att_value_new(attrib, value); + if (att_value == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto value_free; + } + + * result = att_value; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + value_free: + mailimap_annotatemore_value_free(value); + attrib_free: + mailimap_annotatemore_attrib_free(attrib); + err: + return res; +} + +int +mailimap_annotatemore_attrib_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, progress_function * progr_fun) +{ + return mailimap_string_parse(fd, buffer, parser_ctx, indx, result, NULL, + progr_rate, progr_fun); +} + +int +mailimap_annotatemore_value_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, parser_ctx, indx, result, NULL, + progr_rate, progr_fun); +} + +int +mailimap_annotatemore_entry_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, progress_function * progr_fun) +{ + return mailimap_string_parse(fd, buffer, parser_ctx, indx, result, NULL, + progr_rate, progr_fun); +} + +int +mailimap_annotatemore_text_code_annotatemore_parse(mailstream * fd, + MMAPString *buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, int * result, + size_t progr_rate, progress_function * progr_fun) +{ + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "ANNOTATEMORE"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "TOOBIG"); + if (r == MAILIMAP_NO_ERROR) { + * result = MAILIMAP_ANNOTATEMORE_RESP_TEXT_CODE_TOOBIG; + } else { + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "TOOMANY"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + * result = MAILIMAP_ANNOTATEMORE_RESP_TEXT_CODE_TOOMANY; + } + + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + err: + return res; +} + + +/* + this is the extension's initial parser. it switches on calling_parser + and calls the corresponding actual parser. annotatemore extends + imap as follows: + response-data /= "*" SP annotate-data CRLF + ; adds to original IMAP data responses + + resp-text-code =/ "ANNOTATEMORE" SP "TOOBIG" / + "ANNOTATEMORE" SP "TOOMANY" + ; new response codes for SETANNOTATION failures +*/ +int mailimap_annotatemore_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int r; + + struct mailimap_annotatemore_annotate_data * an_data; + int resp_text_code; + + switch (calling_parser) + { + case MAILIMAP_EXTENDED_PARSER_RESPONSE_DATA: + r = mailimap_annotatemore_annotate_data_parse(fd, buffer, parser_ctx, indx, + &an_data, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + * result = mailimap_extension_data_new(&mailimap_extension_annotatemore, + MAILIMAP_ANNOTATEMORE_TYPE_ANNOTATE_DATA, an_data); + if (*result == NULL) { + mailimap_annotatemore_annotate_data_free(an_data); + return MAILIMAP_ERROR_MEMORY; + } + break; + case MAILIMAP_EXTENDED_PARSER_RESP_TEXT_CODE: + r = mailimap_annotatemore_text_code_annotatemore_parse(fd, buffer, parser_ctx, indx, + &resp_text_code, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + * result = mailimap_extension_data_new(&mailimap_extension_annotatemore, + MAILIMAP_ANNOTATEMORE_TYPE_RESP_TEXT_CODE, &resp_text_code); + if (*result == NULL) + return MAILIMAP_ERROR_MEMORY; + break; + default: + /* return a MAILIMAP_ERROR_PARSE if the extension + doesn't extend calling_parser. */ + return MAILIMAP_ERROR_PARSE; + break; + } + + return MAILIMAP_NO_ERROR; +} + diff --git a/Sources/libetpan/low-level/imap/annotatemore_parser.h b/Sources/libetpan/low-level/imap/annotatemore_parser.h new file mode 100644 index 00000000..a8fdaf13 --- /dev/null +++ b/Sources/libetpan/low-level/imap/annotatemore_parser.h @@ -0,0 +1,104 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ANNOTATEMORE_PARSER_H + +#define ANNOTATEMORE_PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_parser.h" +#include "annotatemore_types.h" + +int +mailimap_annotatemore_annotate_data_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_annotatemore_annotate_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_annotatemore_entry_list_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_annotatemore_entry_list ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_annotatemore_entry_att_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_annotatemore_entry_att ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_annotatemore_att_value_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_annotatemore_att_value ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_annotatemore_attrib_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_annotatemore_value_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_annotatemore_entry_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_annotatemore_text_code_annotatemore_parse(mailstream * fd, + MMAPString *buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, int * result, + size_t progr_rate, progress_function * progr_fun); + +int mailimap_annotatemore_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/annotatemore_sender.c b/Sources/libetpan/low-level/imap/annotatemore_sender.c new file mode 100644 index 00000000..e4787475 --- /dev/null +++ b/Sources/libetpan/low-level/imap/annotatemore_sender.c @@ -0,0 +1,213 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailimap_sender.h" +#include "annotatemore_types.h" + +static int annotatemore_string_send(mailstream * fd, const char * str) +{ + return mailimap_quoted_send(fd, str); +} + +static int +annotatemore_entry_match_list_send(mailstream * fd, + struct mailimap_annotatemore_entry_match_list * em_list) +{ + return mailimap_struct_spaced_list_send(fd, em_list->entry_match_list, + (mailimap_struct_sender *) annotatemore_string_send); +} + +static int +annotatemore_attrib_match_list_send(mailstream * fd, + struct mailimap_annotatemore_attrib_match_list * am_list) +{ + /* TODO actually attrib-match is defined as string, not astring */ + return mailimap_struct_spaced_list_send(fd, am_list->attrib_match_list, + (mailimap_struct_sender *) annotatemore_string_send); +} + +int mailimap_annotatemore_getannotation_send(mailstream * fd, + const char * list_mb, + struct mailimap_annotatemore_entry_match_list * entries, + struct mailimap_annotatemore_attrib_match_list * attribs) +{ + int r; + + r = mailimap_token_send(fd, "GETANNOTATION"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_list_mailbox_send(fd, list_mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '('); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = annotatemore_entry_match_list_send(fd, entries); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, ')'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '('); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = annotatemore_attrib_match_list_send(fd, attribs); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, ')'); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +static int +annotatemore_att_value_send(mailstream * fd, + struct mailimap_annotatemore_att_value * att_value) +{ + int r; + + r = annotatemore_string_send(fd, att_value->attrib); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = annotatemore_string_send(fd, att_value->value); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +static int +annotatemore_entry_att_send(mailstream * fd, + struct mailimap_annotatemore_entry_att * en_att) +{ + int r; + + r = annotatemore_string_send(fd, en_att->entry); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '('); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_struct_spaced_list_send(fd, en_att->att_value_list, + (mailimap_struct_sender *) annotatemore_att_value_send); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, ')'); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +static int +annotatemore_entry_att_list_send(mailstream * fd, + struct mailimap_annotatemore_entry_att_list * en_list) +{ + return mailimap_struct_spaced_list_send(fd, en_list->entry_att_list, + (mailimap_struct_sender *) annotatemore_entry_att_send); +} + +int mailimap_annotatemore_setannotation_send(mailstream * fd, + const char * list_mb, + struct mailimap_annotatemore_entry_att_list * en_list) +{ + int r; + + r = mailimap_token_send(fd, "SETANNOTATION"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_list_mailbox_send(fd, list_mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (en_list->entry_att_list->count > 1) { + r = mailimap_char_send(fd, '('); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = annotatemore_entry_att_list_send(fd, en_list); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (en_list->entry_att_list->count > 1) { + r = mailimap_char_send(fd, ')'); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + return MAILIMAP_NO_ERROR; +} diff --git a/Sources/libetpan/low-level/imap/annotatemore_sender.h b/Sources/libetpan/low-level/imap/annotatemore_sender.h new file mode 100644 index 00000000..aa540784 --- /dev/null +++ b/Sources/libetpan/low-level/imap/annotatemore_sender.h @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ANNOTATEMORE_SENDER_H + +#define ANNOTATEMORE_SENDER_H + +#include "mailimap_sender.h" +#include "annotatemore_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int mailimap_annotatemore_getannotation_send(mailstream * fd, + const char * list_mb, + struct mailimap_annotatemore_entry_match_list * entries, + struct mailimap_annotatemore_attrib_match_list * attribs); + +int mailimap_annotatemore_setannotation_send(mailstream * fd, + const char * list_mb, + struct mailimap_annotatemore_entry_att_list * en_att); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/annotatemore_types.c b/Sources/libetpan/low-level/imap/annotatemore_types.c new file mode 100644 index 00000000..7d21ddc6 --- /dev/null +++ b/Sources/libetpan/low-level/imap/annotatemore_types.c @@ -0,0 +1,392 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailimap_types.h" +#include "annotatemore_types.h" +#include "mailimap_extension.h" + +#include +#include + +void mailimap_annotatemore_attrib_free(char * attrib) +{ + mailimap_string_free(attrib); +} + +void mailimap_annotatemore_value_free(char * value) +{ + mailimap_nstring_free(value); +} + +void mailimap_annotatemore_entry_free(char * entry) +{ + mailimap_string_free(entry); +} + +LIBETPAN_EXPORT +struct mailimap_annotatemore_att_value * +mailimap_annotatemore_att_value_new(char * attrib, char * value) +{ + struct mailimap_annotatemore_att_value * att_value; + + att_value = malloc(sizeof(* att_value)); + if (att_value == NULL) + return NULL; + + att_value->attrib = attrib; + att_value->value = value; + + return att_value; +} + +void mailimap_annotatemore_att_value_free(struct + mailimap_annotatemore_att_value * att_value) +{ + mailimap_annotatemore_attrib_free(att_value->attrib); + mailimap_annotatemore_value_free(att_value->value); + + free(att_value); +} + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_att * +mailimap_annotatemore_entry_att_new(char * entry, clist * list) +{ + struct mailimap_annotatemore_entry_att * entry_att; + + entry_att = malloc(sizeof(* entry_att)); + if (entry_att == NULL) + return NULL; + + entry_att->entry = entry; + entry_att->att_value_list = list; + + return entry_att; +} + +LIBETPAN_EXPORT +void mailimap_annotatemore_entry_att_free(struct + mailimap_annotatemore_entry_att * en_att) +{ + mailimap_annotatemore_entry_free(en_att->entry); + clist_foreach(en_att->att_value_list, + (clist_func) mailimap_annotatemore_att_value_free, NULL); + clist_free(en_att->att_value_list); + free(en_att); +} + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_att * +mailimap_annotatemore_entry_att_new_empty(char * entry) +{ + struct mailimap_annotatemore_entry_att * entry_att; + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + entry_att = mailimap_annotatemore_entry_att_new(entry, list); + if (entry_att == NULL) + return NULL; + + return entry_att; +} + +LIBETPAN_EXPORT +int mailimap_annotatemore_entry_att_add(struct + mailimap_annotatemore_entry_att * en_att, + struct mailimap_annotatemore_att_value * at_value) +{ + int r; + + if (en_att->att_value_list == NULL) { + /* catch this error by creating a new clist */ + en_att->att_value_list = clist_new(); + if (en_att->att_value_list == NULL) + return MAILIMAP_ERROR_MEMORY; + } + + r = clist_append(en_att->att_value_list, at_value); + if (r < 0) { + return MAILIMAP_ERROR_MEMORY; + } + + return MAILIMAP_NO_ERROR; +} + +struct mailimap_annotatemore_entry_list * +mailimap_annotatemore_entry_list_new(int type, clist * en_att_list, clist * en_list) +{ + struct mailimap_annotatemore_entry_list * entry_list; + + entry_list = malloc(sizeof(* entry_list)); + if (entry_list == NULL) + return NULL; + + entry_list->en_list_type = type; + switch (type) { + case MAILIMAP_ANNOTATEMORE_ENTRY_LIST_TYPE_ENTRY_ATT_LIST: + entry_list->en_list_data = en_att_list; + break; + case MAILIMAP_ANNOTATEMORE_ENTRY_LIST_TYPE_ENTRY_LIST: + entry_list->en_list_data = en_list; + break; + } + + return entry_list; +} + +void mailimap_annotatemore_entry_list_free(struct + mailimap_annotatemore_entry_list * en_list) +{ + switch(en_list->en_list_type) { + case MAILIMAP_ANNOTATEMORE_ENTRY_LIST_TYPE_ENTRY_ATT_LIST: + clist_foreach(en_list->en_list_data, + (clist_func) mailimap_annotatemore_entry_att_free, NULL); + break; + case MAILIMAP_ANNOTATEMORE_ENTRY_LIST_TYPE_ENTRY_LIST: + clist_foreach(en_list->en_list_data, + (clist_func) mailimap_annotatemore_entry_free, NULL); + break; + } + clist_free(en_list->en_list_data); + free(en_list); +} + +struct mailimap_annotatemore_annotate_data * +mailimap_annotatemore_annotate_data_new(char * mb, struct + mailimap_annotatemore_entry_list * en_list) +{ + struct mailimap_annotatemore_annotate_data * annotate_data; + + annotate_data = malloc(sizeof(* annotate_data)); + if (annotate_data == NULL) + return NULL; + + annotate_data->mailbox = mb; + annotate_data->entry_list = en_list; + + return annotate_data; +} + +LIBETPAN_EXPORT +void mailimap_annotatemore_annotate_data_free(struct + mailimap_annotatemore_annotate_data * an_data) +{ + mailimap_mailbox_free(an_data->mailbox); + mailimap_annotatemore_entry_list_free(an_data->entry_list); + free(an_data); +} + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_match_list * +mailimap_annotatemore_entry_match_list_new(clist * en_list) +{ + struct mailimap_annotatemore_entry_match_list * entry_match_list; + + entry_match_list = malloc(sizeof(* entry_match_list)); + if (entry_match_list == NULL) + return NULL; + entry_match_list->entry_match_list = en_list; + + return entry_match_list; +} + +LIBETPAN_EXPORT +void mailimap_annotatemore_entry_match_list_free( + struct mailimap_annotatemore_entry_match_list * en_list) +{ + clist_foreach(en_list->entry_match_list, (clist_func) free, NULL); + clist_free(en_list->entry_match_list); + free(en_list); +} + +LIBETPAN_EXPORT +struct mailimap_annotatemore_attrib_match_list * +mailimap_annotatemore_attrib_match_list_new(clist * at_list) +{ + struct mailimap_annotatemore_attrib_match_list * attrib_match_list; + + attrib_match_list = malloc(sizeof(* attrib_match_list)); + if (attrib_match_list == NULL) + return NULL; + attrib_match_list->attrib_match_list = at_list; + + return attrib_match_list; +} + +LIBETPAN_EXPORT +void mailimap_annotatemore_attrib_match_list_free( + struct mailimap_annotatemore_attrib_match_list * at_list) +{ + clist_foreach(at_list->attrib_match_list, (clist_func) free, NULL); + clist_free(at_list->attrib_match_list); + free(at_list); +} + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_match_list * +mailimap_annotatemore_entry_match_list_new_empty() +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_annotatemore_entry_match_list_new(list); +} + +LIBETPAN_EXPORT +int mailimap_annotatemore_entry_match_list_add( + struct mailimap_annotatemore_entry_match_list * en_list, char * entry) +{ + char * pentry; + int r; + + pentry = strdup(entry); + if (pentry == NULL) + return MAILIMAP_ERROR_MEMORY; + + r = clist_append(en_list->entry_match_list, pentry); + if (r < 0) { + free(pentry); + return MAILIMAP_ERROR_MEMORY; + } + + return MAILIMAP_NO_ERROR; +} + +LIBETPAN_EXPORT +struct mailimap_annotatemore_attrib_match_list * +mailimap_annotatemore_attrib_match_list_new_empty() +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_annotatemore_attrib_match_list_new(list); +} + +LIBETPAN_EXPORT +int mailimap_annotatemore_attrib_match_list_add( + struct mailimap_annotatemore_attrib_match_list * at_list, char * attrib) +{ + char * pattrib; + int r; + + pattrib = strdup(attrib); + if (pattrib == NULL) + return MAILIMAP_ERROR_MEMORY; + + r = clist_append(at_list->attrib_match_list, pattrib); + if (r < 0) { + free(pattrib); + return MAILIMAP_ERROR_MEMORY; + } + + return MAILIMAP_NO_ERROR; +} + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_att_list * +mailimap_annotatemore_entry_att_list_new(clist * en_list) +{ + struct mailimap_annotatemore_entry_att_list * entry_att_list; + + entry_att_list = malloc(sizeof(* entry_att_list)); + if (entry_att_list == NULL) + return NULL; + entry_att_list->entry_att_list = en_list; + + return entry_att_list; +} + +LIBETPAN_EXPORT +void mailimap_annotatemore_entry_att_list_free( + struct mailimap_annotatemore_entry_att_list * en_list) +{ + clist_foreach(en_list->entry_att_list, + (clist_func) mailimap_annotatemore_entry_att_free, NULL); + clist_free(en_list->entry_att_list); + free(en_list); +} + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_att_list * +mailimap_annotatemore_entry_att_list_new_empty(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_annotatemore_entry_att_list_new(list); +} + +LIBETPAN_EXPORT +int mailimap_annotatemore_entry_att_list_add( + struct mailimap_annotatemore_entry_att_list * en_list, + struct mailimap_annotatemore_entry_att * en_att) +{ + int r; + + r = clist_append(en_list->entry_att_list, en_att); + if (r < 0) + return MAILIMAP_ERROR_MEMORY; + + return MAILIMAP_NO_ERROR; +} + +void +mailimap_annotatemore_free(struct mailimap_extension_data * ext_data) +{ + switch (ext_data->ext_type) + { + case MAILIMAP_ANNOTATEMORE_TYPE_ANNOTATE_DATA: + mailimap_annotatemore_annotate_data_free(ext_data->ext_data); + break; + case MAILIMAP_ANNOTATEMORE_TYPE_RESP_TEXT_CODE: + /* nothing malloced for resp_text_code */ + break; + } + + free (ext_data); +} + diff --git a/Sources/libetpan/low-level/imap/annotatemore_types.h b/Sources/libetpan/low-level/imap/annotatemore_types.h new file mode 100644 index 00000000..de3832cf --- /dev/null +++ b/Sources/libetpan/low-level/imap/annotatemore_types.h @@ -0,0 +1,268 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ANNOTATEMORE_TYPES_H + +#define ANNOTATEMORE_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +/* + ANNOTATEMORE grammar + see [draft-daboo-imap-annotatemore-07] for further information + + annotate-data = "ANNOTATION" SP mailbox SP entry-list + ; empty string for mailbox implies + ; server annotation. + + att-value = attrib SP value + + attrib = string + ; dot-separated attribute name + ; MUST NOT contain "*" or "%" + attrib-match = string + ; dot-separated attribute name + ; MAY contain "*" or "%" for use as wildcards + + attribs = attrib-match / "(" attrib-match *(SP attrib-match) ")" + ; attribute specifiers that can include wildcards + + command-auth /= setannotation / getannotation + ; adds to original IMAP command + + entries = entry-match / "(" entry-match *(SP entry-match) ")" + ; entry specifiers that can include wildcards + + entry = string + ; slash-separated path to entry + ; MUST NOT contain "*" or "%" + + entry-att = entry SP "(" att-value *(SP att-value) ")" + + entry-list = entry-att *(SP entry-att) / + "(" entry *(SP entry) ")" + ; entry attribute-value pairs list for + ; GETANNOTATION response, or + ; parenthesised entry list for unsolicited + ; notification of annotation changes + + entry-match = string + ; slash-separated path to entry + ; MAY contain "*" or "%" for use as wildcards + + getannotation = "GETANNOTATION" SP list-mailbox SP entries SP attribs + ; empty string for list-mailbox implies + ; server annotation. + + response-data /= "*" SP annotate-data CRLF + ; adds to original IMAP data responses + + resp-text-code =/ "ANNOTATEMORE" SP "TOOBIG" / + "ANNOTATEMORE" SP "TOOMANY" + ; new response codes for SETANNOTATION failures + + setannotation = "SETANNOTATION" SP list-mailbox SP setentryatt + ; empty string for list-mailbox implies + ; server annotation. + + setentryatt = entry-att / "(" entry-att *(SP entry-att) ")" + + value = nstring +*/ + +/* + only need to recognize types that can be "embedded" into main + IMAPrev1 types. +*/ +enum { + MAILIMAP_ANNOTATEMORE_TYPE_ANNOTATE_DATA, /* child of response-data */ + MAILIMAP_ANNOTATEMORE_TYPE_RESP_TEXT_CODE /* child of resp-text-code */ +}; + +/* + error codes for annotatemore. +*/ +enum { + MAILIMAP_ANNOTATEMORE_RESP_TEXT_CODE_UNSPECIFIED, /* unspecified response */ + MAILIMAP_ANNOTATEMORE_RESP_TEXT_CODE_TOOBIG, /* annotation too big */ + MAILIMAP_ANNOTATEMORE_RESP_TEXT_CODE_TOOMANY /* too many annotations */ +}; + +void mailimap_annotatemore_attrib_free(char * attrib); + +void mailimap_annotatemore_value_free(char * value); + +void mailimap_annotatemore_entry_free(char * entry); + +struct mailimap_annotatemore_att_value { + char * attrib; + char * value; +}; + +LIBETPAN_EXPORT +struct mailimap_annotatemore_att_value * +mailimap_annotatemore_att_value_new(char * attrib, char * value); + +void mailimap_annotatemore_att_value_free(struct + mailimap_annotatemore_att_value * att_value); + +struct mailimap_annotatemore_entry_att { + char * entry; + clist * att_value_list; + /* list of (struct mailimap_annotatemore_att_value *) */ +}; + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_att * +mailimap_annotatemore_entry_att_new(char * entry, clist * list); + +LIBETPAN_EXPORT +void mailimap_annotatemore_entry_att_free(struct + mailimap_annotatemore_entry_att * en_att); + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_att * +mailimap_annotatemore_entry_att_new_empty(char * entry); + +LIBETPAN_EXPORT +int mailimap_annotatemore_entry_att_add(struct + mailimap_annotatemore_entry_att * en_att, + struct mailimap_annotatemore_att_value * at_value); + +enum { + MAILIMAP_ANNOTATEMORE_ENTRY_LIST_TYPE_ERROR, /* error condition */ + MAILIMAP_ANNOTATEMORE_ENTRY_LIST_TYPE_ENTRY_ATT_LIST, /* entry-att-list */ + MAILIMAP_ANNOTATEMORE_ENTRY_LIST_TYPE_ENTRY_LIST /* entry-list */ +}; + +struct mailimap_annotatemore_entry_list { + int en_list_type; + clist * en_list_data; + /* either a list of (struct annotatemore_entry_att *) + or a list of (char *) */ +}; + +struct mailimap_annotatemore_entry_list * +mailimap_annotatemore_entry_list_new(int type, clist * en_att_list, clist * en_list); + +void mailimap_annotatemore_entry_list_free(struct + mailimap_annotatemore_entry_list * en_list); + +struct mailimap_annotatemore_annotate_data { + char * mailbox; + struct mailimap_annotatemore_entry_list * entry_list; +}; + +struct mailimap_annotatemore_annotate_data * +mailimap_annotatemore_annotate_data_new(char * mb, struct + mailimap_annotatemore_entry_list * en_list); + +LIBETPAN_EXPORT +void mailimap_annotatemore_annotate_data_free(struct + mailimap_annotatemore_annotate_data * an_data); + +struct mailimap_annotatemore_entry_match_list { + clist * entry_match_list; /* list of (char *) */ +}; + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_match_list * +mailimap_annotatemore_entry_match_list_new(clist * en_list); + +LIBETPAN_EXPORT +void mailimap_annotatemore_entry_match_list_free( + struct mailimap_annotatemore_entry_match_list * en_list); + +struct mailimap_annotatemore_attrib_match_list { + clist * attrib_match_list; /* list of (char *) */ +}; + +LIBETPAN_EXPORT +struct mailimap_annotatemore_attrib_match_list * +mailimap_annotatemore_attrib_match_list_new(clist * at_list); + +LIBETPAN_EXPORT +void mailimap_annotatemore_attrib_match_list_free( + struct mailimap_annotatemore_attrib_match_list * at_list); + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_match_list * +mailimap_annotatemore_entry_match_list_new_empty(void); + +LIBETPAN_EXPORT +int mailimap_annotatemore_entry_match_list_add( + struct mailimap_annotatemore_entry_match_list * en_list, + char * entry); + +LIBETPAN_EXPORT +struct mailimap_annotatemore_attrib_match_list * +mailimap_annotatemore_attrib_match_list_new_empty(void); + +LIBETPAN_EXPORT +int mailimap_annotatemore_attrib_match_list_add( + struct mailimap_annotatemore_attrib_match_list * at_list, + char * attrib); + +struct mailimap_annotatemore_entry_att_list { + clist * entry_att_list; /* list of (mailimap_annotatemore_entry_att *) */ +}; + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_att_list * +mailimap_annotatemore_entry_att_list_new(clist * en_list); + +LIBETPAN_EXPORT +void mailimap_annotatemore_entry_att_list_free( + struct mailimap_annotatemore_entry_att_list * en_list); + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_att_list * +mailimap_annotatemore_entry_att_list_new_empty(void); + +LIBETPAN_EXPORT +int mailimap_annotatemore_entry_att_list_add( + struct mailimap_annotatemore_entry_att_list * en_list, + struct mailimap_annotatemore_entry_att * en_att); + +void +mailimap_annotatemore_free(struct mailimap_extension_data * ext_data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/clientid.c b/Sources/libetpan/low-level/imap/clientid.c new file mode 100644 index 00000000..8221a329 --- /dev/null +++ b/Sources/libetpan/low-level/imap/clientid.c @@ -0,0 +1,93 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2018, 2019 - LinuxMagic + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include "mailimap_sender.h" +#include "clientid_sender.h" +#include "clientid.h" + +LIBETPAN_EXPORT +int mailimap_clientid(mailimap * session, + const char * type, const char * clientid) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_NON_AUTHENTICATED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_clientid_send(session->imap_stream, type, clientid); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_CLIENTID; + } +} + +LIBETPAN_EXPORT +int mailimap_has_clientid(mailimap * session) +{ + return mailimap_has_extension(session, "CLIENTID"); +} diff --git a/Sources/libetpan/low-level/imap/clientid.h b/Sources/libetpan/low-level/imap/clientid.h new file mode 100644 index 00000000..41e19a9d --- /dev/null +++ b/Sources/libetpan/low-level/imap/clientid.h @@ -0,0 +1,66 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2018, 2019 - LinuxMagic + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef CLIENTID_H + +#define CLIENTID_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap.h" + +/* + mailimap_clientid() + + This function will perform the clientid command. + + @param session IMAP session + @param type the clientid type + @param clientid the client identifier + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_clientid(mailimap * session, + const char * type, const char * clientid); + +LIBETPAN_EXPORT +int mailimap_has_clientid(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/clientid_sender.c b/Sources/libetpan/low-level/imap/clientid_sender.c new file mode 100644 index 00000000..8d0bc521 --- /dev/null +++ b/Sources/libetpan/low-level/imap/clientid_sender.c @@ -0,0 +1,70 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2018, 2019 - LinuxMagic + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailstream.h" +#include "mailimap_sender.h" +#include "clientid_sender.h" + +/* +=> clientid = "CLIENTID" SP type SP clientid +*/ + +int mailimap_clientid_send(mailstream * fd, + const char * type, const char * clientid) +{ + int r; + + r = mailimap_token_send(fd, "CLIENTID"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_astring_send(fd, type); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_astring_send(fd, clientid); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} diff --git a/Sources/libetpan/low-level/imap/clientid_sender.h b/Sources/libetpan/low-level/imap/clientid_sender.h new file mode 100644 index 00000000..d27ef010 --- /dev/null +++ b/Sources/libetpan/low-level/imap/clientid_sender.h @@ -0,0 +1,49 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2018, 2019 - LinuxMagic + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef CLIENTID_SENDER_H + +#define CLIENTID_SENDER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailstream.h" + +int mailimap_clientid_send(mailstream * fd, + const char * type, const char * clientid); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/condstore.c b/Sources/libetpan/low-level/imap/condstore.c new file mode 100644 index 00000000..455c0dd7 --- /dev/null +++ b/Sources/libetpan/low-level/imap/condstore.c @@ -0,0 +1,984 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2013 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "condstore.h" +#include "condstore_private.h" + +#include +#include +#include + +#include "mailimap_sender.h" +#include "mailimap.h" +#include "condstore_types.h" +#include "mailimap_keywords.h" +#include "mailimap_parser.h" +#include "qresync.h" +#include "qresync_private.h" + +/* + capability =/ "CONDSTORE" + + status-att =/ "HIGHESTMODSEQ" + ;; extends non-terminal defined in RFC 3501. + + status-att-val =/ "HIGHESTMODSEQ" SP mod-sequence-valzer + ;; extends non-terminal defined in [IMAPABNF]. + ;; Value 0 denotes that the mailbox doesn't + ;; support persistent mod-sequences + ;; as described in Section 3.1.2 + + store-modifier =/ "UNCHANGEDSINCE" SP mod-sequence-valzer + ;; Only a single "UNCHANGEDSINCE" may be + ;; specified in a STORE operation + + fetch-modifier =/ chgsince-fetch-mod + ;; conforms to the generic "fetch-modifier" + ;; syntax defined in [IMAPABNF]. + + chgsince-fetch-mod = "CHANGEDSINCE" SP mod-sequence-value + ;; CHANGEDSINCE FETCH modifier conforms to + ;; the fetch-modifier syntax + + fetch-att =/ fetch-mod-sequence + ;; modifies original IMAP4 fetch-att + + fetch-mod-sequence = "MODSEQ" + + fetch-mod-resp = "MODSEQ" SP "(" permsg-modsequence ")" + + msg-att-dynamic =/ fetch-mod-resp + + search-key =/ search-modsequence + ;; modifies original IMAP4 search-key + ;; + ;; This change applies to all commands + ;; referencing this non-terminal, in + ;; particular SEARCH. + + search-modsequence = "MODSEQ" [search-modseq-ext] SP + mod-sequence-valzer + + search-modseq-ext = SP entry-name SP entry-type-req + + resp-text-code =/ "HIGHESTMODSEQ" SP mod-sequence-value / + "NOMODSEQ" / + "MODIFIED" SP set + + entry-name = entry-flag-name + + entry-flag-name = DQUOTE "/flags/" attr-flag DQUOTE + ;; each system or user defined flag + ;; is mapped to "/flags/". + ;; + ;; follows the escape rules + ;; used by "quoted" string as described in + ;; Section 4.3 of [IMAP4], e.g., for the flag + ;; \Seen the corresponding is + ;; "/flags/\\seen", and for the flag + ;; $MDNSent, the corresponding + ;; is "/flags/$mdnsent". + + entry-type-resp = "priv" / "shared" + ;; metadata item type + + entry-type-req = entry-type-resp / "all" + ;; perform SEARCH operation on private + ;; metadata item, shared metadata item or both + + permsg-modsequence = mod-sequence-value + ;; per message mod-sequence + + mod-sequence-value = 1*DIGIT + ;; Positive unsigned 64-bit integer + ;; (mod-sequence) + ;; (1 <= n < 18,446,744,073,709,551,615) + + mod-sequence-valzer = "0" / mod-sequence-value + + search-sort-mod-seq = "(" "MODSEQ" SP mod-sequence-value ")" + + select-param =/ condstore-param + ;; conforms to the generic "select-param" + ;; non-terminal syntax defined in [IMAPABNF]. + + condstore-param = "CONDSTORE" + + mailbox-data =/ "SEARCH" [1*(SP nz-number) SP + search-sort-mod-seq] + + attr-flag = "\\Answered" / "\\Flagged" / "\\Deleted" / + "\\Seen" / "\\Draft" / attr-flag-keyword / + attr-flag-extension + ;; Does not include "\\Recent" + + attr-flag-extension = "\\" atom + ;; Future expansion. Client implementations + ;; MUST accept flag-extension flags. Server + ;; implementations MUST NOT generate + ;; flag-extension flags except as defined by + ;; future standard or standards-track + ;; revisions of [IMAP4]. + + attr-flag-keyword = atom +*/ + +static void + mailimap_condstore_extension_data_free(struct mailimap_extension_data * ext_data); + +static int + mailimap_condstore_extension_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, progress_function * progr_fun); + +struct mailimap_extension_api mailimap_extension_condstore = { + /* name */ "CONDSTORE", + /* extension_id */ MAILIMAP_EXTENSION_CONDSTORE, + /* parser */ mailimap_condstore_extension_parse, + /* free */ mailimap_condstore_extension_data_free +}; + +int mailimap_store_unchangedsince_optional(mailimap * session, + struct mailimap_set * set, int use_unchangedsince, uint64_t mod_sequence_valzer, + struct mailimap_store_att_flags * store_att_flags) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_store_send(session->imap_stream, set, + use_unchangedsince, mod_sequence_valzer, store_att_flags); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_STORE; + } +} + +int mailimap_uid_store_unchangedsince_optional(mailimap * session, + struct mailimap_set * set, int use_unchangedsince, uint64_t mod_sequence_valzer, + struct mailimap_store_att_flags * store_att_flags) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uid_store_send(session->imap_stream, set, + use_unchangedsince, mod_sequence_valzer, store_att_flags); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_UID_STORE; + } +} + +int mailimap_store_unchangedsince(mailimap * session, + struct mailimap_set * set, uint64_t mod_sequence_valzer, + struct mailimap_store_att_flags * store_att_flags) +{ + return mailimap_store_unchangedsince_optional(session, set, 1, mod_sequence_valzer, + store_att_flags); +} + +int mailimap_uid_store_unchangedsince(mailimap * session, + struct mailimap_set * set, uint64_t mod_sequence_valzer, + struct mailimap_store_att_flags * store_att_flags) +{ + return mailimap_uid_store_unchangedsince_optional(session, set, 1, mod_sequence_valzer, + store_att_flags); +} + +int mailimap_fetch_changedsince(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, uint64_t mod_sequence_value, + clist ** result) +{ + return mailimap_fetch_qresync_vanished(session, set, fetch_type, mod_sequence_value, 0, + result, NULL); +} + +int mailimap_uid_fetch_changedsince(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, uint64_t mod_sequence_value, + clist ** result) +{ + return mailimap_uid_fetch_qresync_vanished(session, set, fetch_type, mod_sequence_value, 0, + result, NULL); +} + +struct mailimap_fetch_att * mailimap_fetch_att_new_modseq(void) +{ + char * keyword; + struct mailimap_fetch_att * att; + + keyword = strdup("MODSEQ"); + if (keyword == NULL) + return NULL; + + att = mailimap_fetch_att_new_extension(keyword); + if (att == NULL) { + free(keyword); + return NULL; + } + + return att; +} + +struct mailimap_search_key * mailimap_search_key_new_modseq(struct mailimap_flag * entry_name, + int entry_type_req, + uint64_t modseq_valzer) +{ + struct mailimap_search_key * key; + + key = malloc(sizeof(* key)); + if (key == NULL) + return NULL; + + key->sk_type = MAILIMAP_SEARCH_KEY_MODSEQ; + key->sk_data.sk_modseq.sk_entry_name = entry_name; + key->sk_data.sk_modseq.sk_entry_type_req = entry_type_req; + key->sk_data.sk_modseq.sk_modseq_valzer = modseq_valzer; + + return key; +} + +static int search_modseq(mailimap * session, const char * charset, + struct mailimap_search_key * key, + int uid_enabled, int literalplus_enabled, + clist ** result, uint64_t * p_mod_sequence_value) +{ + struct mailimap_response * response; + int r; + int error_code; + struct mailimap_condstore_search * search_data; + clistiter * cur; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (literalplus_enabled) { + if (uid_enabled) { + r = mailimap_uid_search_literalplus_send(session->imap_stream, charset, key); + } + else { + r = mailimap_search_literalplus_send(session->imap_stream, charset, key); + } + } + else { + if (uid_enabled) { + r = mailimap_uid_search_send(session->imap_stream, charset, key); + } + else { + r = mailimap_search_send(session->imap_stream, charset, key); + } + } + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + search_data = NULL; + for(cur = clist_begin(session->imap_response_info->rsp_extension_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_extension_data * ext_data; + + ext_data = clist_content(cur); + if (ext_data->ext_extension->ext_id != MAILIMAP_EXTENSION_CONDSTORE) { + continue; + } + if (ext_data->ext_type != MAILIMAP_CONDSTORE_TYPE_SEARCH_DATA) { + continue; + } + + search_data = ext_data->ext_data; + ext_data->ext_data = NULL; + break; + } + + if (search_data == NULL) { + * result = session->imap_response_info->rsp_search_result; + if (p_mod_sequence_value != NULL) { + * p_mod_sequence_value = 0; + } + session->imap_response_info->rsp_search_result = NULL; + } + else { + * result = search_data->cs_search_result; + * p_mod_sequence_value = search_data->cs_modseq_value; + search_data->cs_search_result = NULL; + mailimap_condstore_search_free(search_data); + } + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + if (uid_enabled) { + return MAILIMAP_ERROR_UID_SEARCH; + } + else { + return MAILIMAP_ERROR_SEARCH; + } + } +} + +int mailimap_search_modseq(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result, uint64_t * p_mod_sequence_value) +{ + return search_modseq(session, charset, key, 0, 0, result, p_mod_sequence_value); +} + +int mailimap_uid_search_modseq(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result, uint64_t * p_mod_sequence_value) +{ + return search_modseq(session, charset, key, 1, 0, result, p_mod_sequence_value); +} + +LIBETPAN_EXPORT +int mailimap_search_literalplus_modseq(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result, uint64_t * p_mod_sequence_value) +{ + return search_modseq(session, charset, key, 0, 1, result, p_mod_sequence_value); +} + +LIBETPAN_EXPORT +int mailimap_uid_search_literalplus_modseq(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result, uint64_t * p_mod_sequence_value) +{ + return search_modseq(session, charset, key, 1, 1, result, p_mod_sequence_value); +} + +int mailimap_select_condstore(mailimap * session, const char * mb, uint64_t * p_mod_sequence_value) +{ + return mailimap_select_condstore_optional(session, mb, 1, p_mod_sequence_value); +} + +int mailimap_select_condstore_optional(mailimap * session, const char * mb, + int condstore, uint64_t * p_mod_sequence_value) +{ + struct mailimap_response * response; + int r; + int error_code; + uint64_t mod_sequence_value; + clistiter * cur; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_select_send(session->imap_stream, mb, condstore); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + if (session->imap_selection_info != NULL) + mailimap_selection_info_free(session->imap_selection_info); + session->imap_selection_info = mailimap_selection_info_new(); + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + mod_sequence_value = 0; + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + for(cur = clist_begin(session->imap_response_info->rsp_extension_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_extension_data * ext_data; + struct mailimap_condstore_resptextcode * resptextcode; + + ext_data = clist_content(cur); + if (ext_data->ext_extension->ext_id != MAILIMAP_EXTENSION_CONDSTORE) { + continue; + } + if (ext_data->ext_type != MAILIMAP_CONDSTORE_TYPE_RESP_TEXT_CODE) { + continue; + } + + resptextcode = ext_data->ext_data; + switch (resptextcode->cs_type) { + case MAILIMAP_CONDSTORE_RESPTEXTCODE_HIGHESTMODSEQ: + mod_sequence_value = resptextcode->cs_data.cs_modseq_value; + break; + case MAILIMAP_CONDSTORE_RESPTEXTCODE_NOMODSEQ: + mod_sequence_value = 0; + break; + } + } + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + session->imap_state = MAILIMAP_STATE_SELECTED; + * p_mod_sequence_value = mod_sequence_value; + return MAILIMAP_NO_ERROR; + + default: + mailimap_selection_info_free(session->imap_selection_info); + session->imap_selection_info = NULL; + session->imap_state = MAILIMAP_STATE_AUTHENTICATED; + * p_mod_sequence_value = mod_sequence_value; + return MAILIMAP_ERROR_SELECT; + } +} + +int mailimap_examine_condstore(mailimap * session, const char * mb, uint64_t * p_mod_sequence_value) +{ + return mailimap_examine_condstore_optional(session, mb, 1, p_mod_sequence_value); +} + +int mailimap_examine_condstore_optional(mailimap * session, const char * mb, + int condstore, uint64_t * p_mod_sequence_value) +{ + struct mailimap_response * response; + int r; + int error_code; + uint64_t mod_sequence_value; + clistiter * cur; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_examine_send(session->imap_stream, mb, condstore); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + if (session->imap_selection_info != NULL) + mailimap_selection_info_free(session->imap_selection_info); + session->imap_selection_info = mailimap_selection_info_new(); + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + mod_sequence_value = 0; + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + for(cur = clist_begin(session->imap_response_info->rsp_extension_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_extension_data * ext_data; + struct mailimap_condstore_resptextcode * resptextcode; + + ext_data = clist_content(cur); + if (ext_data->ext_extension->ext_id != MAILIMAP_EXTENSION_CONDSTORE) { + continue; + } + if (ext_data->ext_type != MAILIMAP_CONDSTORE_TYPE_RESP_TEXT_CODE) { + continue; + } + + resptextcode = ext_data->ext_data; + switch (resptextcode->cs_type) { + case MAILIMAP_CONDSTORE_RESPTEXTCODE_HIGHESTMODSEQ: + mod_sequence_value = resptextcode->cs_data.cs_modseq_value; + break; + case MAILIMAP_CONDSTORE_RESPTEXTCODE_NOMODSEQ: + mod_sequence_value = 0; + break; + } + } + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + session->imap_state = MAILIMAP_STATE_SELECTED; + * p_mod_sequence_value = mod_sequence_value; + return MAILIMAP_NO_ERROR; + + default: + mailimap_selection_info_free(session->imap_selection_info); + session->imap_selection_info = NULL; + session->imap_state = MAILIMAP_STATE_AUTHENTICATED; + * p_mod_sequence_value = mod_sequence_value; + return MAILIMAP_ERROR_EXAMINE; + } +} + +int mailimap_has_condstore(mailimap * session) +{ + return mailimap_has_extension(session, "CONDSTORE"); +} + +static int fetch_data_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, struct mailimap_condstore_fetch_mod_resp ** result) +{ + int r; + size_t cur_token; + struct mailimap_condstore_fetch_mod_resp * fetch_data; + uint64_t value; + + /* + fetch-mod-resp = "MODSEQ" SP "(" permsg-modsequence ")" + permsg-modsequence = mod-sequence-value + */ + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "MODSEQ"); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + r = mailimap_mod_sequence_value_parse(fd, buffer, parser_ctx, &cur_token, &value); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + fetch_data = mailimap_condstore_fetch_mod_resp_new(value); + if (fetch_data == NULL) { + return MAILIMAP_ERROR_MEMORY; + } + + * indx = cur_token; + * result = fetch_data; + + return MAILIMAP_NO_ERROR; +} + +static int resp_text_code_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, struct mailimap_condstore_resptextcode ** result) +{ + size_t cur_token; + struct mailimap_condstore_resptextcode * resptextcode; + int r; + + cur_token = * indx; + + /* + resp-text-code =/ "HIGHESTMODSEQ" SP mod-sequence-value / + "NOMODSEQ" / + "MODIFIED" SP set + */ + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "HIGHESTMODSEQ"); + if (r == MAILIMAP_NO_ERROR) { + uint64_t value; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + r = mailimap_mod_sequence_value_parse(fd, buffer, parser_ctx, &cur_token, &value); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + resptextcode = mailimap_condstore_resptextcode_new(MAILIMAP_CONDSTORE_RESPTEXTCODE_HIGHESTMODSEQ, value, NULL); + if (resptextcode == NULL) + return MAILIMAP_ERROR_MEMORY; + + * indx = cur_token; + * result = resptextcode; + + return MAILIMAP_NO_ERROR; + } + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "NOMODSEQ"); + if (r == MAILIMAP_NO_ERROR) { + resptextcode = mailimap_condstore_resptextcode_new(MAILIMAP_CONDSTORE_RESPTEXTCODE_NOMODSEQ, 0, NULL); + if (resptextcode == NULL) + return MAILIMAP_ERROR_MEMORY; + + * indx = cur_token; + * result = resptextcode; + + return MAILIMAP_NO_ERROR; + } + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "MODIFIED"); + if (r == MAILIMAP_NO_ERROR) { + struct mailimap_set * set; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + r = mailimap_set_parse(fd, buffer, parser_ctx, &cur_token, &set); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + resptextcode = mailimap_condstore_resptextcode_new(MAILIMAP_CONDSTORE_RESPTEXTCODE_MODIFIED, 0, set); + if (resptextcode == NULL) { + mailimap_set_free(set); + return MAILIMAP_ERROR_MEMORY; + } + + * indx = cur_token; + * result = resptextcode; + + return MAILIMAP_NO_ERROR; + } + return MAILIMAP_ERROR_PARSE; +} + +static int search_data_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, struct mailimap_condstore_search ** result) +{ + int r; + clist * number_list; + struct mailimap_condstore_search * search_data; + size_t cur_token; + int res; + uint64_t value; + + cur_token = * indx; + + /* + mailbox-data =/ "SEARCH" [1*(SP nz-number) SP + search-sort-mod-seq] + search-sort-mod-seq = "(" "MODSEQ" SP mod-sequence-value ")" + */ + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "SEARCH"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + return r; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, &cur_token, &number_list, + (mailimap_struct_parser *) + mailimap_nz_number_alloc_parse, + (mailimap_struct_destructor *) + mailimap_number_alloc_free, + 0, NULL); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_number_list; + } + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_number_list; + } + r = mailimap_mod_sequence_value_parse(fd, buffer, parser_ctx, &cur_token, &value); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_number_list; + } + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_number_list; + } + + search_data = mailimap_condstore_search_new(number_list, value); + if (search_data == NULL) { + res = r; + goto free_number_list; + } + + * indx = cur_token; + * result = search_data; + + return MAILIMAP_NO_ERROR; + +free_number_list: + clist_foreach(number_list, (clist_func) free, NULL); + clist_free(number_list); +err: + return res; +} + +static int status_info_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, struct mailimap_condstore_status_info ** result) +{ + int r; + struct mailimap_condstore_status_info * status_info; + size_t cur_token; + int status_att; + uint64_t value; + + cur_token = * indx; + + r = mailimap_status_att_parse(fd, buffer, parser_ctx, &cur_token, &status_att); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + if (status_att != MAILIMAP_STATUS_ATT_HIGHESTMODSEQ) { + return MAILIMAP_ERROR_PARSE; + } + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_mod_sequence_value_parse(fd, buffer, parser_ctx, &cur_token, &value); + if (r != MAILIMAP_NO_ERROR) + return r; + + status_info = mailimap_condstore_status_info_new(value); + if (status_info == NULL) + return MAILIMAP_ERROR_MEMORY; + + * result = status_info; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +static int + mailimap_condstore_extension_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, progress_function * progr_fun) +{ + size_t cur_token; + int r; + + cur_token = * indx; + + switch (calling_parser) { + case MAILIMAP_EXTENDED_PARSER_FETCH_DATA: { + struct mailimap_condstore_fetch_mod_resp * fetch_data; + struct mailimap_extension_data * ext_data; + + r = fetch_data_parse(fd, buffer, parser_ctx, &cur_token, &fetch_data); + if (r != MAILIMAP_NO_ERROR) + return r; + ext_data = mailimap_extension_data_new(&mailimap_extension_condstore, + MAILIMAP_CONDSTORE_TYPE_FETCH_DATA, fetch_data); + if (ext_data == NULL) { + mailimap_condstore_fetch_mod_resp_free(fetch_data); + return MAILIMAP_ERROR_MEMORY; + } + * indx = cur_token; + * result = ext_data; + return MAILIMAP_NO_ERROR; + } + + case MAILIMAP_EXTENDED_PARSER_RESP_TEXT_CODE: { + struct mailimap_condstore_resptextcode * resptextcode; + struct mailimap_extension_data * ext_data; + + r = resp_text_code_parse(fd, buffer, parser_ctx, &cur_token, &resptextcode); + if (r != MAILIMAP_NO_ERROR) + return r; + ext_data = mailimap_extension_data_new(&mailimap_extension_condstore, + MAILIMAP_CONDSTORE_TYPE_RESP_TEXT_CODE, resptextcode); + if (ext_data == NULL) { + mailimap_condstore_resptextcode_free(resptextcode); + return MAILIMAP_ERROR_MEMORY; + } + * indx = cur_token; + * result = ext_data; + return MAILIMAP_NO_ERROR; + } + + case MAILIMAP_EXTENDED_PARSER_MAILBOX_DATA: { + struct mailimap_condstore_search * search_data; + struct mailimap_extension_data * ext_data; + + search_data = NULL; + r = search_data_parse(fd, buffer, parser_ctx, &cur_token, &search_data); + if (r != MAILIMAP_NO_ERROR) + return r; + ext_data = mailimap_extension_data_new(&mailimap_extension_condstore, + MAILIMAP_CONDSTORE_TYPE_SEARCH_DATA, search_data); + if (ext_data == NULL) { + mailimap_condstore_search_free(search_data); + return MAILIMAP_ERROR_MEMORY; + } + * indx = cur_token; + * result = ext_data; + return MAILIMAP_NO_ERROR; + } + + case MAILIMAP_EXTENDED_PARSER_STATUS_ATT: { + struct mailimap_condstore_status_info * status_info; + struct mailimap_extension_data * ext_data; + + r = status_info_parse(fd, buffer, parser_ctx, &cur_token, &status_info); + if (r != MAILIMAP_NO_ERROR) + return r; + ext_data = mailimap_extension_data_new(&mailimap_extension_condstore, + MAILIMAP_CONDSTORE_TYPE_STATUS_INFO, status_info); + if (ext_data == NULL) { + mailimap_condstore_status_info_free(status_info); + return MAILIMAP_ERROR_MEMORY; + } + * indx = cur_token; + * result = ext_data; + return MAILIMAP_NO_ERROR; + } + } + + return MAILIMAP_ERROR_PARSE; +} + +static void + mailimap_condstore_extension_data_free(struct mailimap_extension_data * ext_data) +{ + switch (ext_data->ext_type) { + case MAILIMAP_CONDSTORE_TYPE_FETCH_DATA: + mailimap_condstore_fetch_mod_resp_free(ext_data->ext_data); + break; + case MAILIMAP_CONDSTORE_TYPE_RESP_TEXT_CODE: + mailimap_condstore_resptextcode_free(ext_data->ext_data); + break; + case MAILIMAP_CONDSTORE_TYPE_SEARCH_DATA: + mailimap_condstore_search_free(ext_data->ext_data); + break; + case MAILIMAP_CONDSTORE_TYPE_STATUS_INFO: + mailimap_condstore_status_info_free(ext_data->ext_data); + break; + } + + free(ext_data); +} diff --git a/Sources/libetpan/low-level/imap/condstore.h b/Sources/libetpan/low-level/imap/condstore.h new file mode 100644 index 00000000..2e2f56c9 --- /dev/null +++ b/Sources/libetpan/low-level/imap/condstore.h @@ -0,0 +1,101 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2013 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef CONDSTORE_H + +#define CONDSTORE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +LIBETPAN_EXPORT +extern struct mailimap_extension_api mailimap_extension_condstore; + +LIBETPAN_EXPORT +int mailimap_store_unchangedsince(mailimap * session, + struct mailimap_set * set, uint64_t mod_sequence_valzer, + struct mailimap_store_att_flags * store_att_flags); + +LIBETPAN_EXPORT +int mailimap_uid_store_unchangedsince(mailimap * session, + struct mailimap_set * set, uint64_t mod_sequence_valzer, + struct mailimap_store_att_flags * store_att_flags); + +LIBETPAN_EXPORT +int mailimap_fetch_changedsince(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, uint64_t mod_sequence_value, + clist ** result); + +LIBETPAN_EXPORT +int mailimap_uid_fetch_changedsince(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, uint64_t mod_sequence_value, + clist ** result); + +LIBETPAN_EXPORT +struct mailimap_fetch_att * mailimap_fetch_att_new_modseq(void); + +LIBETPAN_EXPORT +int mailimap_search_modseq(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result, uint64_t * p_mod_sequence_value); + +LIBETPAN_EXPORT +int mailimap_uid_search_modseq(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result, uint64_t * p_mod_sequence_value); + +LIBETPAN_EXPORT +int mailimap_search_literalplus_modseq(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result, uint64_t * p_mod_sequence_value); + +LIBETPAN_EXPORT +int mailimap_uid_search_literalplus_modseq(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result, uint64_t * p_mod_sequence_value); + +LIBETPAN_EXPORT +int mailimap_select_condstore(mailimap * session, const char * mb, uint64_t * p_mod_sequence_value); + +LIBETPAN_EXPORT +int mailimap_examine_condstore(mailimap * session, const char * mb, uint64_t * p_mod_sequence_value); + +LIBETPAN_EXPORT +int mailimap_has_condstore(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/condstore_private.h b/Sources/libetpan/low-level/imap/condstore_private.h new file mode 100644 index 00000000..f9240d9a --- /dev/null +++ b/Sources/libetpan/low-level/imap/condstore_private.h @@ -0,0 +1,50 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2013 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef CONDSTORE_PRIVATE_H + +#define CONDSTORE_PRIVATE_H + +int mailimap_examine_condstore_optional(mailimap * session, const char * mb, + int condstore, uint64_t * p_mod_sequence_value); + +int mailimap_select_condstore_optional(mailimap * session, const char * mb, + int condstore, uint64_t * p_mod_sequence_value); + +int mailimap_store_unchangedsince_optional(mailimap * session, + struct mailimap_set * set, int use_unchangedsince, uint64_t mod_sequence_valzer, + struct mailimap_store_att_flags * store_att_flags); + +int mailimap_uid_store_unchangedsince_optional(mailimap * session, + struct mailimap_set * set, int use_unchangedsince, uint64_t mod_sequence_valzer, + struct mailimap_store_att_flags * store_att_flags); + +#endif diff --git a/Sources/libetpan/low-level/imap/condstore_types.c b/Sources/libetpan/low-level/imap/condstore_types.c new file mode 100644 index 00000000..e6f9f03a --- /dev/null +++ b/Sources/libetpan/low-level/imap/condstore_types.c @@ -0,0 +1,140 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2013 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "condstore_types.h" + +#include + +LIBETPAN_EXPORT +struct mailimap_condstore_fetch_mod_resp * mailimap_condstore_fetch_mod_resp_new(uint64_t cs_modseq_value) +{ + struct mailimap_condstore_fetch_mod_resp * fetch_data; + + fetch_data = malloc(sizeof(* fetch_data)); + if (fetch_data == NULL) + return NULL; + + fetch_data->cs_modseq_value = cs_modseq_value; + + return fetch_data; +} + +LIBETPAN_EXPORT +void mailimap_condstore_fetch_mod_resp_free(struct mailimap_condstore_fetch_mod_resp * fetch_data) +{ + free(fetch_data); +} + +LIBETPAN_EXPORT +struct mailimap_condstore_resptextcode * mailimap_condstore_resptextcode_new(int cs_type, + uint64_t cs_modseq_value, struct mailimap_set * cs_modified_set) +{ + struct mailimap_condstore_resptextcode * resptextcode; + + resptextcode = malloc(sizeof(* resptextcode)); + if (resptextcode == NULL) + return NULL; + + resptextcode->cs_type = cs_type; + switch (cs_type) { + case MAILIMAP_CONDSTORE_RESPTEXTCODE_HIGHESTMODSEQ: + resptextcode->cs_data.cs_modseq_value = cs_modseq_value; + break; + case MAILIMAP_CONDSTORE_RESPTEXTCODE_NOMODSEQ: + break; + case MAILIMAP_CONDSTORE_RESPTEXTCODE_MODIFIED: + resptextcode->cs_data.cs_modified_set = cs_modified_set; + break; + } + + return resptextcode; +} + +LIBETPAN_EXPORT +void mailimap_condstore_resptextcode_free(struct mailimap_condstore_resptextcode * resptextcode) +{ + switch (resptextcode->cs_type) { + case MAILIMAP_CONDSTORE_RESPTEXTCODE_HIGHESTMODSEQ: + break; + case MAILIMAP_CONDSTORE_RESPTEXTCODE_NOMODSEQ: + break; + case MAILIMAP_CONDSTORE_RESPTEXTCODE_MODIFIED: + mailimap_set_free(resptextcode->cs_data.cs_modified_set); + break; + } + free(resptextcode); +} + +LIBETPAN_EXPORT +struct mailimap_condstore_search * mailimap_condstore_search_new(clist * cs_search_result, uint64_t cs_modseq_value) +{ + struct mailimap_condstore_search * search_data; + + search_data = malloc(sizeof(* search_data)); + if (search_data == NULL) + return NULL; + + search_data->cs_search_result = cs_search_result; + search_data->cs_modseq_value = cs_modseq_value; + + return search_data; +} + +LIBETPAN_EXPORT +void mailimap_condstore_search_free(struct mailimap_condstore_search * search_data) +{ + if (search_data->cs_search_result != NULL) { + clist_foreach(search_data->cs_search_result, (clist_func) free, NULL); + clist_free(search_data->cs_search_result); + } + free(search_data); +} + +LIBETPAN_EXPORT +struct mailimap_condstore_status_info * mailimap_condstore_status_info_new(uint64_t cs_highestmodseq_value) +{ + struct mailimap_condstore_status_info * status_info; + + status_info = malloc(sizeof(* status_info)); + if (status_info == NULL) + return NULL; + + status_info->cs_highestmodseq_value = cs_highestmodseq_value; + + return status_info; +} + +LIBETPAN_EXPORT +void mailimap_condstore_status_info_free(struct mailimap_condstore_status_info * status_info) +{ + free(status_info); +} + diff --git a/Sources/libetpan/low-level/imap/condstore_types.h b/Sources/libetpan/low-level/imap/condstore_types.h new file mode 100644 index 00000000..65a7e7d8 --- /dev/null +++ b/Sources/libetpan/low-level/imap/condstore_types.h @@ -0,0 +1,97 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2013 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef CONDSTORE_TYPE_H + +#define CONDSTORE_TYPE_H + +#include + +enum { + MAILIMAP_CONDSTORE_TYPE_FETCH_DATA, + MAILIMAP_CONDSTORE_TYPE_RESP_TEXT_CODE, + MAILIMAP_CONDSTORE_TYPE_SEARCH_DATA, + MAILIMAP_CONDSTORE_TYPE_STATUS_INFO +}; + +struct mailimap_condstore_fetch_mod_resp { + uint64_t cs_modseq_value; +}; + +enum { + MAILIMAP_CONDSTORE_RESPTEXTCODE_HIGHESTMODSEQ, + MAILIMAP_CONDSTORE_RESPTEXTCODE_NOMODSEQ, + MAILIMAP_CONDSTORE_RESPTEXTCODE_MODIFIED +}; + +struct mailimap_condstore_resptextcode { + int cs_type; + union { + uint64_t cs_modseq_value; + struct mailimap_set * cs_modified_set; + } cs_data; +}; + +struct mailimap_condstore_search { + clist * cs_search_result; /* uint32_t */ + uint64_t cs_modseq_value; +}; + +struct mailimap_condstore_status_info { + uint64_t cs_highestmodseq_value; +}; + +LIBETPAN_EXPORT +struct mailimap_condstore_fetch_mod_resp * mailimap_condstore_fetch_mod_resp_new(uint64_t cs_modseq_value); + +LIBETPAN_EXPORT +void mailimap_condstore_fetch_mod_resp_free(struct mailimap_condstore_fetch_mod_resp * fetch_data); + +LIBETPAN_EXPORT +struct mailimap_condstore_resptextcode * mailimap_condstore_resptextcode_new(int cs_type, + uint64_t cs_modseq_value, struct mailimap_set * cs_modified_set); + +LIBETPAN_EXPORT +void mailimap_condstore_resptextcode_free(struct mailimap_condstore_resptextcode * resptextcode); + +LIBETPAN_EXPORT +struct mailimap_condstore_search * mailimap_condstore_search_new(clist * cs_search_result, uint64_t cs_modseq_value); + +LIBETPAN_EXPORT +void mailimap_condstore_search_free(struct mailimap_condstore_search * search_data); + +LIBETPAN_EXPORT +struct mailimap_condstore_status_info * mailimap_condstore_status_info_new(uint64_t cs_highestmodseq_value); + +LIBETPAN_EXPORT +void mailimap_condstore_status_info_free(struct mailimap_condstore_status_info * status_info); + +#endif diff --git a/Sources/libetpan/low-level/imap/enable.c b/Sources/libetpan/low-level/imap/enable.c new file mode 100644 index 00000000..5191961e --- /dev/null +++ b/Sources/libetpan/low-level/imap/enable.c @@ -0,0 +1,317 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2011 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "enable.h" + +#include + +#include "mailimap_parser.h" +#include "mailimap_sender.h" +#include "mailimap.h" +#include "mailimap_keywords.h" + +enum { + MAILIMAP_ENABLE_TYPE_ENABLE +}; + +static int +mailimap_enable_extension_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, progress_function * progr_fun); + +static void +mailimap_enable_extension_data_free(struct mailimap_extension_data * ext_data); + +LIBETPAN_EXPORT +struct mailimap_extension_api mailimap_extension_enable = { + /* name */ "ENABLE", + /* extension_id */ MAILIMAP_EXTENSION_ENABLE, + /* parser */ mailimap_enable_extension_parse, + /* free */ mailimap_enable_extension_data_free +}; + +/* +"ENABLE" 1*(SP capability) +*/ + +static int mailimap_capability_info_send(mailstream * fd, struct mailimap_capability * cap) +{ + int r; + + switch (cap->cap_type) { + case MAILIMAP_CAPABILITY_AUTH_TYPE: + r = mailimap_token_send(fd, "AUTH="); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_token_send(fd, cap->cap_data.cap_auth_type); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_CAPABILITY_NAME: + r = mailimap_token_send(fd, cap->cap_data.cap_name); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_INVAL; + } +} + +static int mailimap_capability_data_send(mailstream * fd, struct mailimap_capability_data * capabilities) +{ + return mailimap_struct_spaced_list_send(fd, capabilities->cap_list, + (mailimap_struct_sender *) mailimap_capability_info_send); +} + +static int mailimap_enable_send(mailstream * fd, struct mailimap_capability_data * capabilities) +{ + int r; + + r = mailimap_token_send(fd, "ENABLE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_capability_data_send(fd, capabilities); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailimap_enable(mailimap * session, struct mailimap_capability_data * capabilities, + struct mailimap_capability_data ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + clistiter * cur; + struct mailimap_capability_data * cap_data; + + if (session->imap_state != MAILIMAP_STATE_AUTHENTICATED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_enable_send(session->imap_stream, capabilities); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + + cap_data = NULL; + for(cur = clist_begin(session->imap_response_info->rsp_extension_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_extension_data * ext_data; + + ext_data = clist_content(cur); + if (ext_data->ext_extension->ext_id != MAILIMAP_EXTENSION_ENABLE) { + continue; + } + if (ext_data->ext_type != MAILIMAP_ENABLE_TYPE_ENABLE) { + continue; + } + + if (cap_data != NULL) { + mailimap_capability_data_free(cap_data); + } + cap_data = ext_data->ext_data; + ext_data->ext_data = NULL; + break; + } + if (cap_data == NULL) { + clist * list; + + list = clist_new(); + if (list == NULL) { + return MAILIMAP_ERROR_MEMORY; + } + cap_data = mailimap_capability_data_new(list); + if (cap_data == NULL) { + clist_free(list); + return MAILIMAP_ERROR_MEMORY; + } + } + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + * result = cap_data; + return MAILIMAP_NO_ERROR; + + default: + mailimap_capability_data_free(cap_data); + return MAILIMAP_ERROR_EXTENSION; + } +} + + +LIBETPAN_EXPORT +int mailimap_has_enable(mailimap * session) +{ + return mailimap_has_extension(session, "ENABLE"); +} + +static void +mailimap_enable_extension_data_free(struct mailimap_extension_data * ext_data) +{ + if (ext_data->ext_data != NULL) { + mailimap_capability_data_free((struct mailimap_capability_data *) ext_data->ext_data); + } + free(ext_data); +} + +static int mailimap_enable_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_capability_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int r; + int res; + struct mailimap_capability_data * capabilities; + clist * cap_list; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "ENABLED"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_capability_list_parse(fd, buffer, parser_ctx, &cur_token, + &cap_list, + progr_rate, progr_fun); + if (r == MAILIMAP_ERROR_PARSE) { + cap_list = clist_new(); + if (cap_list == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto err; + } + r = MAILIMAP_NO_ERROR; + } + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + capabilities = mailimap_capability_data_new(cap_list); + if (capabilities == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_list; + } + + * result = capabilities; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + +free_list: + if (cap_list) { + clist_foreach(cap_list, (clist_func) mailimap_capability_free, NULL); + clist_free(cap_list); + } +err: + return res; +} + +static int +mailimap_enable_extension_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, progress_function * progr_fun) +{ + int r; + struct mailimap_capability_data * capabilities = NULL; + struct mailimap_extension_data * ext_data; + void * data; + int type; + size_t cur_token; + + cur_token = * indx; + + switch (calling_parser) + { + case MAILIMAP_EXTENDED_PARSER_RESPONSE_DATA: + r = mailimap_enable_parse(fd, buffer, parser_ctx, &cur_token, + &capabilities, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + type = MAILIMAP_ENABLE_TYPE_ENABLE; + data = capabilities; + + ext_data = mailimap_extension_data_new(&mailimap_extension_enable, + type, data); + if (ext_data == NULL) { + if (capabilities != NULL) + mailimap_capability_data_free(capabilities); + return MAILIMAP_ERROR_MEMORY; + } + + * result = ext_data; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + default: + /* return a MAILIMAP_ERROR_PARSE if the extension + doesn't extend calling_parser. */ + return MAILIMAP_ERROR_PARSE; + } +} + diff --git a/Sources/libetpan/low-level/imap/enable.h b/Sources/libetpan/low-level/imap/enable.h new file mode 100644 index 00000000..4023af28 --- /dev/null +++ b/Sources/libetpan/low-level/imap/enable.h @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2011 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ENABLE_H + +#define ENABLE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +LIBETPAN_EXPORT +extern struct mailimap_extension_api mailimap_extension_enable; + +LIBETPAN_EXPORT +int mailimap_enable(mailimap * session, struct mailimap_capability_data * capabilities, + struct mailimap_capability_data ** result); + +LIBETPAN_EXPORT +int mailimap_has_enable(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/idle.c b/Sources/libetpan/low-level/imap/idle.c new file mode 100644 index 00000000..caacd5cd --- /dev/null +++ b/Sources/libetpan/low-level/imap/idle.c @@ -0,0 +1,218 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "idle.h" + +#ifdef WIN32 +# include +#endif + +#include +#include + +#include "mailimap_sender.h" +#include "mailimap_parser.h" +#include "mailimap.h" + +static int mailimap_idle_send(mailimap * session) +{ + int r; + + r = mailimap_token_send(session->imap_stream, "IDLE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +static int mailimap_done_send(mailimap * session) +{ + int r; + + r = mailimap_token_send(session->imap_stream, "DONE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailimap_idle(mailimap * session) +{ + int r; + size_t indx; + struct mailimap_continue_req * cont_req; + struct mailimap_response * response; + clist * resp_data_list; + struct mailimap_parser_context * parser_ctx; + + session->imap_selection_info->sel_has_exists = 0; + session->imap_selection_info->sel_has_recent = 0; + session->imap_idle_timestamp = time(NULL); + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_idle_send(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + indx = 0; + + parser_ctx = mailimap_parser_context_new(session); + if (parser_ctx == NULL) + return MAILIMAP_ERROR_MEMORY; + + r = mailimap_struct_multiple_parse(session->imap_stream, + session->imap_stream_buffer, parser_ctx, + &indx, + &resp_data_list, + (mailimap_struct_parser *) + mailimap_response_data_parse, + (mailimap_struct_destructor *) + mailimap_response_data_free, + session->imap_progr_rate, session->imap_progr_fun); + mailimap_parser_context_free(parser_ctx); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; + if (r == MAILIMAP_NO_ERROR) { + clist_foreach(resp_data_list, + (clist_func) mailimap_response_data_free, NULL); + clist_free(resp_data_list); + } + + r = mailimap_continue_req_parse(session->imap_stream, + session->imap_stream_buffer, NULL, + &indx, &cont_req, + session->imap_progr_rate, session->imap_progr_fun); + + if (r == MAILIMAP_NO_ERROR) + mailimap_continue_req_free(cont_req); + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + mailimap_response_free(response); + + return MAILIMAP_ERROR_PARSE; + } + + return MAILIMAP_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailimap_idle_done(mailimap * session) +{ + int r; + int error_code; + struct mailimap_response * response; + + r = mailimap_done_send(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_EXTENSION; + } +} + +LIBETPAN_EXPORT +int mailimap_idle_get_fd(mailimap * session) +{ + mailstream_low * low; + + low = mailstream_get_low(session->imap_stream); + return mailstream_low_get_fd(low); +} + +LIBETPAN_EXPORT +void mailimap_idle_set_delay(mailimap * session, long delay) +{ + session->imap_idle_maxdelay = delay; +} + +LIBETPAN_EXPORT +long mailimap_idle_get_done_delay(mailimap * session) +{ + time_t current_time; + time_t next_date; + + current_time = time(NULL); + next_date = session->imap_idle_timestamp + session->imap_idle_maxdelay; + + if (current_time >= next_date) + return 0; + + return next_date - current_time; +} + +LIBETPAN_EXPORT +int mailimap_has_idle(mailimap * session) +{ + return mailimap_has_extension(session, "IDLE"); +} diff --git a/Sources/libetpan/low-level/imap/idle.h b/Sources/libetpan/low-level/imap/idle.h new file mode 100644 index 00000000..93d6d704 --- /dev/null +++ b/Sources/libetpan/low-level/imap/idle.h @@ -0,0 +1,64 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILIMAP_IDLE_H + +#define MAILIMAP_IDLE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_types.h" + +LIBETPAN_EXPORT +int mailimap_idle(mailimap * session); + +LIBETPAN_EXPORT +int mailimap_idle_done(mailimap * session); + +LIBETPAN_EXPORT +int mailimap_idle_get_fd(mailimap * session); + +/* delay in seconds */ +LIBETPAN_EXPORT +void mailimap_idle_set_delay(mailimap * session, long delay); + +LIBETPAN_EXPORT +long mailimap_idle_get_done_delay(mailimap * session); + +LIBETPAN_EXPORT +int mailimap_has_idle(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/mailimap.c b/Sources/libetpan/low-level/imap/mailimap.c new file mode 100644 index 00000000..4ffcf55d --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap.c @@ -0,0 +1,2806 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap.c,v 1.51 2011/07/10 23:10:12 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailimap.h" +#include "mailimap_parser.h" +#include "mailimap_sender.h" +#include "mailimap_extension.h" +#include "mail.h" +#include "condstore.h" +#include "condstore_private.h" + +#include +#include +#include + +#ifdef USE_SASL +#include +#include +#endif + +#include "mailsasl.h" + +#ifdef DEBUG +#include "mailimap_print.h" +#endif + +/* + RFC 2060 : IMAP4rev1 + draft-crispin-imapv-15 + RFC 2222 : Simple Authentication and Security Layer + +2061 IMAP4 Compatibility with IMAP2bis. M. Crispin. December 1996. + (Format: TXT=5867 bytes) (Obsoletes RFC1730) (Status: INFORMATIONAL) + +2062 Internet Message Access Protocol - Obsolete Syntax. M. Crispin. + December 1996. (Format: TXT=14222 bytes) (Status: INFORMATIONAL) + +2086 IMAP4 ACL extension. J. Myers. January 1997. (Format: TXT=13925 + bytes) (Status: PROPOSED STANDARD) + +2087 IMAP4 QUOTA extension. J. Myers. January 1997. (Format: TXT=8542 + bytes) (Status: PROPOSED STANDARD) + +2088 IMAP4 non-synchronizing literals. J. Myers. January 1997. + (Format: TXT=4052 bytes) (Status: PROPOSED STANDARD) + +2177 IMAP4 IDLE command. B. Leiba. June 1997. (Format: TXT=6770 bytes) + (Status: PROPOSED STANDARD) + +2180 IMAP4 Multi-Accessed Mailbox Practice. M. Gahrns. July 1997. + (Format: TXT=24750 bytes) (Status: INFORMATIONAL) + +2192 IMAP URL Scheme. C. Newman. September 1997. (Format: TXT=31426 + bytes) (Status: PROPOSED STANDARD) + +2193 IMAP4 Mailbox Referrals. M. Gahrns. September 1997. (Format: + TXT=16248 bytes) (Status: PROPOSED STANDARD) + +2195 IMAP/POP AUTHorize Extension for Simple Challenge/Response. J. + Klensin, R. Catoe, P. Krumviede. September 1997. (Format: TXT=10468 + bytes) (Obsoletes RFC2095) (Status: PROPOSED STANDARD) + +2221 IMAP4 Login Referrals. M. Gahrns. October 1997. (Format: TXT=9251 + bytes) (Status: PROPOSED STANDARD) + +2342 IMAP4 Namespace. M. Gahrns, C. Newman. May 1998. (Format: + TXT=19489 bytes) (Status: PROPOSED STANDARD) + +2359 IMAP4 UIDPLUS extension. J. Myers. June 1998. (Format: TXT=10862 + bytes) (Status: PROPOSED STANDARD) + +2595 Using TLS with IMAP, POP3 and ACAP. C. Newman. June 1999. + (Format: TXT=32440 bytes) (Status: PROPOSED STANDARD) + +2683 IMAP4 Implementation Recommendations. B. Leiba. September 1999. + (Format: TXT=56300 bytes) (Status: INFORMATIONAL) + +2971 IMAP4 ID extension. T. Showalter. October 2000. (Format: + TXT=14670 bytes) (Status: PROPOSED STANDARD) + +http://www.ietf.org/ids.by.wg/imapext.html +*/ + +static inline void imap_logger(mailstream * s, int log_type, + const char * str, size_t size, void * context); + +static int parse_greeting(mailimap * session, + struct mailimap_greeting ** result); + + +/* struct mailimap_response_info * */ + +static void resp_text_store(mailimap * session, + struct mailimap_resp_text * + resp_text) +{ + struct mailimap_resp_text_code * resp_text_code; + + resp_text_code = resp_text->rsp_code; + + if (resp_text_code != NULL) { + switch (resp_text_code->rc_type) { + case MAILIMAP_RESP_TEXT_CODE_ALERT: + if (session->imap_response_info) { + if (session->imap_response_info->rsp_alert != NULL) + free(session->imap_response_info->rsp_alert); + session->imap_response_info->rsp_alert = strdup(resp_text->rsp_text); + } + break; + + case MAILIMAP_RESP_TEXT_CODE_BADCHARSET: + if (session->imap_response_info) { + if (session->imap_response_info->rsp_badcharset != NULL) { + clist_foreach(resp_text_code->rc_data.rc_badcharset, + (clist_func) mailimap_astring_free, NULL); + clist_free(resp_text_code->rc_data.rc_badcharset); + } + session->imap_response_info->rsp_badcharset = + resp_text_code->rc_data.rc_badcharset; + resp_text_code->rc_data.rc_badcharset = NULL; + } + break; + + case MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA: + if (session->imap_connection_info) { + if (session->imap_connection_info->imap_capability != NULL) + mailimap_capability_data_free(session->imap_connection_info->imap_capability); + session->imap_connection_info->imap_capability = + resp_text_code->rc_data.rc_cap_data; + /* detach before free */ + resp_text_code->rc_data.rc_cap_data = NULL; + } + break; + + case MAILIMAP_RESP_TEXT_CODE_PARSE: + if (session->imap_response_info) { + if (session->imap_response_info->rsp_parse != NULL) + free(session->imap_response_info->rsp_parse); + session->imap_response_info->rsp_parse = strdup(resp_text->rsp_text); + } + break; + + case MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS: + if (session->imap_selection_info) { + if (session->imap_selection_info->sel_perm_flags != NULL) { + clist_foreach(session->imap_selection_info->sel_perm_flags, + (clist_func) mailimap_flag_perm_free, NULL); + clist_free(session->imap_selection_info->sel_perm_flags); + } + session->imap_selection_info->sel_perm_flags = + resp_text_code->rc_data.rc_perm_flags; + /* detach before free */ + resp_text_code->rc_data.rc_perm_flags = NULL; + } + break; + + case MAILIMAP_RESP_TEXT_CODE_READ_ONLY: + if (session->imap_selection_info) + session->imap_selection_info->sel_perm = MAILIMAP_MAILBOX_READONLY; + break; + + case MAILIMAP_RESP_TEXT_CODE_READ_WRITE: + if (session->imap_selection_info) + session->imap_selection_info->sel_perm = MAILIMAP_MAILBOX_READWRITE; + break; + + case MAILIMAP_RESP_TEXT_CODE_TRY_CREATE: + if (session->imap_response_info) + session->imap_response_info->rsp_trycreate = TRUE; + break; + + case MAILIMAP_RESP_TEXT_CODE_UIDNEXT: + if (session->imap_selection_info) + session->imap_selection_info->sel_uidnext = + resp_text_code->rc_data.rc_uidnext; + break; + + case MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY: + if (session->imap_selection_info) + session->imap_selection_info->sel_uidvalidity = + resp_text_code->rc_data.rc_uidvalidity; + break; + + case MAILIMAP_RESP_TEXT_CODE_UNSEEN: + if (session->imap_selection_info) + session->imap_selection_info->sel_first_unseen = + resp_text_code->rc_data.rc_first_unseen; + break; + + case MAILIMAP_RESP_TEXT_CODE_OTHER: + if (session->imap_response_info) { + if (session->imap_response_info->rsp_atom != NULL) + free(session->imap_response_info->rsp_atom); + if (session->imap_response_info->rsp_value != NULL) + free(session->imap_response_info->rsp_value); + session->imap_response_info->rsp_atom = + resp_text_code->rc_data.rc_atom.atom_name; + resp_text_code->rc_data.rc_atom.atom_name = NULL; + session->imap_response_info->rsp_value = + resp_text_code->rc_data.rc_atom.atom_value; + resp_text_code->rc_data.rc_atom.atom_value = NULL; + } + break; + case MAILIMAP_RESP_TEXT_CODE_EXTENSION: + mailimap_extension_data_store(session, &(resp_text_code->rc_data.rc_ext_data)); + break; + } + } +} + +static void resp_cond_state_store(mailimap * session, + struct mailimap_resp_cond_state * resp_cond_state) +{ + resp_text_store(session, resp_cond_state->rsp_text); +} + +static void mailbox_data_store(mailimap * session, + struct mailimap_mailbox_data * mb_data) +{ + int r; + + switch (mb_data->mbd_type) { + case MAILIMAP_MAILBOX_DATA_FLAGS: + if (session->imap_selection_info) { + if (session->imap_selection_info->sel_flags != NULL) + mailimap_flag_list_free(session->imap_selection_info->sel_flags); + session->imap_selection_info->sel_flags = mb_data->mbd_data.mbd_flags; + mb_data->mbd_data.mbd_flags = NULL; + } + break; + + case MAILIMAP_MAILBOX_DATA_LIST: + if (session->imap_response_info) { + r = clist_append(session->imap_response_info->rsp_mailbox_list, + mb_data->mbd_data.mbd_list); + if (r == 0) + mb_data->mbd_data.mbd_list = NULL; + else { + /* TODO must handle error case */ + } + } + break; + + case MAILIMAP_MAILBOX_DATA_LSUB: + if (session->imap_response_info) { + r = clist_append(session->imap_response_info->rsp_mailbox_lsub, + mb_data->mbd_data.mbd_lsub); + if (r == 0) + mb_data->mbd_data.mbd_lsub = NULL; + else { + /* TODO must handle error case */ + } + } + break; + + case MAILIMAP_MAILBOX_DATA_SEARCH: + if (session->imap_response_info) { + if (session->imap_response_info->rsp_search_result != NULL) { + if (mb_data->mbd_data.mbd_search != NULL) { + clist_concat(session->imap_response_info->rsp_search_result, + mb_data->mbd_data.mbd_search); + clist_free(mb_data->mbd_data.mbd_search); + mb_data->mbd_data.mbd_search = NULL; + } + } + else { + if (mb_data->mbd_data.mbd_search != NULL) { + session->imap_response_info->rsp_search_result = + mb_data->mbd_data.mbd_search; + mb_data->mbd_data.mbd_search = NULL; + } + } + } + break; + + case MAILIMAP_MAILBOX_DATA_STATUS: + if (session->imap_response_info) { + if (session->imap_response_info->rsp_status != NULL) + mailimap_mailbox_data_status_free(session->imap_response_info->rsp_status); + session->imap_response_info->rsp_status = mb_data->mbd_data.mbd_status; +#if 0 + if (session->imap_selection_info != NULL) { + clistiter * cur; + + for(cur = clist_begin(mb_data->status->status_info_list) + ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_status_info * info; + + info = clist_content(cur); + switch (info->att) { + case MAILIMAP_STATUS_ATT_MESSAGES: + session->imap_selection_info->exists = info->value; + break; + case MAILIMAP_STATUS_ATT_RECENT: + session->imap_selection_info->recent = info->value; + break; + case MAILIMAP_STATUS_ATT_UIDNEXT: + session->imap_selection_info->uidnext = info->value; + break; + case MAILIMAP_STATUS_ATT_UIDVALIDITY: + session->imap_selection_info->uidvalidity = info->value; + break; + case MAILIMAP_STATUS_ATT_UNSEEN: + session->imap_selection_info->unseen = info->value; + break; + } + } + } +#endif +#if 0 + mailimap_mailbox_data_status_free(mb_data->status); +#endif + mb_data->mbd_data.mbd_status = NULL; + } + break; + + case MAILIMAP_MAILBOX_DATA_EXISTS: + if (session->imap_selection_info) { + session->imap_selection_info->sel_exists = mb_data->mbd_data.mbd_exists; + session->imap_selection_info->sel_has_exists = 1; + } + break; + + case MAILIMAP_MAILBOX_DATA_RECENT: + if (session->imap_selection_info) { + session->imap_selection_info->sel_recent = mb_data->mbd_data.mbd_recent; + session->imap_selection_info->sel_has_recent = 1; + } + break; + case MAILIMAP_MAILBOX_DATA_EXTENSION_DATA: + mailimap_extension_data_store(session, &mb_data->mbd_data.mbd_extension); + break; + } +} + +static void +message_data_store(mailimap * session, + struct mailimap_message_data * msg_data) +{ + uint32_t * expunged; + int r; + + switch (msg_data->mdt_type) { + case MAILIMAP_MESSAGE_DATA_EXPUNGE: + if (session->imap_response_info) { + expunged = mailimap_number_alloc_new(msg_data->mdt_number); + if (expunged != NULL) { + r = clist_append(session->imap_response_info->rsp_expunged, expunged); + if (r == 0) { + /* do nothing */ + } + else { + /* TODO : must handle error case */ + mailimap_number_alloc_free(expunged); + } + if (session->imap_selection_info != NULL) + session->imap_selection_info->sel_exists --; + } + } + break; + + case MAILIMAP_MESSAGE_DATA_FETCH: + r = clist_append(session->imap_response_info->rsp_fetch_list, + msg_data->mdt_msg_att); + if (r == 0) { + msg_data->mdt_msg_att->att_number = msg_data->mdt_number; + msg_data->mdt_msg_att = NULL; + } + else { + /* TODO : must handle error case */ + } + break; + } +} + +static void +cont_req_or_resp_data_store(mailimap * session, + struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data) +{ + if (cont_req_or_resp_data->rsp_type == MAILIMAP_RESP_RESP_DATA) { + struct mailimap_response_data * resp_data; + + resp_data = cont_req_or_resp_data->rsp_data.rsp_resp_data; + + switch (resp_data->rsp_type) { + case MAILIMAP_RESP_DATA_TYPE_COND_STATE: + resp_cond_state_store(session, resp_data->rsp_data.rsp_cond_state); + break; + case MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA: + mailbox_data_store(session, resp_data->rsp_data.rsp_mailbox_data); + break; + case MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA: + message_data_store(session, resp_data->rsp_data.rsp_message_data); + break; + case MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA: + if (session->imap_connection_info) { + if (session->imap_connection_info->imap_capability != NULL) + mailimap_capability_data_free(session->imap_connection_info->imap_capability); + session->imap_connection_info->imap_capability = resp_data->rsp_data.rsp_capability_data; + resp_data->rsp_data.rsp_capability_data = NULL; + } + break; + case MAILIMAP_RESP_DATA_TYPE_EXTENSION_DATA: + mailimap_extension_data_store(session, &(resp_data->rsp_data.rsp_extension_data)); + break; + } + } +} + +static void response_tagged_store(mailimap * session, + struct mailimap_response_tagged * tagged) +{ + resp_cond_state_store(session, tagged->rsp_cond_state); +} + +static void resp_cond_bye_store(mailimap * session, + struct mailimap_resp_cond_bye * resp_cond_bye) +{ + resp_text_store(session, resp_cond_bye->rsp_text); +} + +static void response_fatal_store(mailimap * session, + struct mailimap_response_fatal * fatal) +{ + resp_cond_bye_store(session, fatal->rsp_bye); +} + +static void response_done_store(mailimap * session, + struct mailimap_response_done * resp_done) +{ + switch(resp_done->rsp_type) { + case MAILIMAP_RESP_DONE_TYPE_TAGGED: + response_tagged_store(session, resp_done->rsp_data.rsp_tagged); + break; + case MAILIMAP_RESP_DONE_TYPE_FATAL: + response_fatal_store(session, resp_done->rsp_data.rsp_fatal); + break; + } +} + +static void +response_store(mailimap * session, + struct mailimap_response * response) +{ + clistiter * cur; + + if (session->imap_response_info) { + mailimap_response_info_free(session->imap_response_info); + session->imap_response_info = NULL; + } + + session->imap_response_info = mailimap_response_info_new(); + if (session->imap_response_info == NULL) { + /* ignored error */ + return; + } + + if (response->rsp_cont_req_or_resp_data_list != NULL) { + for(cur = clist_begin(response->rsp_cont_req_or_resp_data_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data; + + cont_req_or_resp_data = clist_content(cur); + + cont_req_or_resp_data_store(session, cont_req_or_resp_data); + } + } + + response_done_store(session, response->rsp_resp_done); +} + +static void resp_cond_auth_store(mailimap * session, + struct mailimap_resp_cond_auth * cond_auth) +{ + resp_text_store(session, cond_auth->rsp_text); +} + +static void greeting_store(mailimap * session, + struct mailimap_greeting * greeting) +{ + switch (greeting->gr_type) { + case MAILIMAP_GREETING_RESP_COND_AUTH: + resp_cond_auth_store(session, greeting->gr_data.gr_auth); + break; + + case MAILIMAP_GREETING_RESP_COND_BYE: + resp_cond_bye_store(session, greeting->gr_data.gr_bye); + break; + } +} + +LIBETPAN_EXPORT +int mailimap_connect(mailimap * session, mailstream * s) +{ + struct mailimap_greeting * greeting; + int r; + int auth_type; + struct mailimap_connection_info * connection_info; + + if (session->imap_state != MAILIMAP_STATE_DISCONNECTED) + return MAILIMAP_ERROR_BAD_STATE; + + session->imap_stream = s; + mailstream_set_logger(s, imap_logger, session); + + if (session->imap_connection_info) + mailimap_connection_info_free(session->imap_connection_info); + connection_info = mailimap_connection_info_new(); + if (connection_info != NULL) + session->imap_connection_info = connection_info; + + if (mailimap_read_line(session) == NULL) { + return MAILIMAP_ERROR_STREAM; + } + + r = parse_greeting(session, &greeting); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + auth_type = greeting->gr_data.gr_auth->rsp_type; + + mailimap_greeting_free(greeting); + + switch (auth_type) { + case MAILIMAP_RESP_COND_AUTH_PREAUTH: + session->imap_state = MAILIMAP_STATE_AUTHENTICATED; + return MAILIMAP_NO_ERROR_AUTHENTICATED; + default: + session->imap_state = MAILIMAP_STATE_NON_AUTHENTICATED; + return MAILIMAP_NO_ERROR_NON_AUTHENTICATED; + } +} + + + + + + + + +/* ********************************************************************** */ + + + +LIBETPAN_EXPORT +int mailimap_append(mailimap * session, const char * mailbox, + struct mailimap_flag_list * flag_list, + struct mailimap_date_time * date_time, + const char * literal, size_t literal_size) +{ + struct mailimap_response * response; + int r; + int error_code; + struct mailimap_continue_req * cont_req; + size_t indx; + size_t fixed_literal_size; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + fixed_literal_size = mailstream_get_data_crlf_size(literal, literal_size); + + r = mailimap_append_send(session->imap_stream, mailbox, flag_list, date_time, + fixed_literal_size); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + indx = 0; + + r = mailimap_continue_req_parse(session->imap_stream, + session->imap_stream_buffer, NULL, + &indx, &cont_req, + session->imap_progr_rate, session->imap_progr_fun); + if (r == MAILIMAP_NO_ERROR) + mailimap_continue_req_free(cont_req); + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + mailimap_response_free(response); + + return MAILIMAP_ERROR_APPEND; + } + + if (session->imap_body_progress_fun != NULL) { + r = mailimap_literal_data_send_with_context(session->imap_stream, literal, literal_size, + session->imap_body_progress_fun, + session->imap_progress_context); + } + else { + r = mailimap_literal_data_send(session->imap_stream, literal, literal_size, + session->imap_progr_rate, session->imap_progr_fun); + } + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_APPEND; + } +} + +LIBETPAN_EXPORT +int mailimap_noop(mailimap * session) +{ + struct mailimap_response * response; + int r; + int error_code; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_noop_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_NOOP; + } +} + +LIBETPAN_EXPORT +int mailimap_logout(mailimap * session) +{ + struct mailimap_response * response; + int r; + int error_code; + int res; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto close; + } + + r = mailimap_logout_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto close; + } + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto close; + } + + if (mailstream_flush(session->imap_stream) == -1) { + res = MAILIMAP_ERROR_STREAM; + goto close; + } + + if (mailimap_read_line(session) == NULL) { + res = MAILIMAP_ERROR_STREAM; + goto close; + } + + r = mailimap_parse_response(session, &response); + if (r == MAILIMAP_ERROR_STREAM) { + // the response is expected to be MAILIMAP_ERROR_STREAM + // because the server responds with BYE so the stream + // is immediately closed + res = MAILIMAP_NO_ERROR; + goto close; + } else if (r != MAILIMAP_NO_ERROR) { + res = r; + goto close; + } + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + if (session->imap_connection_info) { + mailimap_connection_info_free(session->imap_connection_info); + session->imap_connection_info = NULL; + } + res = MAILIMAP_NO_ERROR; + goto close; + + default: + res = MAILIMAP_ERROR_LOGOUT; + goto close; + } + + close: + mailstream_close(session->imap_stream); + session->imap_stream = NULL; + session->imap_state = MAILIMAP_STATE_DISCONNECTED; + return res; +} + +/* send the results back to the caller */ +/* duplicate the result */ + +static struct mailimap_capability * +mailimap_capability_dup(struct mailimap_capability * orig_cap) +{ + struct mailimap_capability * cap; + char * auth_type; + char * name; + + name = NULL; + auth_type = NULL; + switch (orig_cap->cap_type) { + case MAILIMAP_CAPABILITY_NAME: + name = strdup(orig_cap->cap_data.cap_name); + if (name == NULL) + goto err; + break; + case MAILIMAP_CAPABILITY_AUTH_TYPE: + auth_type = strdup(orig_cap->cap_data.cap_auth_type); + if (auth_type == NULL) + goto err; + break; + } + + cap = mailimap_capability_new(orig_cap->cap_type, auth_type, name); + if (cap == NULL) + goto free; + + return cap; + + free: + if (name != NULL) + free(name); + if (auth_type != NULL) + free(auth_type); + err: + return NULL; +} + +static struct mailimap_capability_data * +mailimap_capability_data_dup(struct mailimap_capability_data * orig_cap_data) +{ + struct mailimap_capability_data * cap_data; + struct mailimap_capability * cap_dup; + clist * list; + clistiter * cur; + int r; + + list = clist_new(); + if (list == NULL) + goto err; + + for(cur = clist_begin(orig_cap_data->cap_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailimap_capability * cap; + + cap = clist_content(cur); + + cap_dup = mailimap_capability_dup(cap); + if (cap_dup == NULL) + goto list; + + r = clist_append(list, cap_dup); + if (r < 0) { + mailimap_capability_free(cap_dup); + goto list; + } + } + + cap_data = mailimap_capability_data_new(list); + if (cap_data == NULL) + goto list; + + return cap_data; + +list: + clist_foreach(list, (clist_func) mailimap_capability_free, NULL); + clist_free(list); +err: + return NULL; +} + +LIBETPAN_EXPORT +int mailimap_capability(mailimap * session, + struct mailimap_capability_data ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + struct mailimap_capability_data * cap_data; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_capability_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + cap_data = + mailimap_capability_data_dup(session->imap_connection_info->imap_capability); + if (cap_data == NULL) + return MAILIMAP_ERROR_MEMORY; + + * result = cap_data; + + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_CAPABILITY; + } +} + +LIBETPAN_EXPORT +int mailimap_check(mailimap * session) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_check_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_CHECK; + } +} + +LIBETPAN_EXPORT +int mailimap_close(mailimap * session) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_close_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + /* leave selected state */ + mailimap_selection_info_free(session->imap_selection_info); + session->imap_selection_info = NULL; + + session->imap_state = MAILIMAP_STATE_AUTHENTICATED; + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_CLOSE; + } +} + +LIBETPAN_EXPORT +int mailimap_expunge(mailimap * session) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_expunge_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_EXPUNGE; + } +} + +LIBETPAN_EXPORT +int mailimap_copy(mailimap * session, struct mailimap_set * set, + const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_copy_send(session->imap_stream, set, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_COPY; + } +} + +LIBETPAN_EXPORT +int mailimap_uid_copy(mailimap * session, struct mailimap_set * set, + const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uid_copy_send(session->imap_stream, set, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_UID_COPY; + } +} + +LIBETPAN_EXPORT +int mailimap_move(mailimap * session, struct mailimap_set * set, + const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_move_send(session->imap_stream, set, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_MOVE; + } +} + +LIBETPAN_EXPORT +int mailimap_uid_move(mailimap * session, struct mailimap_set * set, + const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uid_move_send(session->imap_stream, set, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_UID_MOVE; + } +} + +LIBETPAN_EXPORT +int mailimap_create(mailimap * session, const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_create_send(session->imap_stream, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_CREATE; + } +} + + +LIBETPAN_EXPORT +int mailimap_delete(mailimap * session, const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_delete_send(session->imap_stream, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_DELETE; + } +} + +#if 0 +LIBETPAN_EXPORT +int mailimap_examine(mailimap * session, const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_examine_send(session->imap_stream, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + if (session->imap_selection_info != NULL) + mailimap_selection_info_free(session->imap_selection_info); + session->imap_selection_info = mailimap_selection_info_new(); + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + session->imap_state = MAILIMAP_STATE_SELECTED; + return MAILIMAP_NO_ERROR; + + default: + mailimap_selection_info_free(session->imap_selection_info); + session->imap_selection_info = NULL; + session->imap_state = MAILIMAP_STATE_AUTHENTICATED; + return MAILIMAP_ERROR_EXAMINE; + } +} +#else +LIBETPAN_EXPORT +int mailimap_examine(mailimap * session, const char * mb) +{ + uint64_t dummy; + return mailimap_examine_condstore_optional(session, mb, 0, &dummy); +} +#endif + +LIBETPAN_EXPORT +int +mailimap_fetch(mailimap * session, struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, clist ** result) +{ +#if 0 + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_fetch_send(session->imap_stream, set, fetch_type); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = session->imap_response_info->rsp_fetch_list; + session->imap_response_info->rsp_fetch_list = NULL; + + if (clist_count(* result) == 0) { + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + } + else { + error_code = MAILIMAP_RESP_COND_STATE_OK; + } + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + mailimap_fetch_list_free(* result); + return MAILIMAP_ERROR_FETCH; + } +#else + return mailimap_fetch_changedsince(session, set, fetch_type, 0, result); +#endif +} + +LIBETPAN_EXPORT +void mailimap_fetch_list_free(clist * fetch_list) +{ + clist_foreach(fetch_list, (clist_func) mailimap_msg_att_free, NULL); + clist_free(fetch_list); +} + +LIBETPAN_EXPORT +int +mailimap_uid_fetch(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, clist ** result) +{ +#if 0 + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uid_fetch_send(session->imap_stream, set, fetch_type); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + * result = session->imap_response_info->rsp_fetch_list; + session->imap_response_info->rsp_fetch_list = NULL; + + if (clist_count(* result) == 0) { + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + } + else { + error_code = MAILIMAP_RESP_COND_STATE_OK; + } + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + mailimap_fetch_list_free(* result); + * result = NULL; + return MAILIMAP_ERROR_UID_FETCH; + } +#else + return mailimap_uid_fetch_changedsince(session, set, fetch_type, 0, result); +#endif +} + +LIBETPAN_EXPORT +int mailimap_list(mailimap * session, const char * mb, + const char * list_mb, clist ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_list_send(session->imap_stream, mb, list_mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = session->imap_response_info->rsp_mailbox_list; + session->imap_response_info->rsp_mailbox_list = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_LIST; + } +} + +LIBETPAN_EXPORT +int mailimap_login(mailimap * session, + const char * userid, const char * password) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_NON_AUTHENTICATED) + return MAILIMAP_ERROR_BAD_STATE; + + mailstream_set_privacy(session->imap_stream, 0); + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) { + mailstream_set_privacy(session->imap_stream, 1); + return r; + } + + r = mailimap_login_send(session->imap_stream, userid, password); + if (r != MAILIMAP_NO_ERROR) { + mailstream_set_privacy(session->imap_stream, 1); + return r; + } + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) { + mailstream_set_privacy(session->imap_stream, 1); + return r; + } + + if (mailstream_flush(session->imap_stream) == -1) { + mailstream_set_privacy(session->imap_stream, 1); + return MAILIMAP_ERROR_STREAM; + } + mailstream_set_privacy(session->imap_stream, 1); + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + session->imap_state = MAILIMAP_STATE_AUTHENTICATED; + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_LOGIN; + } +} + +#ifdef USE_SASL +static int sasl_getsimple(void * context, int id, + const char ** result, unsigned * len) +{ + mailimap * session; + + session = context; + + switch (id) { + case SASL_CB_USER: + if (result != NULL) + * result = session->imap_sasl.sasl_login; + if (len != NULL) + * len = (unsigned) strlen(session->imap_sasl.sasl_login); + return SASL_OK; + + case SASL_CB_AUTHNAME: + if (result != NULL) + * result = session->imap_sasl.sasl_auth_name; + if (len != NULL) + * len = (unsigned) strlen(session->imap_sasl.sasl_auth_name); + return SASL_OK; + } + + return SASL_FAIL; +} + +static int sasl_getsecret(sasl_conn_t * conn, void * context, int id, + sasl_secret_t ** psecret) +{ + mailimap * session; + + session = context; + + switch (id) { + case SASL_CB_PASS: + if (psecret != NULL) + * psecret = session->imap_sasl.sasl_secret; + return SASL_OK; + } + + return SASL_FAIL; +} + +static int sasl_getrealm(void * context, int id, + const char ** availrealms, + const char ** result) +{ + mailimap * session; + + session = context; + + switch (id) { + case SASL_CB_GETREALM: + if (result != NULL) + * result = session->imap_sasl.sasl_realm; + return SASL_OK; + } + + return SASL_FAIL; +} +#endif + +LIBETPAN_EXPORT +int mailimap_authenticate(mailimap * session, const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm) +{ +#ifdef USE_SASL + struct mailimap_response * response; + int r; + int error_code; + size_t indx; + sasl_callback_t sasl_callback[5]; + const char * sasl_out; + unsigned sasl_out_len; + const char * mechusing; + sasl_secret_t * secret; + int res; + size_t len; + + if (session->imap_state != MAILIMAP_STATE_NON_AUTHENTICATED) { + res = MAILIMAP_ERROR_BAD_STATE; + goto err; + } + + sasl_callback[0].id = SASL_CB_GETREALM; + sasl_callback[0].proc = (int(*)(void)) sasl_getrealm; + sasl_callback[0].context = session; + sasl_callback[1].id = SASL_CB_USER; + sasl_callback[1].proc = (int(*)(void)) sasl_getsimple; + sasl_callback[1].context = session; + sasl_callback[2].id = SASL_CB_AUTHNAME; + sasl_callback[2].proc = (int(*)(void)) sasl_getsimple; + sasl_callback[2].context = session; + sasl_callback[3].id = SASL_CB_PASS; + sasl_callback[3].proc = (int(*)(void)) sasl_getsecret; + sasl_callback[3].context = session; + sasl_callback[4].id = SASL_CB_LIST_END; + sasl_callback[4].proc = NULL; + sasl_callback[4].context = NULL; + + len = strlen(password); + secret = malloc(sizeof(* secret) + len); + if (secret == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto err; + } + secret->len = len; + memcpy(secret->data, password, len + 1); + + session->imap_sasl.sasl_server_fqdn = server_fqdn; + session->imap_sasl.sasl_login = login; + session->imap_sasl.sasl_auth_name = auth_name; + session->imap_sasl.sasl_password = password; + session->imap_sasl.sasl_realm = realm; + session->imap_sasl.sasl_secret = secret; + + /* init SASL */ + if (session->imap_sasl.sasl_conn != NULL) { + sasl_dispose((sasl_conn_t **) &session->imap_sasl.sasl_conn); + session->imap_sasl.sasl_conn = NULL; + } + else { + mailsasl_ref(); + } + + r = sasl_client_new("imap", server_fqdn, + local_ip_port, remote_ip_port, sasl_callback, 0, + (sasl_conn_t **) &session->imap_sasl.sasl_conn); + if (r != SASL_OK) { + res = MAILIMAP_ERROR_LOGIN; + goto free_secret; + } + + r = sasl_client_start(session->imap_sasl.sasl_conn, + auth_type, NULL, &sasl_out, &sasl_out_len, &mechusing); + if ((r != SASL_CONTINUE) && (r != SASL_OK)) { + res = MAILIMAP_ERROR_LOGIN; + goto free_sasl_conn; + } + + mailstream_set_privacy(session->imap_stream, 0); + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_sasl_conn; + } + + r = mailimap_authenticate_send(session->imap_stream, auth_type); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_sasl_conn; + } + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_sasl_conn; + } + + if (mailstream_flush(session->imap_stream) == -1) { + res = MAILIMAP_ERROR_STREAM; + goto free_sasl_conn; + } + + while (1) { + struct mailimap_continue_req * cont_req; + char * response_base64; + int got_response; + char * encoded; + unsigned int encoded_len; + unsigned int max_encoded; + + if (mailimap_read_line(session) == NULL) { + res = MAILIMAP_ERROR_STREAM; + goto free_sasl_conn; + } + + indx = 0; + + r = mailimap_continue_req_parse(session->imap_stream, + session->imap_stream_buffer, NULL, + &indx, &cont_req, + session->imap_progr_rate, session->imap_progr_fun); + if (r != MAILIMAP_NO_ERROR) + break; + + got_response = 1; + if (cont_req->cr_type == MAILIMAP_CONTINUE_REQ_BASE64) { + response_base64 = cont_req->cr_data.cr_base64; + if (* response_base64 == '\0') + got_response = 0; + } + else { + response_base64 = ""; + got_response = 0; + } + + if (got_response) { + unsigned int response_len; + char * decoded; + unsigned int decoded_len; + unsigned int max_decoded; + + response_len = (unsigned int) strlen(response_base64); + max_decoded = response_len * 3 / 4; + decoded = malloc(max_decoded + 1); + if (decoded == NULL) { + mailimap_continue_req_free(cont_req); + res = MAILIMAP_ERROR_MEMORY; + goto free_sasl_conn; + } + + r = sasl_decode64(response_base64, response_len, + decoded, max_decoded + 1, &decoded_len); + + mailimap_continue_req_free(cont_req); + + if (r != SASL_OK) { + free(decoded); + res = MAILIMAP_ERROR_MEMORY; + goto free_sasl_conn; + } + + r = sasl_client_step(session->imap_sasl.sasl_conn, + decoded, decoded_len, NULL, &sasl_out, &sasl_out_len); + + free(decoded); + + if ((r != SASL_CONTINUE) && (r != SASL_OK)) { + res = MAILIMAP_ERROR_LOGIN; + goto free_sasl_conn; + } + } + else { + mailimap_continue_req_free(cont_req); + } + + max_encoded = ((sasl_out_len + 2) / 3) * 4; + encoded = malloc(max_encoded + 1); + if (encoded == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_sasl_conn; + } + + r = sasl_encode64(sasl_out, sasl_out_len, + encoded, max_encoded + 1, &encoded_len); + if (r != SASL_OK) { + free(encoded); + res = MAILIMAP_ERROR_MEMORY; + goto free_sasl_conn; + } + + r = mailimap_token_send(session->imap_stream, encoded); + + free(encoded); + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_sasl_conn; + } + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_sasl_conn; + } + + if (mailstream_flush(session->imap_stream) == -1) { + res = MAILIMAP_ERROR_STREAM; + goto free_sasl_conn; + } + } + + free(session->imap_sasl.sasl_secret); + session->imap_sasl.sasl_secret = NULL; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_sasl_conn; + } + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + session->imap_state = MAILIMAP_STATE_AUTHENTICATED; + res = MAILIMAP_NO_ERROR; + goto free_sasl_conn; + + default: + res = MAILIMAP_ERROR_LOGIN; + goto free_sasl_conn; + } + + free_sasl_conn: + mailstream_set_privacy(session->imap_stream, 1); + sasl_dispose((sasl_conn_t **) &session->imap_sasl.sasl_conn); + session->imap_sasl.sasl_conn = NULL; + mailsasl_unref(); + free_secret: + free(session->imap_sasl.sasl_secret); + session->imap_sasl.sasl_secret = NULL; + err: + return res; +#else + return MAILIMAP_ERROR_LOGIN; +#endif +} + +LIBETPAN_EXPORT +int mailimap_lsub(mailimap * session, const char * mb, + const char * list_mb, clist ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_lsub_send(session->imap_stream, mb, list_mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = session->imap_response_info->rsp_mailbox_lsub; + session->imap_response_info->rsp_mailbox_lsub = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_LSUB; + } +} + +LIBETPAN_EXPORT +void mailimap_list_result_free(clist * list) +{ + clist_foreach(list, (clist_func) mailimap_mailbox_list_free, NULL); + clist_free(list); +} + +LIBETPAN_EXPORT +int mailimap_rename(mailimap * session, + const char * mb, const char * new_name) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_rename_send(session->imap_stream, mb, new_name); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_RENAME; + } +} + +LIBETPAN_EXPORT +int +mailimap_search(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result) +{ + return mailimap_search_modseq(session, charset, key, result, NULL); +} + +LIBETPAN_EXPORT +int +mailimap_uid_search(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result) +{ + return mailimap_uid_search_modseq(session, charset, key, result, NULL); +} + +LIBETPAN_EXPORT int mailimap_search_literalplus(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result) +{ + return mailimap_search_literalplus_modseq(session, charset, key, result, NULL); +} + +LIBETPAN_EXPORT int mailimap_uid_search_literalplus(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result) +{ + return mailimap_uid_search_literalplus_modseq(session, charset, key, result, NULL); +} + +LIBETPAN_EXPORT +void mailimap_search_result_free(clist * search_result) +{ + clist_foreach(search_result, (clist_func) free, NULL); + clist_free(search_result); +} + +LIBETPAN_EXPORT +int +mailimap_select(mailimap * session, const char * mb) +{ + uint64_t dummy; + return mailimap_select_condstore_optional(session, mb, 0, &dummy); +} + +LIBETPAN_EXPORT +int +mailimap_custom_command(mailimap * session, const char * command) +{ + int r; + int error_code; + struct mailimap_response * response; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_send_custom_command(session->imap_stream, command); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_CUSTOM_COMMAND; + } +} + +LIBETPAN_EXPORT +int +mailimap_status(mailimap * session, const char * mb, + struct mailimap_status_att_list * status_att_list, + struct mailimap_mailbox_data_status ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_status_send(session->imap_stream, mb, status_att_list); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = session->imap_response_info->rsp_status; + session->imap_response_info->rsp_status = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_STATUS; + } +} + + +LIBETPAN_EXPORT +int +mailimap_store(mailimap * session, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags) +{ +#if 0 + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_store_send(session->imap_stream, set, store_att_flags); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_STORE; + } +#else + return mailimap_store_unchangedsince_optional(session, + set, 0, 0, store_att_flags); +#endif +} + +LIBETPAN_EXPORT +int +mailimap_uid_store(mailimap * session, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags) +{ +#if 0 + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uid_store_send(session->imap_stream, set, store_att_flags); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_UID_STORE; + } +#else + return mailimap_uid_store_unchangedsince_optional(session, + set, 0, 0, store_att_flags); +#endif +} + +LIBETPAN_EXPORT +int mailimap_subscribe(mailimap * session, const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_subscribe_send(session->imap_stream, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_SUBSCRIBE; + } +} + +LIBETPAN_EXPORT +int mailimap_unsubscribe(mailimap * session, const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_unsubscribe_send(session->imap_stream, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_UNSUBSCRIBE; + } +} + + +LIBETPAN_EXPORT +int mailimap_starttls(mailimap * session) +{ + struct mailimap_response * response; + int r; + int error_code; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_starttls_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + // Detect if the server send extra data after the STARTTLS response. + // This *may* be a "response injection attack". + if (session->imap_stream->read_buffer_len != 0) { + // Since it is also an IMAP protocol violation, exit. + return MAILIMAP_ERROR_STARTTLS; + } + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_STARTTLS; + } +} + + + +char * mailimap_read_line(mailimap * session) +{ + return mailstream_read_line(session->imap_stream, session->imap_stream_buffer); +} + +int mailimap_send_current_tag(mailimap * session) +{ + char tag_str[15]; + int r; + + session->imap_tag ++; + + if(mailimap_is_163_workaround_enabled(session)) + snprintf(tag_str, 15, "C%i", session->imap_tag); + else + snprintf(tag_str, 15, "%i", session->imap_tag); + + + r = mailimap_tag_send(session->imap_stream, tag_str); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_parse_response(mailimap * session, + struct mailimap_response ** result) +{ + size_t indx; + struct mailimap_response * response; + struct mailimap_parser_context * parser_ctx; + char tag_str[15]; + int r; + + indx = 0; + + session->imap_response = NULL; + + if (session->imap_stream_buffer->allocated_len > 128 * 1024) { + MMAPString * buffer; + + buffer = mmap_string_new_len(session->imap_stream_buffer->str, session->imap_stream_buffer->len); + mmap_string_free(session->imap_stream_buffer); + session->imap_stream_buffer = buffer; + } + + parser_ctx = mailimap_parser_context_new(session); + if (parser_ctx == NULL) + return MAILIMAP_ERROR_MEMORY; + + if ((session->imap_body_progress_fun != NULL) || + (session->imap_items_progress_fun != NULL)) { + r = mailimap_response_parse_with_context(session->imap_stream, + session->imap_stream_buffer, + parser_ctx, + &indx, &response, + session->imap_body_progress_fun, + session->imap_items_progress_fun, + session->imap_progress_context, + session->imap_msg_att_handler, + session->imap_msg_att_handler_context); + } + else { + r = mailimap_response_parse(session->imap_stream, + session->imap_stream_buffer, + parser_ctx, + &indx, &response, + session->imap_progr_rate, session->imap_progr_fun); + } + + mailimap_parser_context_free(parser_ctx); + + if (r != MAILIMAP_NO_ERROR) + return r; + +#if 0 + mailimap_response_print(response); +#endif + + response_store(session, response); + + if (response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_text->rsp_text != NULL) { + if (mmap_string_assign(session->imap_response_buffer, + response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_text->rsp_text) + == NULL) { + mailimap_response_free(response); + return MAILIMAP_ERROR_MEMORY; + } + } + + session->imap_response = session->imap_response_buffer->str; + + if (response->rsp_resp_done->rsp_type == MAILIMAP_RESP_DONE_TYPE_FATAL) { + mailimap_response_free(response); + return MAILIMAP_ERROR_FATAL; + } + + if(mailimap_is_163_workaround_enabled(session)) + snprintf(tag_str, 15, "C%i", session->imap_tag); + else + snprintf(tag_str, 15, "%i", session->imap_tag); + + if (strcmp(response->rsp_resp_done->rsp_data.rsp_tagged->rsp_tag, tag_str) != 0) { + mailimap_response_free(response); + return MAILIMAP_ERROR_PROTOCOL; + } + + if (response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type == + MAILIMAP_RESP_COND_STATE_BAD) { + mailimap_response_free(response); + return MAILIMAP_ERROR_PROTOCOL; + } + + * result = response; + + return MAILIMAP_NO_ERROR; +} + + +static int parse_greeting(mailimap * session, + struct mailimap_greeting ** result) +{ + size_t indx; + struct mailimap_greeting * greeting; + int r; + + indx = 0; + + session->imap_response = NULL; + + r = mailimap_greeting_parse(session->imap_stream, + session->imap_stream_buffer, NULL, + &indx, &greeting, session->imap_progr_rate, + session->imap_progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + +#if 0 + mailimap_greeting_print(greeting); +#endif + + greeting_store(session, greeting); + + if (greeting->gr_type == MAILIMAP_GREETING_RESP_COND_BYE) { + if (greeting->gr_data.gr_bye->rsp_text->rsp_text != NULL) { + if (mmap_string_assign(session->imap_response_buffer, + greeting->gr_data.gr_bye->rsp_text->rsp_text) == NULL) + return MAILIMAP_ERROR_MEMORY; + } + + session->imap_response = session->imap_response_buffer->str; + + return MAILIMAP_ERROR_DONT_ACCEPT_CONNECTION; + } + + if (greeting->gr_data.gr_auth->rsp_text->rsp_text != NULL) { + if (mmap_string_assign(session->imap_response_buffer, + greeting->gr_data.gr_auth->rsp_text->rsp_text) == NULL) + return MAILIMAP_ERROR_MEMORY; + } + + session->imap_response = session->imap_response_buffer->str; + + * result = greeting; + + return MAILIMAP_NO_ERROR; +} + + +LIBETPAN_EXPORT +mailimap * mailimap_new(size_t imap_progr_rate, + progress_function * imap_progr_fun) +{ + mailimap * f; + + f = malloc(sizeof(* f)); + if (f == NULL) + goto err; + + f->imap_response = NULL; + + f->imap_stream = NULL; + + f->imap_progr_rate = imap_progr_rate; + f->imap_progr_fun = imap_progr_fun; + + f->imap_stream_buffer = mmap_string_new(""); + if (f->imap_stream_buffer == NULL) + goto free_f; + + f->imap_response_buffer = mmap_string_new(""); + if (f->imap_response_buffer == NULL) + goto free_stream_buffer; + + f->imap_state = MAILIMAP_STATE_DISCONNECTED; + f->imap_tag = 0; + + f->imap_selection_info = NULL; + f->imap_response_info = NULL; + f->imap_connection_info = NULL; + +#ifdef USE_SASL + f->imap_sasl.sasl_conn = NULL; +#endif + + f->imap_idle_timestamp = 0; + f->imap_idle_maxdelay = 29 * 60; /* IMAP IDLE spec */ + + f->imap_body_progress_fun = NULL; + f->imap_items_progress_fun = NULL; + f->imap_progress_context = NULL; + + f->imap_msg_att_handler = NULL; + f->imap_msg_att_handler_context = NULL; + + f->imap_msg_body_handler = NULL; + f->imap_msg_body_handler_context = NULL; + + f->imap_timeout = 0; + + f->imap_logger = NULL; + f->imap_logger_context = NULL; + f->is_163_workaround_enabled = 0; + f->is_rambler_workaround_enabled = 0; + f->is_qip_workaround_enabled = 0; + return f; + + free_stream_buffer: + mmap_string_free(f->imap_stream_buffer); + free_f: + free(f); + err: + return NULL; +} + +LIBETPAN_EXPORT +void mailimap_free(mailimap * session) +{ +#ifdef USE_SASL + if (session->imap_sasl.sasl_conn != NULL) { + sasl_dispose((sasl_conn_t **) &session->imap_sasl.sasl_conn); + mailsasl_unref(); + } +#endif + + if (session->imap_stream) + mailimap_logout(session); + + mmap_string_free(session->imap_response_buffer); + mmap_string_free(session->imap_stream_buffer); + + if (session->imap_response_info) + mailimap_response_info_free(session->imap_response_info); + if (session->imap_selection_info) + mailimap_selection_info_free(session->imap_selection_info); + if (session->imap_connection_info) + mailimap_connection_info_free(session->imap_connection_info); + + free(session); +} + +LIBETPAN_EXPORT +void mailimap_set_timeout(mailimap * session, time_t timeout) +{ + session->imap_timeout = timeout; +} + +LIBETPAN_EXPORT +time_t mailimap_get_timeout(mailimap * session) +{ + return session->imap_timeout; +} + +LIBETPAN_EXPORT +void mailimap_set_progress_callback(mailimap * session, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context) +{ + session->imap_body_progress_fun = body_progr_fun; + session->imap_items_progress_fun = items_progr_fun; + session->imap_progress_context = context; +} + +LIBETPAN_EXPORT +void mailimap_set_msg_att_handler(mailimap * session, + mailimap_msg_att_handler * handler, + void * context) +{ + session->imap_msg_att_handler = handler; + session->imap_msg_att_handler_context = context; +} + +LIBETPAN_EXPORT +void mailimap_set_msg_body_handler(mailimap * session, + mailimap_msg_body_handler * handler, + void * context) +{ + session->imap_msg_body_handler = handler; + session->imap_msg_body_handler_context = context; +} + +static inline void imap_logger(mailstream * s, int log_type, + const char * str, size_t size, void * context) +{ + mailimap * session; + + session = context; + if (session->imap_logger == NULL) + return; + + session->imap_logger(session, log_type, str, size, session->imap_logger_context); +} + +LIBETPAN_EXPORT +void mailimap_set_logger(mailimap * session, void (* logger)(mailimap * session, int log_type, + const char * str, size_t size, void * context), void * logger_context) +{ + session->imap_logger = logger; + session->imap_logger_context = logger_context; +} + +LIBETPAN_EXPORT +void mailimap_set_163_workaround_enabled(mailimap * session, int enabled) { + session->is_163_workaround_enabled = enabled; +} + +LIBETPAN_EXPORT +int mailimap_is_163_workaround_enabled(mailimap * session) { + return session->is_163_workaround_enabled; +} + +LIBETPAN_EXPORT +void mailimap_set_rambler_workaround_enabled(mailimap * session, int enabled) { + if (session) + session->is_rambler_workaround_enabled = enabled; +} + +LIBETPAN_EXPORT +int mailimap_is_rambler_workaround_enabled(mailimap * session) { + return session->is_rambler_workaround_enabled; +} + +LIBETPAN_EXPORT +void mailimap_set_qip_workaround_enabled(mailimap * session, int enabled) { + if (session) { + session->is_qip_workaround_enabled = enabled; + } +} + +LIBETPAN_EXPORT +int mailimap_is_qip_workaround_enabled(mailimap * session) { + return session->is_qip_workaround_enabled; +} diff --git a/Sources/libetpan/low-level/imap/mailimap.h b/Sources/libetpan/low-level/imap/mailimap.h new file mode 100644 index 00000000..d654e54d --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap.h @@ -0,0 +1,935 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap.h,v 1.23 2011/03/29 23:59:05 hoa Exp $ + */ + +#ifndef MAILIMAP_H + +#define MAILIMAP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + mailimap_connect() + + This function will connect the IMAP session with the given stream. + + @param session the IMAP session + @param s stream to use + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + + note that on success, MAILIMAP_NO_ERROR_AUTHENTICATED or + MAILIMAP_NO_ERROR_NON_AUTHENTICATED is returned + + MAILIMAP_NO_ERROR_NON_AUTHENTICATED is returned when you need to + use mailimap_login() to authenticate, else + MAILIMAP_NO_ERROR_AUTHENTICATED is returned. +*/ + +LIBETPAN_EXPORT +int mailimap_connect(mailimap * session, mailstream * s); + +/* + mailimap_append() + + This function will append a given message to the given mailbox + by sending an APPEND command. + + @param session the IMAP session + @param mailbox name of the mailbox + @param flag_list flags of the message + @param date_time timestamp of the message + @param literal content of the message + @param literal_size size of the message + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_append(mailimap * session, const char * mailbox, + struct mailimap_flag_list * flag_list, + struct mailimap_date_time * date_time, + const char * literal, size_t literal_size); + +/* + mailimap_noop() + + This function will poll for an event on the server by + sending a NOOP command to the IMAP server + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR_XXX codes +*/ + +LIBETPAN_EXPORT +int mailimap_noop(mailimap * session); + +/* + mailimap_logout() + + This function will logout from an IMAP server by sending + a LOGOUT command. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_logout(mailimap * session); + +/* + mailimap_capability() + + This function will query an IMAP server for his capabilities + by sending a CAPABILITY command. + + @param session IMAP session + @param result The result of this command is a list of + capabilities and it is stored into (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +LIBETPAN_EXPORT +int mailimap_capability(mailimap * session, + struct mailimap_capability_data ** result); + +/* + mailimap_check() + + This function will request for a checkpoint of the mailbox by + sending a CHECK command. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +LIBETPAN_EXPORT +int mailimap_check(mailimap * session); + +/* + mailimap_close() + + This function will close the selected mailbox by sending + a CLOSE command. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +LIBETPAN_EXPORT +int mailimap_close(mailimap * session); + +/* + mailimap_expunge() + + This function will permanently remove from the selected mailbox + message that have the \Deleted flag set. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_expunge(mailimap * session); + +/* + mailimap_copy() + + This function will copy the given messages from the selected mailbox + to the given mailbox. + + @param session IMAP session + @param set This is a set of message numbers. + @param mb This is the destination mailbox. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +LIBETPAN_EXPORT +int mailimap_copy(mailimap * session, struct mailimap_set * set, + const char * mb); + +/* + mailimap_uid_copy() + + This function will copy the given messages from the selected mailbox + to the given mailbox. + + @param session IMAP session + @param set This is a set of message unique identifiers. + @param mb This is the destination mailbox. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +LIBETPAN_EXPORT +int mailimap_uid_copy(mailimap * session, + struct mailimap_set * set, const char * mb); + +/* + mailimap_move() + + This function will move the given messages from the selected mailbox + to the given mailbox. + + @param session IMAP session + @param set This is a set of message numbers. + @param mb This is the destination mailbox. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +LIBETPAN_EXPORT +int mailimap_move(mailimap * session, struct mailimap_set * set, + const char * mb); + +/* + mailimap_uid_move() + + This function will move the given messages from the selected mailbox + to the given mailbox. + + @param session IMAP session + @param set This is a set of message unique identifiers. + @param mb This is the destination mailbox. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +LIBETPAN_EXPORT +int mailimap_uid_move(mailimap * session, struct mailimap_set * set, + const char * mb); + +/* + mailimap_create() + + This function will create a mailbox. + + @param session IMAP session + @param mb This is the name of the mailbox to create. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_create(mailimap * session, const char * mb); + +/* + mailimap_delete() + + This function will delete a mailox. + + @param session IMAP session + @param mb This is the name of the mailbox to delete. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_delete(mailimap * session, const char * mb); + +/* + mailimap_examine() + + This function will select the mailbox for read-only operations. + + @param session IMAP session + @param mb This is the name of the mailbox to select. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_examine(mailimap * session, const char * mb); + +/* + mailimap_fetch() + + This function will retrieve data associated with the given message + numbers. + + @param session IMAP session + @param set set of message numbers + @param fetch_type type of information to be retrieved + @param result The result of this command is a clist + and it is stored into (* result). Each element of the clist is a + (struct mailimap_msg_att *). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int +mailimap_fetch(mailimap * session, struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, clist ** result); + +/* + mailimap_uid_fetch() + + This function will retrieve data associated with the given message + numbers. + + @param session IMAP session + @param set set of message unique identifiers + @param fetch_type type of information to be retrieved + @param result The result of this command is a clist + and it is stored into (* result). Each element of the clist is a + (struct mailimap_msg_att *). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int +mailimap_uid_fetch(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, clist ** result); + +/* + mailimap_fetch_list_free() + + This function will free the result of a fetch command. + + @param fetch_list This is the clist containing + (struct mailimap_msg_att *) elements to free. +*/ + +LIBETPAN_EXPORT +void mailimap_fetch_list_free(clist * fetch_list); + +/* + mailimap_list() + + This function will return the list of the mailbox + available on the server. + + @param session IMAP session + @param mb This is the reference name that informs + of the level of hierarchy + @param list_mb mailbox name with possible wildcard + @param result This will store a clist of (struct mailimap_mailbox_list *) + in (* result) + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_list(mailimap * session, const char * mb, + const char * list_mb, clist ** result); + +/* + mailimap_login() + + This function will authenticate the client. + + @param session IMAP session + @param userid login of the user + @param password password of the user + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_login(mailimap * session, + const char * userid, const char * password); + +/* + mailimap_authenticate() + + This function will authenticate the client. + TODO : documentation +*/ + +LIBETPAN_EXPORT +int mailimap_authenticate(mailimap * session, const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); + +/* + mailimap_lsub() + + This function will return the list of the mailbox + that the client has subscribed to. + + @param session IMAP session + @param mb This is the reference name that informs + of the level of hierarchy + @param list_mb mailbox name with possible wildcard + @param result This will store a list of (struct mailimap_mailbox_list *) + in (* result) + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_lsub(mailimap * session, const char * mb, + const char * list_mb, clist ** result); + +/* + mailimap_list_result_free() + + This function will free the clist of (struct mailimap_mailbox_list *) + + @param list This is the clist to free. +*/ + +LIBETPAN_EXPORT +void mailimap_list_result_free(clist * list); + +/* + mailimap_rename() + + This function will change the name of a mailbox. + + @param session IMAP session + @param mb current name + @param new_name new name + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_rename(mailimap * session, + const char * mb, const char * new_name); + +/* + mailimap_search() + + All mails that match the given criteria will be returned + their numbers in the result list. + + @param session IMAP session + @param charset This indicates the charset of the strings that appears + in the searching criteria + @param key This is the searching criteria + @param result The result is a clist of (uint32_t *) and will be + stored in (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int +mailimap_search(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result); + +/* + mailimap_uid_search() + + + All mails that match the given criteria will be returned + their unique identifiers in the result list. + + @param session IMAP session + @param charset This indicates the charset of the strings that appears + in the searching criteria + @param key This is the searching criteria + @param result The result is a clist of (uint32_t *) and will be + stored in (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int +mailimap_uid_search(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result); + +/* + mailimap_search_literalplus() + + All mails that match the given criteria will be returned + their numbers in the result list. + LITERAL+ feature will be used to send strings. + + @param session IMAP session + @param charset This indicates the charset of the strings that appears + in the searching criteria + @param key This is the searching criteria + @param result The result is a clist of (uint32_t *) and will be + stored in (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT int mailimap_search_literalplus(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result); + +/* + mailimap_uid_search_literalplus() + + All mails that match the given criteria will be returned + their numbers in the result list. + LITERAL+ feature will be used to send strings. + + @param session IMAP session + @param charset This indicates the charset of the strings that appears + in the searching criteria + @param key This is the searching criteria + @param result The result is a clist of (uint32_t *) and will be + stored in (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT int mailimap_uid_search_literalplus(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result); + +/* + mailimap_search_result_free() + + This function will free the result of the a search. + + @param search_result This is a clist of (uint32_t *) returned + by mailimap_uid_search() or mailimap_search() +*/ + +LIBETPAN_EXPORT +void mailimap_search_result_free(clist * search_result); + +/* + mailimap_select() + + This function will select a given mailbox so that messages in the + mailbox can be accessed. + + @param session IMAP session + @param mb This is the name of the mailbox to select. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int +mailimap_select(mailimap * session, const char * mb); + +/* + mailimap_custom_command() + + @param session IMAP session + @param command Custom IMAP command to be send + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR_XXX codes + */ + +LIBETPAN_EXPORT +int mailimap_custom_command(mailimap * session, const char * command); + +/* + mailimap_status() + + This function will return informations about a given mailbox. + + @param session IMAP session + @param mb This is the name of the mailbox + @param status_att_list This is the list of mailbox information to return + @param result List of returned values + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int +mailimap_status(mailimap * session, const char * mb, + struct mailimap_status_att_list * status_att_list, + struct mailimap_mailbox_data_status ** result); + +/* + mailimap_uid_store() + + This function will alter the data associated with some messages + (flags of the messages). + + @param session IMAP session + @param set This is a list of message numbers. + @param store_att_flags This is the data to associate with the + given messages + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int +mailimap_store(mailimap * session, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags); + +/* + mailimap_uid_store() + + This function will alter the data associated with some messages + (flags of the messages). + + @param session IMAP session + @param set This is a list of message unique identifiers. + @param store_att_flags This is the data to associate with the + given messages + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int +mailimap_uid_store(mailimap * session, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags); + +/* + mailimap_subscribe() + + This function adds the specified mailbox name to the + server's set of "active" or "subscribed" mailboxes. + + @param session IMAP session + @param mb This is the name of the mailbox + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_subscribe(mailimap * session, const char * mb); + +/* + mailimap_unsubscribe() + + This function removes the specified mailbox name to the + server's set of "active" or "subscribed" mailboxes. + + @param session IMAP session + @param mb This is the name of the mailbox + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_unsubscribe(mailimap * session, const char * mb); + +/* + mailimap_starttls() + + This function starts change the mode of the connection to + switch to SSL connection. + It won't change the stream connection to SSL rightway. + See mailimap_socket_starttls() will switch the mailstream too. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR_XXX codes + */ + +LIBETPAN_EXPORT +int mailimap_starttls(mailimap * session); + +/* + mailimap_new() + + This function returns a new IMAP session. + + @param progr_rate When downloading messages, a function will be called + each time the amount of bytes downloaded reaches a multiple of this + value, this can be 0. + @param progr_fun This is the function to call to notify the progress, + this can be NULL. + + @return an IMAP session is returned. + */ + +LIBETPAN_EXPORT +mailimap * mailimap_new(size_t imap_progr_rate, + progress_function * imap_progr_fun); + +/* + mailimap_free() + + This function will free the data structures associated with + the IMAP session. + + @param session IMAP session + */ + +LIBETPAN_EXPORT +void mailimap_free(mailimap * session); + +/* + mailimap_send_current_tag() send current IMAP tag. See RFC 3501. + + @param session IMAP session + + @return MAILIMAP_NO_ERROR if the tag could be sent on the network. +*/ + +int mailimap_send_current_tag(mailimap * session); + +/* + mailimap_read_line() receive a line line buffer into memory. + + It needs to be called before starting to parse a response. + + @param session IMAP session + + @return MAILIMAP_NO_ERROR if a line could be buffered. +*/ + +char * mailimap_read_line(mailimap * session); + +/* + mailimap_parse_response() parse an IMAP response. + + @param session IMAP session + @param result an IMAP response data structure will be allocated and + filled with the parsed response. The pointer to the + allocated data structure will be stored in result. + + @return MAILIMAP_NO_ERROR if a line could be buffered. +*/ + +int mailimap_parse_response(mailimap * session, + struct mailimap_response ** result); + +/* + mailimap_set_progress_callback() set IMAP progression callbacks. + + @param session IMAP session + @param body_progr_fun set callback function for a progression of an imap + call that involves the download of a significant amount of data. + @param items_progr_fun set callback function for a progression of an imap + call that involves the download of information of several items. +*/ + +LIBETPAN_EXPORT +void mailimap_set_progress_callback(mailimap * session, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context); + +/* + mailimap_set_msg_att_handler() set a callback when a message information is + downloaded using FETCH. + + @param session IMAP session + @param handler set a callback function. This function will be called + during the download of the response each time a new message information + has just been downloaded. + @param context parameter that's passed to the callback function. +*/ + +LIBETPAN_EXPORT +void mailimap_set_msg_att_handler(mailimap * session, + mailimap_msg_att_handler * handler, + void * context); + +/* + mailimap_set_msg_body_handler() set a callback when a message body is + downloaded using FETCH. + + @param session IMAP session + @param handler set a callback function. This function will be called + during the download of the response to process the message body + as data become available from the network. + This can be used, for example, for downloading big messages (or it attachments) + to the file without keeping it in memory. + @param context parameter that's passed to the callback function. +*/ + +LIBETPAN_EXPORT +void mailimap_set_msg_body_handler(mailimap * session, + mailimap_msg_body_handler * handler, + void * context); + +/* + mailimap_set_timeout() set the network timeout of the IMAP session. + + @param session IMAP session + @param timeout value of the timeout in seconds. +*/ + +LIBETPAN_EXPORT +void mailimap_set_timeout(mailimap * session, time_t timeout);; + +/* + mailimap_get_timeout() get the network timeout of the IMAP session. + + @param session IMAP session + @return the value of the timeout in seconds. +*/ + +LIBETPAN_EXPORT +time_t mailimap_get_timeout(mailimap * session); + +/* + mailimap_set_logger() get the network timeout of the IMAP session. + + @param session IMAP session + @param logger logger function. See mailstream_types.h to know possible log_type values. + str is the log, data received or data sent. + @param logger_context parameter that is passed to the logger function. + @return the value of the timeout in seconds. +*/ + +LIBETPAN_EXPORT +void mailimap_set_logger(mailimap * session, void (* logger)(mailimap * session, int log_type, + const char * str, size_t size, void * context), void * logger_context); + +#ifndef LIBETPAN_HAS_MAILIMAP_163_WORKAROUND + #define LIBETPAN_HAS_MAILIMAP_163_WORKAROUND 1 +#endif + +LIBETPAN_EXPORT +int mailimap_is_163_workaround_enabled(mailimap * session); + +LIBETPAN_EXPORT +void mailimap_set_163_workaround_enabled(mailimap * session, int enabled); + +#ifndef LIBETPAN_HAS_MAILIMAP_RAMBLER_WORKAROUND + #define LIBETPAN_HAS_MAILIMAP_RAMBLER_WORKAROUND 1 +#endif + +/* + Enable workaround for Rambler IMAP server. + + Occasionally, for large attachments (~20MB) Rambler returns wrong length of the literal. + Since this workaround is not completely free from false positives, by default is is off. + + It is proposed to enable it only during downloading large attachments from Rambler: + + @code + if (encoding is (base64 or uuencode) and server is rambler.ru) { + mailimap_set_rambler_workaround_enabled(imap, 1); + … fetch part ... + mailimap_set_rambler_workaround_enabled(imap, 0); + } + @endcode +*/ + +LIBETPAN_EXPORT +int mailimap_is_rambler_workaround_enabled(mailimap * session); + +LIBETPAN_EXPORT +void mailimap_set_rambler_workaround_enabled(mailimap * session, int enabled); + +#ifndef LIBETPAN_HAS_MAILIMAP_QIP_WORKAROUND +#define LIBETPAN_HAS_MAILIMAP_QIP_WORKAROUND 1 +#endif + +/* + Enable workaround for QIP IMAP server. + + QIP returns invalid (?) response for storeFlags operation: + C: A999 UID STORE 123 +FLAGS.SILENT (\Seen) + S: * 6 FETCH () + S: A999 OK STORE completed + + Enabling this workaround allows successfully parse such responses. +*/ + +LIBETPAN_EXPORT +int mailimap_is_qip_workaround_enabled(mailimap * session); + +LIBETPAN_EXPORT +void mailimap_set_qip_workaround_enabled(mailimap * session, int enabled); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/mailimap_compress.c b/Sources/libetpan/low-level/imap/mailimap_compress.c new file mode 100644 index 00000000..b58bbfa9 --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_compress.c @@ -0,0 +1,118 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "mailimap_compress.h" + +#include "mailimap.h" +#include "mailimap_sender.h" +#include "mailstream_compress.h" + +#include + +LIBETPAN_EXPORT +int mailimap_compress(mailimap * session) +{ + struct mailimap_response * response; + int r; + int res; + int error_code; + mailstream_low * compressed_stream; + mailstream_low * low; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_token_send(session->imap_stream, "COMPRESS DEFLATE"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + if (mailstream_flush(session->imap_stream) == -1) { + res = MAILIMAP_ERROR_STREAM; + goto err; + } + + if (mailimap_read_line(session) == NULL) { + res = MAILIMAP_ERROR_STREAM; + goto err; + } + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + if (error_code != MAILIMAP_RESP_COND_STATE_OK) { + res = MAILIMAP_ERROR_EXTENSION; + goto err; + } + + low = mailstream_get_low(session->imap_stream); + compressed_stream = mailstream_low_compress_open(low); + if (compressed_stream == NULL) { + res = MAILIMAP_ERROR_STREAM; + goto err; + } + mailstream_low_set_timeout(compressed_stream, session->imap_timeout); + mailstream_set_low(session->imap_stream, compressed_stream); + + return MAILIMAP_NO_ERROR; + +err: + return res; +} + +LIBETPAN_EXPORT +int mailimap_has_compress_deflate(mailimap * session) +{ + return mailimap_has_extension(session, "COMPRESS=DEFLATE"); +} diff --git a/Sources/libetpan/low-level/imap/mailimap_compress.h b/Sources/libetpan/low-level/imap/mailimap_compress.h new file mode 100644 index 00000000..98731e7f --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_compress.h @@ -0,0 +1,68 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef MAILIMAP_COMPRESS_H + +#define MAILIMAP_COMPRESS_H + +#include + +/* + mailimap_compress() + + This function will request IMAP compression by sending + a COMPRESS command. It will also change the stream connection to + a compressed stream (mailstream_compress). + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +LIBETPAN_EXPORT +int mailimap_compress(mailimap * session); + +/* + mailimap_has_compress_deflate() + + This function will return 1 if compression deflate is available + on the server else it will return 0. + + @param session IMAP session + + @return returns 1 if compression deflate is available on the server. + */ + +LIBETPAN_EXPORT +int mailimap_has_compress_deflate(mailimap * session); + +#endif diff --git a/Sources/libetpan/low-level/imap/mailimap_extension.c b/Sources/libetpan/low-level/imap/mailimap_extension.c new file mode 100644 index 00000000..e4115c30 --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_extension.c @@ -0,0 +1,241 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailimap_extension.h" + +#include +#include +#include + +#include "clist.h" +#include "annotatemore.h" +#include "acl.h" +#include "uidplus.h" +#include "quota.h" +#include "namespace.h" +#include "xlist.h" +#include "xgmlabels.h" +#include "xgmmsgid.h" +#include "xgmthrid.h" +#include "mailimap_id.h" +#include "enable.h" +#include "condstore.h" +#include "qresync.h" +#include "mailimap_sort.h" + +/* + the list of registered extensions (struct mailimap_extension_api *) + + the list of extension is kept as a simple clist. +*/ + +static clist * mailimap_extension_list = NULL; + +static struct mailimap_extension_api * internal_extension_list[] = { + &mailimap_extension_annotatemore, + &mailimap_extension_acl, + &mailimap_extension_uidplus, + &mailimap_extension_quota, + &mailimap_extension_namespace, + &mailimap_extension_xlist, + &mailimap_extension_xgmlabels, + &mailimap_extension_xgmmsgid, + &mailimap_extension_xgmthrid, + &mailimap_extension_id, + &mailimap_extension_enable, + &mailimap_extension_condstore, + &mailimap_extension_qresync, + &mailimap_extension_sort +}; + +LIBETPAN_EXPORT +int +mailimap_extension_register(struct mailimap_extension_api * extension) +{ + if (mailimap_extension_list == NULL) { + mailimap_extension_list = clist_new(); + if (mailimap_extension_list == NULL) + return MAILIMAP_ERROR_MEMORY; + } + + return clist_append(mailimap_extension_list, extension); +} + +LIBETPAN_EXPORT +void +mailimap_extension_unregister_all(void) +{ + clist_free(mailimap_extension_list); + mailimap_extension_list = NULL; +} + +LIBETPAN_EXPORT +int +mailimap_extension_data_parse(int calling_parser, + mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + clistiter * cur; + int r; + unsigned int i; + + for(i = 0 ; i < sizeof(internal_extension_list) / sizeof(* internal_extension_list) ; i ++) { + struct mailimap_extension_api * ext; + + ext = internal_extension_list[i]; + r = ext->ext_parser(calling_parser, fd, buffer, parser_ctx, indx, result, + progr_rate, progr_fun); + if (r != MAILIMAP_ERROR_PARSE) + return r; + } + + if (mailimap_extension_list == NULL) + return MAILIMAP_ERROR_PARSE; + + for (cur = clist_begin(mailimap_extension_list); + cur != NULL; cur = clist_next(cur)) { + struct mailimap_extension_api * ext; + + ext = clist_content(cur); + r = ext->ext_parser(calling_parser, fd, buffer, parser_ctx, indx, result, + progr_rate, progr_fun); + if (r != MAILIMAP_ERROR_PARSE) + return r; + } + + return MAILIMAP_ERROR_PARSE; +} + +LIBETPAN_EXPORT +struct mailimap_extension_data * +mailimap_extension_data_new(struct mailimap_extension_api * extension, + int type, void * data) +{ + struct mailimap_extension_data * ext_data; + + ext_data = malloc(sizeof(* ext_data)); + if (ext_data == NULL) + return NULL; + + ext_data->ext_extension = extension; + ext_data->ext_type = type; + ext_data->ext_data = data; + + return ext_data; +} + +LIBETPAN_EXPORT +void +mailimap_extension_data_free(struct + mailimap_extension_data * data) +{ + if (data == NULL) + return; + + if (data->ext_extension != NULL && data->ext_data != NULL) + /* ext_free() includes free(data) */ + data->ext_extension->ext_free(data); + else + free(data); +} + +void mailimap_extension_data_store(mailimap * session, + struct mailimap_extension_data ** ext_data) +{ + int r; + + if (session->imap_response_info) { + r = clist_append(session->imap_response_info->rsp_extension_list, + * ext_data); + if (r == 0) + * ext_data = NULL; + else { + /* TODO must handle error case */ + } + } +} + +LIBETPAN_EXPORT +int mailimap_has_extension(mailimap * session, const char * extension_name) +{ + if (session->imap_connection_info != NULL) { + if (session->imap_connection_info->imap_capability != NULL) { + clist * list; + clistiter * cur; + + list = session->imap_connection_info->imap_capability->cap_list; + for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_capability * cap; + + cap = clist_content(cur); + if (cap->cap_type != MAILIMAP_CAPABILITY_NAME) + continue; + + if (strcasecmp(cap->cap_data.cap_name, extension_name) == 0) + return 1; + } + } + } + + return 0; +} + +LIBETPAN_EXPORT +int mailimap_has_authentication(mailimap * session, const char * authentication_name) +{ + if (session->imap_connection_info != NULL) { + if (session->imap_connection_info->imap_capability != NULL) { + clist * list; + clistiter * cur; + + list = session->imap_connection_info->imap_capability->cap_list; + for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_capability * cap; + + cap = clist_content(cur); + if (cap->cap_type != MAILIMAP_CAPABILITY_AUTH_TYPE) + continue; + + if (strcasecmp(cap->cap_data.cap_name, authentication_name) == 0) + return 1; + + } + } + } + + return 0; +} diff --git a/Sources/libetpan/low-level/imap/mailimap_extension.h b/Sources/libetpan/low-level/imap/mailimap_extension.h new file mode 100644 index 00000000..d9dfe722 --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_extension.h @@ -0,0 +1,111 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef MAILIMAP_EXTENSION_H + +#define MAILIMAP_EXTENSION_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/* + you add a (static) mailimap_extension_api to the list of extensions + by calling register. making the list of + extensions contain all extensions statically may prove detrimental + to speed if you have many extensions and don't need any of them. + as unregistering single extensions does not really make any sense, + it's not provided - just an unregister_all which is primarily used + to free the clist on exit. +*/ + +LIBETPAN_EXPORT +int +mailimap_extension_register(struct mailimap_extension_api * extension); + +LIBETPAN_EXPORT +void +mailimap_extension_unregister_all(void); + +/* + this is called as the main parser wrapper for all extensions. + it gos through the list of registered extensions and calls + all of the extensions' parsers looking for one that doesn't + return MAILIMAP_ERROR_PARSE. +*/ +LIBETPAN_EXPORT +int +mailimap_extension_data_parse(int calling_parser, + mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +LIBETPAN_EXPORT +struct mailimap_extension_data * +mailimap_extension_data_new(struct mailimap_extension_api * extension, + int type, void * data); + +/* + wrapper for the extensions' free. calls the correct extension's free + based on data->extension. +*/ +LIBETPAN_EXPORT +void +mailimap_extension_data_free(struct + mailimap_extension_data * data); + +/* + stores the ext_data in the session (only needed for extensions + that embed directly into response-data). +*/ +void mailimap_extension_data_store(mailimap * session, + struct mailimap_extension_data ** ext_data); + +/* + return 1 if the extension of the given name is supported. + the name is searched in the capabilities. +*/ + +LIBETPAN_EXPORT +int mailimap_has_extension(mailimap * session, const char * extension_name); + +LIBETPAN_EXPORT +int mailimap_has_authentication(mailimap * session, const char * authentication_name); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/mailimap_extension_types.h b/Sources/libetpan/low-level/imap/mailimap_extension_types.h new file mode 100644 index 00000000..5f70b7cb --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_extension_types.h @@ -0,0 +1,115 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILIMAP_EXTENSION_TYPES_H + +#define MAILIMAP_EXTENSION_TYPES_H + +#include +#include + +struct mailimap_extension_data; + +/* + this is the list of known extensions with the purpose to + get integer identifers for the extensions. +*/ + +enum { + MAILIMAP_EXTENSION_ANNOTATEMORE, /* the annotatemore-draft */ + MAILIMAP_EXTENSION_ACL, /* the acl capability */ + MAILIMAP_EXTENSION_UIDPLUS, /* UIDPLUS */ + MAILIMAP_EXTENSION_QUOTA, /* quota */ + MAILIMAP_EXTENSION_NAMESPACE, /* namespace */ + MAILIMAP_EXTENSION_XLIST, /* XLIST (Gmail and Zimbra have this) */ + MAILIMAP_EXTENSION_XGMLABELS, /* X-GM-LABELS (Gmail) */ + MAILIMAP_EXTENSION_XGMMSGID, /* X-GM-MSGID (Gmail) */ + MAILIMAP_EXTENSION_XGMTHRID, /* X-GM-THRID (Gmail) */ + MAILIMAP_EXTENSION_ID, /* ID */ + MAILIMAP_EXTENSION_ENABLE, /* ENABLE */ + MAILIMAP_EXTENSION_CONDSTORE, /* CONDSTORE */ + MAILIMAP_EXTENSION_QRESYNC, /* QRESYNC */ + MAILIMAP_EXTENSION_SORT /* SORT */ +}; + + +/* + this is a list of extended parser functions. The extended parser + passes its identifier to the extension parser. +*/ + +enum { + MAILIMAP_EXTENDED_PARSER_RESPONSE_DATA, + MAILIMAP_EXTENDED_PARSER_RESP_TEXT_CODE, + MAILIMAP_EXTENDED_PARSER_MAILBOX_DATA, + MAILIMAP_EXTENDED_PARSER_FETCH_DATA, + MAILIMAP_EXTENDED_PARSER_STATUS_ATT +}; + +/* + this is the extension interface. each extension consists + of a initial parser and an initial free. the parser is + passed the calling parser's identifier. based on this + identifier the initial parser can then decide which + actual parser to call. free has mailimap_extension_data + as parameter. if you look at mailimap_extension_data + you'll see that it contains "type" as one of its + elements. thus an extension's initial free can call + the correct actual free to free its data. +*/ +struct mailimap_extension_api { + char * ext_name; + int ext_id; /* use -1 if this is an extension outside libetpan */ + + int (* ext_parser)(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun); + + void (* ext_free)(struct mailimap_extension_data * ext_data); +}; + +/* + mailimap_extension_data is a wrapper for values parsed by extensions + + - extension is an identifier for the extension that parsed the value. + + - type is an identifier for the real type of the data. + + - data is a pointer to the real data. +*/ +struct mailimap_extension_data { + struct mailimap_extension_api * ext_extension; + int ext_type; + void * ext_data; +}; + +#endif diff --git a/Sources/libetpan/low-level/imap/mailimap_helper.c b/Sources/libetpan/low-level/imap/mailimap_helper.c new file mode 100644 index 00000000..e332e0ac --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_helper.c @@ -0,0 +1,209 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_helper.c,v 1.13 2011/05/21 23:28:21 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailimap_helper.h" + +#include +#include "mailimap.h" + +LIBETPAN_EXPORT +int mailimap_fetch_rfc822(mailimap * session, + uint32_t msgid, char ** result) +{ + int r; + clist * fetch_list; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + struct mailimap_set * set; + struct mailimap_msg_att * msg_att; + struct mailimap_msg_att_item * item; + int res; + clistiter * cur; + + fetch_att = mailimap_fetch_att_new_rfc822(); + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + set = mailimap_set_new_single(msgid); + + r = mailimap_fetch(session, set, fetch_type, &fetch_list); + + mailimap_set_free(set); + mailimap_fetch_type_free(fetch_type); + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + if (clist_isempty(fetch_list)) { + res = MAILIMAP_ERROR_FETCH; + goto free; + } + + msg_att = (struct mailimap_msg_att *) clist_begin(fetch_list)->data; + + for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; cur = clist_next(cur)) { + item = (struct mailimap_msg_att_item *) clist_content(cur); + + if (item->att_type != MAILIMAP_MSG_ATT_ITEM_STATIC) { + continue; + } + if (item->att_data.att_static->att_type != MAILIMAP_MSG_ATT_RFC822) { + continue; + } + + * result = item->att_data.att_static->att_data.att_rfc822.att_content; + item->att_data.att_static->att_data.att_rfc822.att_content = NULL; + mailimap_fetch_list_free(fetch_list); + + return MAILIMAP_NO_ERROR; + } + + res = MAILIMAP_ERROR_FETCH; + +free: + mailimap_fetch_list_free(fetch_list); +err: + return res; +} + +LIBETPAN_EXPORT +int mailimap_fetch_rfc822_header(mailimap * session, + uint32_t msgid, char ** result) +{ + int r; + int res; + clist * fetch_list; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + struct mailimap_set * set; + struct mailimap_msg_att * msg_att; + struct mailimap_msg_att_item * item; + clistiter * cur; + + fetch_att = mailimap_fetch_att_new_rfc822_header(); + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + set = mailimap_set_new_single(msgid); + + r = mailimap_fetch(session, set, fetch_type, &fetch_list); + + mailimap_set_free(set); + mailimap_fetch_type_free(fetch_type); + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + if (clist_isempty(fetch_list)) { + res = MAILIMAP_ERROR_FETCH; + goto free; + } + + msg_att = (struct mailimap_msg_att *) clist_begin(fetch_list)->data; + + for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; cur = clist_next(cur)) { + item = (struct mailimap_msg_att_item *) clist_content(cur); + + if (item->att_type != MAILIMAP_MSG_ATT_ITEM_STATIC) { + continue; + } + if (item->att_data.att_static->att_type != MAILIMAP_MSG_ATT_RFC822_HEADER) { + continue; + } + + * result = item->att_data.att_static->att_data.att_rfc822_header.att_content; + item->att_data.att_static->att_data.att_rfc822_header.att_content = NULL; + mailimap_fetch_list_free(fetch_list); + + return MAILIMAP_NO_ERROR; + } + + res = MAILIMAP_ERROR_FETCH; + +free: + mailimap_fetch_list_free(fetch_list); +err: + return res; +} + +LIBETPAN_EXPORT +int mailimap_fetch_envelope(mailimap * session, + uint32_t first, uint32_t last, + clist ** result) +{ + int r; + clist * fetch_list; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + struct mailimap_set * set; + + fetch_att = mailimap_fetch_att_new_envelope(); + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + set = mailimap_set_new_interval(first, last); + + r = mailimap_fetch(session, set, fetch_type, &fetch_list); + + mailimap_set_free(set); + mailimap_fetch_type_free(fetch_type); + + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = fetch_list; + + return MAILIMAP_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailimap_append_simple(mailimap * session, const char * mailbox, + const char * content, size_t size) +{ + return mailimap_append(session, mailbox, NULL, NULL, content, size); +} + +LIBETPAN_EXPORT +int mailimap_login_simple(mailimap * session, + const char * userid, const char * password) +{ + if (session->imap_state == MAILIMAP_STATE_NON_AUTHENTICATED) + return mailimap_login(session, userid, password); + else + return MAILIMAP_NO_ERROR; +} + diff --git a/Sources/libetpan/low-level/imap/mailimap_helper.h b/Sources/libetpan/low-level/imap/mailimap_helper.h new file mode 100644 index 00000000..aa0f278b --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_helper.h @@ -0,0 +1,71 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_helper.h,v 1.12 2006/06/07 15:10:01 smarinier Exp $ + */ + +#ifndef MAILIMAP_HELPER_H + +#define MAILIMAP_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +LIBETPAN_EXPORT +int mailimap_fetch_rfc822(mailimap * session, + uint32_t msgid, char ** result); + +LIBETPAN_EXPORT +int mailimap_fetch_rfc822_header(mailimap * session, + uint32_t msgid, char ** result); + +LIBETPAN_EXPORT +int mailimap_fetch_envelope(mailimap * session, + uint32_t first, uint32_t last, + clist ** result); + +LIBETPAN_EXPORT +int mailimap_append_simple(mailimap * session, const char * mailbox, + const char * content, size_t size); + +LIBETPAN_EXPORT +int mailimap_login_simple(mailimap * session, + const char * userid, const char * password); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/mailimap_id.c b/Sources/libetpan/low-level/imap/mailimap_id.c new file mode 100644 index 00000000..aac16b15 --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_id.c @@ -0,0 +1,231 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2011 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mailimap_id.h" + +#include +#include +#include + +#include "mailimap.h" +#include "mailimap_sender.h" +#include "mailimap_id_sender.h" +#include "mailimap_id_parser.h" +#include "mailimap_id_types.h" + +static void mailimap_id_ext_data_free(struct mailimap_extension_data * ext_data); + +LIBETPAN_EXPORT +struct mailimap_extension_api mailimap_extension_id = { + /* name */ "ID", + /* extension_id */ MAILIMAP_EXTENSION_ID, + /* parser */ mailimap_id_parse, + /* free */ mailimap_id_ext_data_free +}; + +int mailimap_id(mailimap * session, struct mailimap_id_params_list * client_identification, + struct mailimap_id_params_list ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + clistiter * cur; + struct mailimap_id_params_list * params_list; + + if ((session->imap_state == MAILIMAP_STATE_DISCONNECTED) || (session->imap_state == MAILIMAP_STATE_LOGOUT)) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_id_send(session->imap_stream, client_identification); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + params_list = NULL; + for (cur = clist_begin(session->imap_response_info->rsp_extension_list); + cur != NULL; cur = clist_next(cur)) { + struct mailimap_extension_data * ext_data; + + ext_data = (struct mailimap_extension_data *) clist_content(cur); + if (ext_data->ext_extension->ext_id == MAILIMAP_EXTENSION_ID) { + params_list = ext_data->ext_data; + ext_data->ext_data = NULL; + ext_data->ext_type = -1; + } + } + + if (params_list == NULL) { + params_list = mailimap_id_params_list_new_empty(); + } + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + * result = params_list; + return MAILIMAP_NO_ERROR; + + default: + mailimap_id_params_list_free(params_list); + return MAILIMAP_ERROR_EXTENSION; + } +} + +static void mailimap_id_ext_data_free(struct mailimap_extension_data * ext_data) +{ + if (ext_data->ext_data != NULL) { + mailimap_id_params_list_free(ext_data->ext_data); + } + free(ext_data); +} + +LIBETPAN_EXPORT +int mailimap_id_basic(mailimap * session, const char * name, const char * version, + char ** p_server_name, char ** p_server_version) +{ + struct mailimap_id_params_list * client_identification; + struct mailimap_id_params_list * server_identification; + int r; + char * server_name; + char * server_version; + char * dup_name; + char * dup_value; + clistiter * cur; + + client_identification = mailimap_id_params_list_new_empty(); + if (client_identification == NULL) + return MAILIMAP_ERROR_MEMORY; + + if (name != NULL) { + dup_name = strdup("name"); + if (dup_name == NULL) { + mailimap_id_params_list_free(client_identification); + return MAILIMAP_ERROR_MEMORY; + } + + dup_value = strdup(name); + if (dup_value == NULL) { + free(dup_name); + mailimap_id_params_list_free(client_identification); + return MAILIMAP_ERROR_MEMORY; + } + + r = mailimap_id_params_list_add_name_value(client_identification, dup_name, dup_value); + if (r != MAILIMAP_NO_ERROR) { + free(dup_value); + free(dup_name); + mailimap_id_params_list_free(client_identification); + return MAILIMAP_ERROR_MEMORY; + } + } + + if (version != NULL) { + dup_name = strdup("version"); + if (dup_name == NULL) { + mailimap_id_params_list_free(client_identification); + return MAILIMAP_ERROR_MEMORY; + } + + dup_value = strdup(version); + if (dup_value == NULL) { + free(dup_name); + mailimap_id_params_list_free(client_identification); + return MAILIMAP_ERROR_MEMORY; + } + + r = mailimap_id_params_list_add_name_value(client_identification, dup_name, dup_value); + if (r != MAILIMAP_NO_ERROR) { + free(dup_value); + free(dup_name); + mailimap_id_params_list_free(client_identification); + return MAILIMAP_ERROR_MEMORY; + } + } + + r = mailimap_id(session, client_identification, &server_identification); + if (r != MAILIMAP_NO_ERROR) { + mailimap_id_params_list_free(client_identification); + return r; + } + + server_name = NULL; + server_version = NULL; + for(cur = clist_begin(server_identification->idpa_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_id_param * param; + + param = clist_content(cur); + if (strcasecmp(param->idpa_name, "name") == 0) { + if (server_name != NULL) { + free(server_name); + } + server_name = strdup(param->idpa_value); + } + else if (strcasecmp(param->idpa_name, "version") == 0) { + if (server_version != NULL) { + free(server_version); + } + server_version = strdup(param->idpa_value); + } + } + + mailimap_id_params_list_free(client_identification); + mailimap_id_params_list_free(server_identification); + + * p_server_name = server_name; + * p_server_version = server_version; + + return MAILIMAP_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailimap_has_id(mailimap * session) +{ + return mailimap_has_extension(session, "ID"); +} + diff --git a/Sources/libetpan/low-level/imap/mailimap_id.h b/Sources/libetpan/low-level/imap/mailimap_id.h new file mode 100644 index 00000000..93384a0e --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_id.h @@ -0,0 +1,64 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2011 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef MAILIMAP_ID_H + +#define MAILIMAP_ID_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +LIBETPAN_EXPORT extern struct mailimap_extension_api mailimap_extension_id; + +LIBETPAN_EXPORT +int mailimap_has_id(mailimap * session); + +LIBETPAN_EXPORT +int mailimap_id(mailimap * session, struct mailimap_id_params_list * client_identification, + struct mailimap_id_params_list ** result); + +/* Helpers */ + +/* result must be freed */ +LIBETPAN_EXPORT +int mailimap_id_basic(mailimap * session, const char * name, const char * version, + char ** p_server_name, char ** p_server_version); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/mailimap_id_parser.c b/Sources/libetpan/low-level/imap/mailimap_id_parser.c new file mode 100644 index 00000000..69df4a4b --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_id_parser.c @@ -0,0 +1,193 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "mailimap_id_parser.h" + +#include "mailimap_parser.h" +#include "mailimap_id_types.h" +#include "mailimap_keywords.h" +#include "mailimap_id.h" + +#include + +static int mailimap_id_response_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result); + +static int mailimap_id_params_list_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_id_params_list ** result); + +int mailimap_id_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + if (calling_parser != MAILIMAP_EXTENDED_PARSER_RESPONSE_DATA) + return MAILIMAP_ERROR_PARSE; + + return mailimap_id_response_parse(fd, buffer, parser_ctx, indx, result); +} + +/* id_response ::= "ID" SPACE id_params_list */ + +static int mailimap_id_response_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result) +{ + struct mailimap_id_params_list * params_list; + struct mailimap_extension_data * ext_data; + size_t cur_token; + int r; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "ID"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + /* ignore result */ + + r = mailimap_id_params_list_parse(fd, buffer, parser_ctx, &cur_token, ¶ms_list); + if (r != MAILIMAP_NO_ERROR) + return r; + + ext_data = mailimap_extension_data_new(&mailimap_extension_id, + 0, params_list); + if (ext_data == NULL) { + mailimap_id_params_list_free(params_list); + return MAILIMAP_ERROR_MEMORY; + } + + * indx = cur_token; + * result = ext_data; + + return MAILIMAP_NO_ERROR; +} + +/* + string SPACE nstring +*/ + +static int mailimap_id_param_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_id_param ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int r; + char * name; + char * value; + size_t len; + size_t cur_token; + struct mailimap_id_param * param; + + cur_token = * indx; + + r = mailimap_string_parse(fd, buffer, parser_ctx, &cur_token, &name, &len, 0, NULL); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + /* ignore result */ + + r = mailimap_nstring_parse(fd, buffer, parser_ctx, &cur_token, &value, &len, 0, NULL); + if (r != MAILIMAP_NO_ERROR) { + mailimap_string_free(name); + return r; + } + + param = mailimap_id_param_new(name, value); + if (param == NULL) { + mailimap_nstring_free(value); + mailimap_string_free(name); + return MAILIMAP_ERROR_MEMORY; + } + + * indx = cur_token; + * result = param; + + return MAILIMAP_NO_ERROR; +} + +/* +id_params_list ::= "(" #(string SPACE nstring) ")" / nil + ;; list of field value pairs +*/ + +static int mailimap_id_params_list_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_id_params_list ** result) +{ + struct mailimap_id_params_list * params_list; + clist * items; + size_t cur_token; + int r; + + cur_token = * indx; + + r = mailimap_nil_parse(fd, buffer, parser_ctx, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + * indx = cur_token; + * result = NULL; + return MAILIMAP_NO_ERROR; + } + + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, + &cur_token, &items, + (mailimap_struct_parser *) mailimap_id_param_parse, + (mailimap_struct_destructor *) mailimap_id_param_free, + 0, NULL); + if (r != MAILIMAP_NO_ERROR) + return r; + + params_list = mailimap_id_params_list_new(items); + if (params_list == NULL) { + clist_foreach(items, (clist_func) mailimap_id_param_free, NULL); + clist_free(items); + return MAILIMAP_ERROR_MEMORY; + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + mailimap_id_params_list_free(params_list); + return r; + } + + * indx = cur_token; + * result = params_list; + + return MAILIMAP_NO_ERROR; +} diff --git a/Sources/libetpan/low-level/imap/mailimap_id_parser.h b/Sources/libetpan/low-level/imap/mailimap_id_parser.h new file mode 100644 index 00000000..7918a826 --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_id_parser.h @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILIMAP_ID_PARSER_H + +#define MAILIMAP_ID_PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +int mailimap_id_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/mailimap_id_sender.c b/Sources/libetpan/low-level/imap/mailimap_id_sender.c new file mode 100644 index 00000000..68e8cdc4 --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_id_sender.c @@ -0,0 +1,113 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "mailimap_id_sender.h" + +#include + +#include "mailimap_sender.h" + +static int mailimap_id_param_send(mailstream * fd, struct mailimap_id_param * param); +static int mailimap_id_params_list_send(mailstream * fd, struct mailimap_id_params_list * list); + +int mailimap_id_send(mailstream * fd, struct mailimap_id_params_list * client_identification) +{ + int r; + + r = mailimap_token_send(fd, "ID"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_id_params_list_send(fd, client_identification); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +static int mailimap_id_params_list_send(mailstream * fd, struct mailimap_id_params_list * list) +{ + int r; + + if ((list == NULL) || (clist_count(list->idpa_list) == 0)) { + r = mailimap_token_send(fd, "NIL"); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + } + + r = mailimap_oparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_struct_spaced_list_send(fd, list->idpa_list, + (mailimap_struct_sender *) + mailimap_id_param_send); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_cparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +static int mailimap_id_param_send(mailstream * fd, struct mailimap_id_param * param) +{ + int r; + + // Sends quoted string instead since Yahoo IMAP server will break when sending atoms. + r = mailimap_quoted_send(fd, param->idpa_name); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (param->idpa_value == NULL) { + r = mailimap_token_send(fd, "NIL"); + if (r != MAILIMAP_NO_ERROR) + return r; + } + else { + // Sends quoted string instead since Yahoo IMAP server will break when sending atoms. + r = mailimap_quoted_send(fd, param->idpa_value); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + return MAILIMAP_NO_ERROR; +} diff --git a/Sources/libetpan/low-level/imap/mailimap_id_sender.h b/Sources/libetpan/low-level/imap/mailimap_id_sender.h new file mode 100644 index 00000000..7fd9dfb8 --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_id_sender.h @@ -0,0 +1,50 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILIMAP_ID_SENDER_H + +#define MAILIMAP_ID_SENDER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +LIBETPAN_EXPORT +int mailimap_id_send(mailstream * fd, struct mailimap_id_params_list * client_identification); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/mailimap_id_types.c b/Sources/libetpan/low-level/imap/mailimap_id_types.c new file mode 100644 index 00000000..af4fde05 --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_id_types.c @@ -0,0 +1,119 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "mailimap_id_types.h" + +#include + +#include "mailimap_types.h" + +LIBETPAN_EXPORT +struct mailimap_id_params_list * mailimap_id_params_list_new(clist * items) +{ + struct mailimap_id_params_list * list; + + list = malloc(sizeof(* list)); + if (list == NULL) + return NULL; + + list->idpa_list = items; + + return list; +} + +LIBETPAN_EXPORT +void mailimap_id_params_list_free(struct mailimap_id_params_list * list) +{ + clist_foreach(list->idpa_list, (clist_func) mailimap_id_param_free, NULL); + clist_free(list->idpa_list); + free(list); +} + +LIBETPAN_EXPORT +struct mailimap_id_param * mailimap_id_param_new(char * name, char * value) +{ + struct mailimap_id_param * param; + + param = malloc(sizeof(* param)); + if (param == NULL) + return NULL; + + param->idpa_name = name; + param->idpa_value = value; + + return param; +} + +LIBETPAN_EXPORT +void mailimap_id_param_free(struct mailimap_id_param * param) +{ + mailimap_string_free(param->idpa_name); + mailimap_nstring_free(param->idpa_value); + free(param); +} + +LIBETPAN_EXPORT +struct mailimap_id_params_list * mailimap_id_params_list_new_empty(void) +{ + clist * items; + struct mailimap_id_params_list * list; + + items = clist_new(); + if (items == NULL) + return NULL; + + list = mailimap_id_params_list_new(items); + if (list == NULL) { + clist_free(items); + return NULL; + } + + return list; +} + +LIBETPAN_EXPORT +int mailimap_id_params_list_add_name_value(struct mailimap_id_params_list * list, char * name, char * value) +{ + struct mailimap_id_param * param; + int r; + + param = mailimap_id_param_new(name, value); + if (param == NULL) + return -1; + + r = clist_append(list->idpa_list, param); + if (r < 0) { + mailimap_id_param_free(param); + return -1; + } + + return 0; +} + diff --git a/Sources/libetpan/low-level/imap/mailimap_id_types.h b/Sources/libetpan/low-level/imap/mailimap_id_types.h new file mode 100644 index 00000000..4a73f400 --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_id_types.h @@ -0,0 +1,72 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILIMAP_ID_TYPES_H + +#define MAILIMAP_ID_TYPES_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct mailimap_id_params_list { + clist * /* struct mailimap_id_param */ idpa_list; +}; + +LIBETPAN_EXPORT +struct mailimap_id_params_list * mailimap_id_params_list_new(clist * items); + +LIBETPAN_EXPORT +void mailimap_id_params_list_free(struct mailimap_id_params_list * list); + +struct mailimap_id_param { + char * idpa_name; + char * idpa_value; +}; + +LIBETPAN_EXPORT +struct mailimap_id_param * mailimap_id_param_new(char * name, char * value); + +LIBETPAN_EXPORT +void mailimap_id_param_free(struct mailimap_id_param * param); + +LIBETPAN_EXPORT +struct mailimap_id_params_list * mailimap_id_params_list_new_empty(void); + +LIBETPAN_EXPORT +int mailimap_id_params_list_add_name_value(struct mailimap_id_params_list * list, char * name, char * value); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/mailimap_keywords.c b/Sources/libetpan/low-level/imap/mailimap_keywords.c new file mode 100644 index 00000000..d9b1013f --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_keywords.c @@ -0,0 +1,361 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_keywords.c,v 1.14 2011/05/28 23:21:45 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailimap_keywords.h" +#include "mailimap_types.h" +#include +#include + +#ifndef UNSTRICT_SYNTAX +#define UNSTRICT_SYNTAX +#endif + +struct mailimap_token_value { + int value; + const char * str; +}; + +int mailimap_token_case_insensitive_parse(mailstream * fd, + MMAPString * buffer, + size_t * indx, + const char * token) +{ + size_t len; + size_t cur_token; + int r; + + cur_token = * indx; + len = strlen(token); + +#ifdef UNSTRICT_SYNTAX + r = mailimap_space_parse(fd, buffer, &cur_token); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; +#endif + + if (strncasecmp(buffer->str + cur_token, token, len) == 0) { + cur_token += len; + * indx = cur_token; + return MAILIMAP_NO_ERROR; + } + else + return MAILIMAP_ERROR_PARSE; +} + + +static int is_space_or_tab(char ch) +{ + return (ch == ' ') || (ch == '\t'); +} + +int mailimap_char_parse(mailstream * fd, MMAPString * buffer, + size_t * indx, char token) +{ + size_t cur_token; + + cur_token = * indx; + + if (buffer->str[cur_token] == token) { + cur_token ++; + * indx = cur_token; + return MAILIMAP_NO_ERROR; + } + else + return MAILIMAP_ERROR_PARSE; +} + +int mailimap_space_parse(mailstream * fd, MMAPString * buffer, + size_t * indx) +{ +#ifdef UNSTRICT_SYNTAX + + /* can accept unstrict syntax */ + size_t cur_token; + + cur_token = * indx; + + while (is_space_or_tab(* (buffer->str + cur_token))) + cur_token ++; + + if (cur_token == * indx) + return MAILIMAP_ERROR_PARSE; + + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + +#else + return mailimap_char_parse(fd, buffer, indx, ' '); +#endif +} + + + +#define mailimap_get_token_str(indx, tab) \ + mailimap_get_token_str_size(indx, tab, \ + sizeof(tab) / sizeof(struct mailimap_token_value)) + +#define mailimap_get_token_value(fd, buffer, indx, tab) \ + mailimap_get_token_value_size(fd, buffer, indx, tab, \ + sizeof(tab) / sizeof(struct mailimap_token_value)) + + +static const char * mailimap_get_token_str_size(int indx, + struct mailimap_token_value * tab, + size_t size) +{ + size_t i; + + for(i = 0 ; i < size ; i++) + if (indx == tab[i].value) + return tab[i].str; + + return NULL; +} + + + +static int mailimap_get_token_value_size(mailstream * fd, MMAPString * buffer, + size_t * indx, + struct mailimap_token_value * tab, + size_t size) +{ + size_t i; + int r; + +#ifdef UNSTRICT_SYNTAX + /* can accept unstrict syntax */ + r = mailimap_space_parse(fd, buffer, indx); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; +#endif + + for(i = 0 ; i < size ; i++) { + r = mailimap_token_case_insensitive_parse(fd, buffer, indx, tab[i].str); + if (r == MAILIMAP_NO_ERROR) + return tab[i].value; + } + + return -1; +} + + +static struct mailimap_token_value status_att_tab[] = { + {MAILIMAP_STATUS_ATT_MESSAGES, "MESSAGES"}, + {MAILIMAP_STATUS_ATT_RECENT, "RECENT"}, + {MAILIMAP_STATUS_ATT_UIDNEXT, "UIDNEXT"}, + {MAILIMAP_STATUS_ATT_UIDVALIDITY, "UIDVALIDITY"}, + {MAILIMAP_STATUS_ATT_UNSEEN, "UNSEEN"}, + {MAILIMAP_STATUS_ATT_HIGHESTMODSEQ, "HIGHESTMODSEQ"}, +}; + +int mailimap_status_att_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * indx) +{ + int r; + +#ifdef UNSTRICT_SYNTAX + /* can accept unstrict syntax */ + r = mailimap_space_parse(fd, buffer, indx); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; +#endif + return mailimap_get_token_value(fd, buffer, indx, + status_att_tab); +} + + +const char * mailimap_status_att_get_token_str(int indx) +{ + return mailimap_get_token_str(indx, status_att_tab); +} + +static struct mailimap_token_value month_tab[] = { + {1, "Jan"}, + {2, "Feb"}, + {3, "Mar"}, + {4, "Apr"}, + {5, "May"}, + {6, "Jun"}, + {7, "Jul"}, + {8, "Aug"}, + {9, "Sep"}, + {10, "Oct"}, + {11, "Nov"}, + {12, "Dec"} +}; + +int mailimap_month_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * indx) +{ + return mailimap_get_token_value(fd, buffer, indx, month_tab); +} + + +const char * mailimap_month_get_token_str(int indx) +{ + return mailimap_get_token_str(indx, month_tab); +} + + + + + +static struct mailimap_token_value mailimap_flag_tab[] = { + {MAILIMAP_FLAG_ANSWERED, "\\Answered"}, + {MAILIMAP_FLAG_FLAGGED, "\\Flagged"}, + {MAILIMAP_FLAG_DELETED, "\\Deleted"}, + {MAILIMAP_FLAG_SEEN, "\\Seen"}, + {MAILIMAP_FLAG_DRAFT, "\\Draft"} +}; + +int mailimap_flag_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * indx) +{ + return mailimap_get_token_value(fd, buffer, indx, + mailimap_flag_tab); +} + + +const char * mailimap_flag_get_token_str(int indx) +{ + return mailimap_get_token_str(indx, mailimap_flag_tab); +} + + + + +static struct mailimap_token_value encoding_tab[] = { + {MAILIMAP_BODY_FLD_ENC_7BIT, "7BIT"}, + {MAILIMAP_BODY_FLD_ENC_8BIT, "8BIT"}, + {MAILIMAP_BODY_FLD_ENC_BINARY, "BINARY"}, + {MAILIMAP_BODY_FLD_ENC_BASE64, "BASE64"}, + {MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE, "QUOTED-PRINTABLE"} +}; + +int mailimap_encoding_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * indx) +{ + return mailimap_get_token_value(fd, buffer, indx, encoding_tab); +} + +static struct mailimap_token_value mbx_list_sflag_tab[] = { + {MAILIMAP_MBX_LIST_SFLAG_MARKED, "\\Marked"}, + {MAILIMAP_MBX_LIST_SFLAG_NOSELECT, "\\Noselect"}, + {MAILIMAP_MBX_LIST_SFLAG_UNMARKED, "\\Unmarked"}, + {MAILIMAP_MBX_LIST_SFLAG_MARKED, "/Marked"}, + {MAILIMAP_MBX_LIST_SFLAG_NOSELECT, "/Noselect"}, + {MAILIMAP_MBX_LIST_SFLAG_UNMARKED, "/Unmarked"} +}; + +int mailimap_mbx_list_sflag_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * indx) +{ + return mailimap_get_token_value(fd, buffer, indx, mbx_list_sflag_tab); +} + +static struct mailimap_token_value media_basic_tab[] = { + {MAILIMAP_MEDIA_BASIC_APPLICATION, "APPLICATION"}, + {MAILIMAP_MEDIA_BASIC_AUDIO, "AUDIO"}, + {MAILIMAP_MEDIA_BASIC_IMAGE, "IMAGE"}, + {MAILIMAP_MEDIA_BASIC_MESSAGE, "MESSAGE"}, + {MAILIMAP_MEDIA_BASIC_VIDEO, "VIDEO"} +}; + +int mailimap_media_basic_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * indx) +{ + return mailimap_get_token_value(fd, buffer, indx, media_basic_tab); +} + +static struct mailimap_token_value resp_cond_state_tab[] = { + {MAILIMAP_RESP_COND_STATE_OK, "OK"}, + {MAILIMAP_RESP_COND_STATE_NO, "NO"}, + {MAILIMAP_RESP_COND_STATE_BAD, "BAD"} +}; + +int mailimap_resp_cond_state_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * indx) +{ + return mailimap_get_token_value(fd, buffer, indx, resp_cond_state_tab); +} + +static struct mailimap_token_value resp_text_code_1_tab[] = { + {MAILIMAP_RESP_TEXT_CODE_ALERT, "ALERT"}, + {MAILIMAP_RESP_TEXT_CODE_PARSE, "PARSE"}, + {MAILIMAP_RESP_TEXT_CODE_READ_ONLY, "READ-ONLY"}, + {MAILIMAP_RESP_TEXT_CODE_READ_WRITE, "READ-WRITE"}, + {MAILIMAP_RESP_TEXT_CODE_TRY_CREATE, "TRYCREATE"} +}; + +int mailimap_resp_text_code_1_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * indx) +{ + return mailimap_get_token_value(fd, buffer, indx, resp_text_code_1_tab); +} + +static struct mailimap_token_value resp_text_code_2_tab[] = { + {MAILIMAP_RESP_TEXT_CODE_UIDNEXT, "UIDNEXT"}, + {MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY, "UIDVALIDITY"}, + {MAILIMAP_RESP_TEXT_CODE_UNSEEN, "UNSEEN"}, +}; + +int mailimap_resp_text_code_2_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * indx) +{ + return mailimap_get_token_value(fd, buffer, indx, resp_text_code_2_tab); +} + +static struct mailimap_token_value section_msgtext_tab[] = { + {MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT, "HEADER.FIELDS.NOT"}, + {MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, "HEADER.FIELDS"}, + {MAILIMAP_SECTION_MSGTEXT_HEADER, "HEADER"}, + {MAILIMAP_SECTION_MSGTEXT_TEXT, "TEXT"} +}; + +int mailimap_section_msgtext_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * indx) +{ + return mailimap_get_token_value(fd, buffer, indx, section_msgtext_tab); +} diff --git a/Sources/libetpan/low-level/imap/mailimap_keywords.h b/Sources/libetpan/low-level/imap/mailimap_keywords.h new file mode 100644 index 00000000..d1350628 --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_keywords.h @@ -0,0 +1,107 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_keywords.h,v 1.9 2008/02/20 22:15:51 hoa Exp $ + */ + +#ifndef MAILIMAP_COMMON_H + +#define MAILIMAP_COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailstream.h" + + +/* tools */ + +int mailimap_char_parse(mailstream * fd, MMAPString * buffer, + size_t * indx, char token); + +int mailimap_space_parse(mailstream * fd, MMAPString * buffer, + size_t * indx); + +/* tokens */ + +int mailimap_token_case_insensitive_parse(mailstream * fd, + MMAPString * buffer, + size_t * indx, + const char * token); + +int mailimap_status_att_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * indx); +const char * mailimap_status_att_get_token_str(int indx); + + +int mailimap_month_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * indx); +const char * mailimap_month_get_token_str(int indx); + + +int mailimap_flag_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * indx); + +const char * mailimap_flag_get_token_str(int indx); + +int mailimap_encoding_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * indx); + +int mailimap_mbx_list_sflag_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * indx); + +int mailimap_media_basic_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * indx); + +int mailimap_resp_cond_state_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * indx); + +int mailimap_resp_text_code_1_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * indx); + +int mailimap_resp_text_code_2_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * indx); + +int mailimap_section_msgtext_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * indx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/mailimap_oauth2.c b/Sources/libetpan/low-level/imap/mailimap_oauth2.c new file mode 100644 index 00000000..c8bf0f95 --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_oauth2.c @@ -0,0 +1,206 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "mailimap_oauth2.h" + +#include +#include + +#include "base64.h" +#include "mailimap_sender.h" +#include "mailimap_parser.h" +#include "mailimap.h" + +static int mailimap_oauth2_authenticate_send(mailimap * session, + const char * auth_user, + const char * access_token); + +LIBETPAN_EXPORT +int mailimap_oauth2_authenticate(mailimap * session, const char *auth_user, const char * access_token) +{ + struct mailimap_response * response; + int r; + int error_code; + size_t indx; + struct mailimap_continue_req * cont_req; + + if (session->imap_state != MAILIMAP_STATE_NON_AUTHENTICATED) + return MAILIMAP_ERROR_BAD_STATE; + + mailstream_set_privacy(session->imap_stream, 0); + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) { + mailstream_set_privacy(session->imap_stream, 1); + return r; + } + + r = mailimap_oauth2_authenticate_send(session, auth_user, access_token); + if (r != MAILIMAP_NO_ERROR) { + mailstream_set_privacy(session->imap_stream, 1); + return r; + } + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) { + mailstream_set_privacy(session->imap_stream, 1); + return r; + } + + if (mailstream_flush(session->imap_stream) == -1) { + mailstream_set_privacy(session->imap_stream, 1); + return MAILIMAP_ERROR_STREAM; + } + mailstream_set_privacy(session->imap_stream, 1); + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + indx = 0; + r = mailimap_continue_req_parse(session->imap_stream, + session->imap_stream_buffer, NULL, + &indx, &cont_req, + session->imap_progr_rate, session->imap_progr_fun); + if (r == MAILIMAP_NO_ERROR) { + mailimap_continue_req_free(cont_req); + + /* There's probably an error, send an empty line as acknowledgement. */ + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + if (mailstream_flush(session->imap_stream) == -1) { + return MAILIMAP_ERROR_STREAM; + } + } + else if (r == MAILIMAP_ERROR_PARSE) { + r = MAILIMAP_NO_ERROR; + } + + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + session->imap_state = MAILIMAP_STATE_AUTHENTICATED; + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_LOGIN; + } +} + +static int mailimap_oauth2_authenticate_send(mailimap * session, + const char * auth_user, + const char * access_token) +{ + int r; + char * ptr; + char * full_auth_string; + char * full_auth_string_b64; + size_t auth_user_len; + size_t access_token_len; + size_t full_auth_string_len; + int res; + + full_auth_string = NULL; + full_auth_string_b64 = NULL; + + /* Build client response string */ + auth_user_len = strlen(auth_user); + access_token_len = strlen(access_token); + full_auth_string_len = 5 + auth_user_len + 1 + 12 + access_token_len + 2; + full_auth_string = malloc(full_auth_string_len + 1); + if (full_auth_string == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + ptr = memcpy(full_auth_string, "user=", 5); + ptr = memcpy(ptr + 5, auth_user, auth_user_len); + ptr = memcpy(ptr + auth_user_len, "\1auth=Bearer ", 13); + ptr = memcpy(ptr + 13, access_token, access_token_len); + ptr = memcpy(ptr + access_token_len, "\1\1\0", 3); + + /* Convert to base64 */ + full_auth_string_b64 = encode_base64(full_auth_string, (int) full_auth_string_len); + if (full_auth_string_b64 == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + r = mailimap_token_send(session->imap_stream, "AUTHENTICATE"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + r = mailimap_space_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + r = mailimap_token_send(session->imap_stream, "XOAUTH2"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + r = mailimap_space_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + r = mailimap_token_send(session->imap_stream, full_auth_string_b64); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + res = MAILIMAP_NO_ERROR; + + free: + free(full_auth_string); + free(full_auth_string_b64); + return res; +} + +LIBETPAN_EXPORT +int mailimap_has_xoauth2(mailimap * session) +{ + return mailimap_has_authentication(session, "XOAUTH2"); +} diff --git a/Sources/libetpan/low-level/imap/mailimap_oauth2.h b/Sources/libetpan/low-level/imap/mailimap_oauth2.h new file mode 100644 index 00000000..6b154940 --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_oauth2.h @@ -0,0 +1,102 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILIMAP_OAUTH2_H + +#define MAILIMAP_OAUTH2_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mailimap_oauth2_authenticate() + Authenticates the client using using an oauth2 token. + To gather a deeper understanding of the OAuth2 aunthentication + process refer to: https://developers.google.com/gmail/xoauth2_protocol + For a quick start you may follow this brief set of steps: + 1. Set up a profile for your app in the Google + API Console: https://code.google.com/apis/console + 2. With your recently obtained client_id and secret + load the following URL (everything goes ina single line): + https://accounts.google.com/o/oauth2/auth?client_id=[YOUR_CLIENT_ID]& + redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob& + response_type=code&scope=https%3A%2F%2Fmail.google.com%2F%20email& + &access_type=offline + 3. The user most follow instructions to authorize application access + to Gmail. + 4. After the user hits the "Accept" button it will be redirected to another + page where the access token will be issued. + 5. Now from the app we need and authorization token, to get one we issue a POST request + the following URL: https://accounts.google.com/o/oauth2/token using these parameters: + client_id: This is the client id we got from step 1 + client_secret: Client secret as we got it from step 1 + code: This is the code we received in step 4 + redirect_uri: This is a redirect URI where the access token will be sent, for non + web applications this is usually urn:ietf:wg:oauth:2.0:oob (as we got from step 1) + grant_type: Always use the authorization_code parameter to retrieve an access and refresh tokens + 6. After step 5 completes we receive a JSON object similar to: + { + "access_token":"1/fFAGRNJru1FTz70BzhT3Zg", + "refresh_token":"1/fFAGRNJrufoiWEGIWEFJFJF", + "expires_in":3920, + "token_type":"Bearer" + } + The above output gives us the access_token, now we need to also retrieve the user's e-mail, + to do that we need to perform an HTTP GET request to Google's UserInfo API using this URL: + https://www.googleapis.com/oauth2/v1/userinfo?access_token=[YOUR_ACCESS_TOKEN] + this will return the following JSON output: + { + "id": "00000000000002222220000000", + "email": "email@example.com", + "verified_email": true + } + @param session IMAP session + @param auth_user Authentication user (tipically an e-mail address, depends on server) + @param access_token OAuth2 access token + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +LIBETPAN_EXPORT +int mailimap_oauth2_authenticate(mailimap * session, const char * auth_user, + const char * access_token); + +LIBETPAN_EXPORT +int mailimap_has_xoauth2(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Sources/libetpan/low-level/imap/mailimap_parser.c b/Sources/libetpan/low-level/imap/mailimap_parser.c new file mode 100644 index 00000000..06fb3f15 --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_parser.c @@ -0,0 +1,11238 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_parser.c,v 1.74 2011/07/13 09:28:36 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +#include "mailstream.h" +#include "mailimap_keywords.h" +#include "mailimap_parser.h" +#include "mailimap_extension.h" +#include "mmapstring.h" +#include "mail.h" +#include "timeutils.h" + +#ifdef _WIN32 +# ifdef _MSC_VER +# include "win_etpan.h" +# endif +#endif + +#ifndef UNSTRICT_SYNTAX +#define UNSTRICT_SYNTAX +#endif + +/* + Document: internet-drafts/draft-crispin-imapv-15.txt + RFC 2060 (IMAP but rather used draft) + RFC 2234 for all token that are not defined such as ALPHA +*/ + + + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + + +typedef int mailimap_struct_parser_progress(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, void * result, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context); + +static int mailimap_address_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_address ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_addr_adl_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_addr_host_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_addr_mailbox_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_addr_name_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_auth_type_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_base64_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_body_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_body_extension_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_extension ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_body_ext_1part_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_ext_1part ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_body_ext_mpart_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_ext_mpart ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_body_fields_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_fields ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_body_fld_desc_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_body_fld_dsp_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_fld_dsp ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_body_fld_enc_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_fld_enc ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int mailimap_body_fld_id_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_body_fld_lang_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_fld_lang ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_body_fld_lines_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + uint32_t * result); + +static int mailimap_body_fld_loc_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_body_fld_md5_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_body_fld_octets_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + uint32_t * result); + +static int +mailimap_body_fld_param_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_body_fld_param ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_body_type_1part_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_type_1part ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_body_type_basic_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_type_basic ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_body_type_mpart_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_type_mpart ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_body_type_msg_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_type_msg ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_body_type_text_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_type_text ** + result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_capability_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_capability ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +/* +static gboolean mailimap_date_day_parse(mailstream * fd, + MMAPString * buffer, + guint32 * indx, + gint * result); +*/ +static int mailimap_date_day_fixed_parse(mailstream * fd, + MMAPString * buffer, + size_t * indx, + int * result); + +static int mailimap_date_month_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, int * result); + +/* +struct mailimap_date_text { + gint day; + gint month; + gint year; +}; + +static gboolean +mailimap_date_text_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + guint32 * indx, struct mailimap_date_text ** result); +static void mailimap_date_text_free(struct mailimap_date_text * date_text); +*/ + +static int mailimap_date_year_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, int * result); + +static int mailimap_date_time_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_date_time ** t, + size_t progr_rate, + progress_function * progr_fun); + +#ifndef UNSTRICT_SYNTAX +static int mailimap_digit_nz_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, int * result); +#endif + + +static int mailimap_envelope_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_envelope ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_env_bcc_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_env_bcc ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_env_cc_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_env_cc ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_env_date_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_env_from_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_env_from ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int mailimap_env_in_reply_to_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_env_message_id_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int +mailimap_env_reply_to_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_env_reply_to ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_env_sender_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_env_sender ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_env_subject_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_env_to_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_env_to ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int mailimap_flag_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_flag ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_flag_extension_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + char ** result, + size_t progr_rate, + progress_function * progr_fun); + + + + +static int +mailimap_flag_fetch_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_flag_fetch ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_flag_perm_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_flag_perm ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int mailimap_flag_keyword_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + char ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int mailimap_flag_list_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_flag_list ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_header_fld_name_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + char ** result, + size_t progr_rate, + progress_function * progr_fun); + + + + +static int +mailimap_header_list_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_header_list ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_literal_parse_progress(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context); + + +static int +mailimap_mailbox_data_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_mailbox_data ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_mbx_list_flags_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_mbx_list_flags ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_mbx_list_oflag_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_mbx_list_oflag ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int +mailimap_mbx_list_oflag_no_sflag_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_mbx_list_oflag ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int +mailimap_mbx_list_sflag_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + int * result); + + +static int +mailimap_media_basic_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_media_basic ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int +mailimap_media_message_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx); + +static int +mailimap_media_subtype_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_media_text_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int +mailimap_msg_att_parse_progress(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_msg_att ** result, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context); + + +static int +mailimap_msg_att_dynamic_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_msg_att_dynamic ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int +mailimap_msg_att_static_parse_progress(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_msg_att_static ** result, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context); + +static int +mailimap_quoted_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int +mailimap_quoted_specials_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char * result); + + + + +static int +mailimap_response_done_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_response_done ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int +mailimap_response_fatal_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_response_fatal ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_response_tagged_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_response_tagged ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_resp_cond_auth_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_resp_cond_auth ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int +mailimap_resp_cond_bye_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_resp_cond_bye ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_resp_cond_state_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_resp_cond_state ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_resp_text_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_resp_text ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_resp_text_code_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_resp_text_code ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_section_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_section ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_section_msgtext_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_section_msgtext ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_section_part_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_section_part ** result, + size_t progr_rate, + progress_function * progr_fun); + + + + +static int +mailimap_section_spec_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_section_spec ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_section_text_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_section_text ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int mailimap_tag_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_text_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_time_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + int * phour, int * pmin, int * psec); + +static int mailimap_zone_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, int * result); + +static int +mailimap_mailbox_gmail_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int +mailimap_response_data_parse_progress(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_response_data ** result, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context); + +static int mailimap_nstring_parse_progress(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context); + +static int +mailimap_string_parse_progress(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context); + +static int has_crlf(MMAPString * buffer, size_t index); + +static int mailimap_address_list_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + clist ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_envelope_parse_full(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_envelope ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_envelope_parse_workaround_qq_mail(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_envelope ** result, + size_t progr_rate, + progress_function * progr_fun); + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + + + + + +/* ******************** TOOLS **************************** */ + + +static int mailimap_unstrict_char_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char token) +{ + size_t cur_token; + int r; + + cur_token = * indx; + +#ifdef UNSTRICT_SYNTAX + /* can accept unstrict syntax */ + + mailimap_space_parse(fd, buffer, &cur_token); + if (token == ' ') { + * indx = cur_token; + return MAILIMAP_NO_ERROR; + } +#endif + + r = mailimap_char_parse(fd, buffer, &cur_token, token); + if (r != MAILIMAP_NO_ERROR) + return r; + + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_oparenth_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx) +{ + return mailimap_unstrict_char_parse(fd, buffer, parser_ctx, indx, '('); +} + +int mailimap_cparenth_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx) +{ + return mailimap_unstrict_char_parse(fd, buffer, parser_ctx, indx, ')'); +} + +static int mailimap_oaccolade_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx) +{ + return mailimap_unstrict_char_parse(fd, buffer, parser_ctx, indx, '{'); +} + +static int mailimap_caccolade_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx) +{ + return mailimap_unstrict_char_parse(fd, buffer, parser_ctx, indx, '}'); +} + +static int mailimap_plus_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx) +{ + return mailimap_unstrict_char_parse(fd, buffer, parser_ctx, indx, '+'); +} + +static int mailimap_minus_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx) +{ + return mailimap_unstrict_char_parse(fd, buffer, parser_ctx, indx, '-'); +} + +static int mailimap_star_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx) +{ + return mailimap_unstrict_char_parse(fd, buffer, parser_ctx, indx, '*'); +} + +static int mailimap_dot_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx) +{ + return mailimap_unstrict_char_parse(fd, buffer, parser_ctx, indx, '.'); +} + +int mailimap_colon_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx) +{ + return mailimap_unstrict_char_parse(fd, buffer, parser_ctx, indx, ':'); +} + +static int mailimap_lower_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx) +{ + return mailimap_unstrict_char_parse(fd, buffer, parser_ctx, indx, '<'); +} + +static int mailimap_greater_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx) +{ + return mailimap_unstrict_char_parse(fd, buffer, parser_ctx, indx, '>'); +} + +static int mailimap_obracket_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx) +{ + return mailimap_unstrict_char_parse(fd, buffer, parser_ctx, indx, '['); +} + +static int mailimap_cbracket_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx) +{ + return mailimap_unstrict_char_parse(fd, buffer, parser_ctx, indx, ']'); +} + +int mailimap_dquote_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx) +{ + return mailimap_char_parse(fd, buffer, indx, '\"'); +} + +static int mailimap_crlf_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx) +{ + size_t cur_token = * indx; + int r; + +#ifdef UNSTRICT_SYNTAX + mailimap_space_parse(fd, buffer, &cur_token); +#endif + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "\r\n"); + if (r == MAILIMAP_NO_ERROR) { + * indx = cur_token; + return MAILIMAP_NO_ERROR; + } + +#ifdef UNSTRICT_SYNTAX + r = mailimap_unstrict_char_parse(fd, buffer, parser_ctx, &cur_token, '\n'); + if (r == MAILIMAP_NO_ERROR) { + * indx = cur_token; + return MAILIMAP_NO_ERROR; + } +#endif + + return MAILIMAP_ERROR_PARSE; +} + +static int +mailimap_struct_multiple_parse_progress(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, clist ** result, + mailimap_struct_parser_progress * parser, + mailimap_struct_destructor * destructor, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context) +{ + clist * struct_list; + size_t cur_token; + void * value; + int r; + int res; + + cur_token = * indx; + + r = parser(fd, buffer, parser_ctx, &cur_token, &value, progr_rate, progr_fun, + body_progr_fun, items_progr_fun, context, msg_att_handler, msg_att_context); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + struct_list = clist_new(); + if (struct_list == NULL) { + destructor(value); + res = MAILIMAP_ERROR_MEMORY; + goto err; + } + + if (value != NULL) { + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMAP_ERROR_MEMORY; + goto free_list; + } + } + + while (1) { + r = parser(fd, buffer, parser_ctx, &cur_token, &value, progr_rate, progr_fun, + body_progr_fun, items_progr_fun, context, msg_att_handler, msg_att_context); + if (r == MAILIMAP_ERROR_PARSE) + break; + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list; + } + + if (value != NULL) { + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMAP_ERROR_MEMORY; + goto free_list; + } + } + } + + * result = struct_list; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + +free_list: + clist_foreach(struct_list, (clist_func) destructor, NULL); + clist_free(struct_list); +err: + return res; +} + +int +mailimap_struct_multiple_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, clist ** result, + mailimap_struct_parser * parser, + mailimap_struct_destructor * destructor, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * struct_list; + size_t cur_token; + void * value; + int r; + int res; + + cur_token = * indx; + + r = parser(fd, buffer, parser_ctx, &cur_token, &value, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + struct_list = clist_new(); + if (struct_list == NULL) { + destructor(value); + res = MAILIMAP_ERROR_MEMORY; + goto err; + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMAP_ERROR_MEMORY; + goto free_list; + } + + while (1) { + r = parser(fd, buffer, parser_ctx, &cur_token, &value, progr_rate, progr_fun); + if (r == MAILIMAP_ERROR_PARSE) + break; + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMAP_ERROR_MEMORY; + goto free_list; + } + } + + * result = struct_list; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free_list: + clist_foreach(struct_list, (clist_func) destructor, NULL); + clist_free(struct_list); + err: + return res; +} + +int +mailimap_struct_list_parse_progress(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, clist ** result, + char symbol, + mailimap_struct_parser_progress * parser, + mailimap_struct_destructor * destructor, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context) +{ + clist * struct_list; + size_t cur_token; + void * value; + size_t final_token; + int r; + int res; + + cur_token = * indx; + struct_list = NULL; + + r = parser(fd, buffer, parser_ctx, &cur_token, &value, progr_rate, progr_fun, + body_progr_fun, items_progr_fun, context, msg_att_handler, msg_att_context); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + struct_list = clist_new(); + if (struct_list == NULL) { + destructor(value); + res = MAILIMAP_ERROR_MEMORY; + goto err; + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMAP_ERROR_MEMORY; + goto free_list; + } + + final_token = cur_token; + + while (1) { + r = mailimap_unstrict_char_parse(fd, buffer, parser_ctx, &cur_token, symbol); + if (r == MAILIMAP_ERROR_PARSE) + break; + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list; + } + + r = parser(fd, buffer, parser_ctx, &cur_token, &value, progr_rate, progr_fun, + body_progr_fun, items_progr_fun, context, msg_att_handler, msg_att_context); + if (r == MAILIMAP_ERROR_PARSE) + break; + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMAP_ERROR_MEMORY; + goto free_list; + } + + final_token = cur_token; + } + + * result = struct_list; + * indx = final_token; + + return MAILIMAP_NO_ERROR; + +free_list: + clist_foreach(struct_list, (clist_func) destructor, NULL); + clist_free(struct_list); +err: + return res; +} + +int +mailimap_struct_list_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, clist ** result, + char symbol, + mailimap_struct_parser * parser, + mailimap_struct_destructor * destructor, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * struct_list; + size_t cur_token; + void * value; + size_t final_token; + int r; + int res; + + cur_token = * indx; + struct_list = NULL; + + r = parser(fd, buffer, parser_ctx, &cur_token, &value, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + struct_list = clist_new(); + if (struct_list == NULL) { + destructor(value); + res = MAILIMAP_ERROR_MEMORY; + goto err; + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMAP_ERROR_MEMORY; + goto free_list; + } + + final_token = cur_token; + + while (1) { + r = mailimap_unstrict_char_parse(fd, buffer, parser_ctx, &cur_token, symbol); + if (r == MAILIMAP_ERROR_PARSE) + break; + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list; + } + + r = parser(fd, buffer, parser_ctx, &cur_token, &value, progr_rate, progr_fun); + if (r == MAILIMAP_ERROR_PARSE) + break; + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMAP_ERROR_MEMORY; + goto free_list; + } + + final_token = cur_token; + } + + * result = struct_list; + * indx = final_token; + + return MAILIMAP_NO_ERROR; + + free_list: + clist_foreach(struct_list, (clist_func) destructor, NULL); + clist_free(struct_list); + err: + return res; +} + +int +mailimap_struct_spaced_list_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, clist ** result, + mailimap_struct_parser * parser, + mailimap_struct_destructor * destructor, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_struct_list_parse(fd, buffer, parser_ctx, indx, result, + ' ', parser, destructor, + progr_rate, progr_fun); +} + +static int +mailimap_struct_spaced_list_parse_progress(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, clist ** result, + mailimap_struct_parser_progress * parser, + mailimap_struct_destructor * destructor, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context) +{ + return mailimap_struct_list_parse_progress(fd, buffer, parser_ctx, indx, result, + ' ', parser, destructor, + progr_rate, progr_fun, + body_progr_fun, items_progr_fun, context, + msg_att_handler, msg_att_context); +} + + +static int +mailimap_custom_string_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + int (* is_custom_char)(char)) +{ + size_t begin; + size_t end; + char * gstr; + + begin = * indx; + +#ifdef UNSTRICT_SYNTAX + mailimap_space_parse(fd, buffer, &begin); +#endif + + end = begin; + + while (is_custom_char(buffer->str[end])) + end ++; + + if (end != begin) { + gstr = malloc(end - begin + 1); + if (gstr == NULL) + return MAILIMAP_ERROR_MEMORY; + + strncpy(gstr, buffer->str + begin, end - begin); + gstr[end - begin] = '\0'; + + * indx = end; + * result = gstr; + return MAILIMAP_NO_ERROR; + } + else + return MAILIMAP_ERROR_PARSE; +} + + + +int +mailimap_nz_number_alloc_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + uint32_t ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + uint32_t number; + uint32_t * number_alloc; + size_t cur_token; + int r; + + cur_token = * indx; + + r = mailimap_nz_number_parse(fd, buffer, parser_ctx, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) + return r; + + number_alloc = mailimap_number_alloc_new(number); + if (number_alloc == NULL) + return MAILIMAP_ERROR_MEMORY; + + * indx = cur_token; + * result = number_alloc; + + return MAILIMAP_NO_ERROR; +} + + +static int is_ctl(char ch) +{ + unsigned char uch = (unsigned char) ch; + + return (uch <= 0x1F); +} + +static int is_char(char ch) +{ +#ifdef UNSTRICT_SYNTAX + return (ch != 0); +#else + unsigned char uch = ch; + + return (uch >= 0x01) && (uch <= 0x7f); +#endif +} + +static int is_alpha(char ch) +{ + return ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && (ch <= 'z'))); +} + +static int is_digit(char ch) +{ + return (ch >= '0') && (ch <= '9'); +} + +static int mailimap_digit_parse(mailstream * fd, MMAPString * buffer, + size_t * indx, int * result) +{ + size_t cur_token; + + cur_token = * indx; + + if (is_digit(buffer->str[cur_token])) { + * result = buffer->str[cur_token] - '0'; + cur_token ++; + * indx = cur_token; + return MAILIMAP_NO_ERROR; + } + else + return MAILIMAP_ERROR_PARSE; +} + + +/* ******************** parser **************************** */ + +/* + address = "(" addr-name SP addr-adl SP addr-mailbox SP + addr-host ")" +*/ + +static int mailimap_address_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_address ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * addr_name; + char * addr_adl; + char * addr_mailbox; + char * addr_host; + struct mailimap_address * addr; + int r; + int res; + + cur_token = * indx; + + addr_name = NULL; + addr_adl = NULL; + addr_mailbox = NULL; + addr_host = NULL; + + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_addr_name_parse(fd, buffer, parser_ctx, &cur_token, &addr_name, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto addr_name_free; + } + + r = mailimap_addr_adl_parse(fd, buffer, parser_ctx, &cur_token, &addr_adl, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto addr_name_free; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto addr_adl_free; + } + + r = mailimap_addr_mailbox_parse(fd, buffer, parser_ctx, &cur_token, &addr_mailbox, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto addr_adl_free; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto addr_mailbox_free; + } + + r = mailimap_addr_host_parse(fd, buffer, parser_ctx, &cur_token, &addr_host, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto addr_mailbox_free; + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto addr_host_free; + } + + addr = mailimap_address_new(addr_name, addr_adl, addr_mailbox, addr_host); + + if (addr == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto addr_host_free; + } + + * result = addr; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + addr_host_free: + mailimap_addr_host_free(addr_host); + addr_mailbox_free: + mailimap_addr_mailbox_free(addr_mailbox); + addr_adl_free: + mailimap_addr_adl_free(addr_adl); + addr_name_free: + mailimap_addr_name_free(addr_name); + err: + return res; +} + +/* + addr-adl = nstring + ; Holds route from [RFC-822] route-addr if + ; non-NIL +*/ + +static int mailimap_addr_adl_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, parser_ctx, indx, result, NULL, + progr_rate, progr_fun); +} + +/* + addr-host = nstring + ; NIL indicates [RFC-822] group syntax. + ; Otherwise, holds [RFC-822] domain name +*/ + +static int mailimap_addr_host_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int r; + + /* workaround for qq.com IMAP Server. */ + r = mailimap_token_case_insensitive_parse(fd, buffer, indx, "\"qq.com\\\""); + if (r == MAILIMAP_NO_ERROR) { + return r; + } + + return mailimap_nstring_parse(fd, buffer, parser_ctx, indx, result, NULL, + progr_rate, progr_fun); +} + +/* + addr-mailbox = nstring + ; NIL indicates end of [RFC-822] group; if + ; non-NIL and addr-host is NIL, holds + ; [RFC-822] group name. + ; Otherwise, holds [RFC-822] local-part + ; after removing [RFC-822] quoting + */ + +static int mailimap_addr_mailbox_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, parser_ctx, indx, result, NULL, + progr_rate, progr_fun); +} + + +/* + addr-name = nstring + ; If non-NIL, holds phrase from [RFC-822] + ; mailbox after removing [RFC-822] quoting +*/ + +static int mailimap_addr_name_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, parser_ctx, indx, result, NULL, + progr_rate, progr_fun); +} + + +/* + NOT IMPLEMENTED + append = "APPEND" SP mailbox [SP flag-list] [SP date-time] SP + literal +*/ + +/* + astring = 1*ASTRING-CHAR / string +*/ + +static int is_astring_char(char ch); + +static int +mailimap_atom_astring_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_custom_string_parse(fd, buffer, parser_ctx, indx, result, + is_astring_char); +} + +int +mailimap_astring_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * astring; + int r; + + cur_token = * indx; + + r = mailimap_atom_astring_parse(fd, buffer, parser_ctx, &cur_token, &astring, + progr_rate, progr_fun); + switch (r) { + case MAILIMAP_NO_ERROR: + break; + + case MAILIMAP_ERROR_PARSE: + r = mailimap_string_parse(fd, buffer, parser_ctx, &cur_token, &astring, NULL, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + break; + + default: + return r; + } + + * result = astring; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + ASTRING-CHAR = ATOM-CHAR / resp-specials +*/ + +static int is_atom_char(char ch); +static int is_resp_specials(char ch); + +static int is_astring_char(char ch) +{ + if (is_atom_char(ch)) + return TRUE; + if (is_resp_specials(ch)) + return TRUE; + return FALSE; +} + +/* + atom = 1*ATOM-CHAR +*/ + +int mailimap_atom_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_custom_string_parse(fd, buffer, parser_ctx, indx, result, + is_atom_char); +} + +/* + ATOM-CHAR = +*/ + +static int is_atom_specials(char ch); + +static int is_atom_char(char ch) +{ + if (is_atom_specials(ch)) + return FALSE; + + return is_char(ch); +} + +/* + atom-specials = "(" / ")" / "{" / SP / CTL / list-wildcards / + quoted-specials / resp-specials + +no "}" because there is no need (Mark Crispin) +*/ + +static int is_quoted_specials(char ch); +static int is_list_wildcards(char ch); + +static int is_atom_specials(char ch) +{ + switch (ch) { + case '(': + case ')': + case '{': + case ' ': + return TRUE; + }; + if (is_ctl(ch)) + return TRUE; + if (is_list_wildcards(ch)) + return TRUE; + if (is_resp_specials(ch)) + return TRUE; + + return is_quoted_specials(ch); +} + +/* + NOT IMPLEMENTED + authenticate = "AUTHENTICATE" SP auth-type *(CRLF base64) +*/ + +/* + auth-type = atom + ; Defined by [SASL] +*/ + +static int mailimap_auth_type_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_atom_parse(fd, buffer, parser_ctx, indx, result, + progr_rate, progr_fun); +} + +/* + base64 = *(4base64-char) [base64-terminal] +*/ + +static int is_base64_4char(char * str); +static int is_base64_terminal(char * str); + +static int mailimap_base64_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t begin; + size_t end; + char * gstr; + + begin = * indx; + end = begin; + + while (is_base64_4char(buffer->str + end)) + end += 4; + if (is_base64_terminal(buffer->str + end)) + end += 4; + + if (begin == end) + return MAILIMAP_ERROR_PARSE; + + gstr = malloc(end - begin + 1); + if (gstr == NULL) + return MAILIMAP_ERROR_MEMORY; + strncpy(gstr, buffer->str + begin, end - begin); + gstr[end - begin] = '\0'; + + * result = gstr; + * indx = end; + + return MAILIMAP_NO_ERROR; +} + +/* + base64-char = ALPHA / DIGIT / "+" / "/" + ; Case-sensitive +*/ + +static int is_base64_char(char ch) +{ + return (is_alpha(ch) || is_digit(ch) || ch == '+' || ch == '/'); +} + +static int is_base64_4char(char * str) +{ + size_t i; + + for (i = 0 ; i < 4 ; i++) + if (!is_base64_char(str[i])) + return FALSE; + return TRUE; +} + +/* + base64-terminal = (2base64-char "==") / (3base64-char "=") +*/ + +static int is_base64_terminal(char * str) +{ + if (str[0] == 0) + return FALSE; + if (str[1] == 0) + return FALSE; + if (str[2] == 0) + return FALSE; + if (str[3] == 0) + return FALSE; + + if (is_base64_char(str[0]) && is_base64_char(str[1]) + && str[2] == '=' && str[3] == '=') + return TRUE; + if (is_base64_char(str[0]) && is_base64_char(str[1]) + && is_base64_char(str[2]) && str[3] == '=') + return TRUE; + return FALSE; +} + + +/* + body = "(" (body-type-1part / body-type-mpart) ")" +*/ + +static int mailimap_body_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_body_type_1part * body_type_1part; + struct mailimap_body_type_mpart * body_type_mpart; + struct mailimap_body * body; + size_t cur_token; + int type; + int r; + int res; + + cur_token = * indx; + + body_type_1part = NULL; + body_type_mpart = NULL; + + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + type = MAILIMAP_BODY_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_body_type_1part_parse(fd, buffer, parser_ctx, &cur_token, &body_type_1part, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_1PART; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_body_type_mpart_parse(fd, buffer, parser_ctx, &cur_token, + &body_type_mpart, + progr_rate, progr_fun); + + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_MPART; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + body = mailimap_body_new(type, body_type_1part, body_type_mpart); + if (body == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = body; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (body_type_1part) + mailimap_body_type_1part_free(body_type_1part); + if (body_type_mpart) + mailimap_body_type_mpart_free(body_type_mpart); + err: + return res; +} + +/* + body-extension = nstring / number / + "(" body-extension *(SP body-extension) ")" + ; Future expansion. Client implementations + ; MUST accept body-extension fields. Server + ; implementations MUST NOT generate + ; body-extension fields except as defined by + ; future standard or standards-track + ; revisions of this specification. +*/ + +/* + "(" body-extension *(SP body-extension) ")" +*/ + +static int +mailimap_body_ext_list_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + clist ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * list; + int r; + int res; + + cur_token = * indx; + + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, + &cur_token, &list, + (mailimap_struct_parser * ) + mailimap_body_extension_parse, + (mailimap_struct_destructor * ) + mailimap_body_extension_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list; + } + + * indx = cur_token; + * result = list; + + return MAILIMAP_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimap_body_extension_free, NULL); + clist_free(list); + err: + return res; +} + +/* + body-extension = nstring / number / + "(" body-extension *(SP body-extension) ")" + ; Future expansion. Client implementations + ; MUST accept body-extension fields. Server + ; implementations MUST NOT generate + ; body-extension fields except as defined by + ; future standard or standards-track + ; revisions of this specification. +*/ + +static int +mailimap_body_extension_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_extension ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + uint32_t number; + char * nstring; + clist * body_extension_list; + struct mailimap_body_extension * body_extension; + int type; + int r; + int res; + + cur_token = * indx; + + nstring = NULL; + number = 0; + body_extension_list = NULL; + type = MAILIMAP_BODY_EXTENSION_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_nstring_parse(fd, buffer, parser_ctx, &cur_token, &nstring, NULL, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_EXTENSION_NSTRING; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_EXTENSION_NUMBER; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_body_ext_list_parse(fd, buffer, parser_ctx, &cur_token, + &body_extension_list, + progr_rate, progr_fun); + + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_EXTENSION_LIST; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + body_extension = mailimap_body_extension_new(type, nstring, number, + body_extension_list); + + if (body_extension == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = body_extension; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (nstring != NULL) + mailimap_nstring_free(nstring); + if (body_extension_list) { + clist_foreach(body_extension_list, + (clist_func) mailimap_body_extension_free, + NULL); + clist_free(body_extension_list); + } + err: + return res; +} + +/* + body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] + ; MUST NOT be returned on non-extensible + ; "BODY" fetch +*/ + +/* + *(SP body-extension) +*/ + +static int +mailimap_body_ext_1part_4_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + clist ** body_ext_list, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int r; + + cur_token = * indx; + * body_ext_list = NULL; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, &cur_token, + body_ext_list, + (mailimap_struct_parser *) + mailimap_body_extension_parse, + (mailimap_struct_destructor *) + mailimap_body_extension_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* +[SP body-fld-loc *(SP body-extension)]]] +*/ + +static int +mailimap_body_ext_1part_3_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + char ** fld_loc, + clist ** body_ext_list, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int r; + + cur_token = * indx; + * fld_loc = NULL; + * body_ext_list = NULL; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_body_fld_loc_parse(fd, buffer, parser_ctx, &cur_token, fld_loc, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_body_ext_1part_4_parse(fd, buffer, parser_ctx, &cur_token, + body_ext_list, progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; + + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + [SP body-fld-lang + *(SP body-extension)]] +*/ + +static int +mailimap_body_ext_1part_2_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_fld_lang ** fld_lang, + char ** fld_loc, + clist ** body_ext_list, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int r; + + cur_token = * indx; + * fld_lang = NULL; + * fld_loc = NULL; + * body_ext_list = NULL; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_body_fld_lang_parse(fd, buffer, parser_ctx, &cur_token, fld_lang, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_body_ext_1part_3_parse(fd, buffer, parser_ctx, &cur_token, + fld_loc, body_ext_list, progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; + + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] +*/ + +static int +mailimap_body_ext_1part_1_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_fld_dsp ** fld_dsp, + struct mailimap_body_fld_lang ** fld_lang, + char ** fld_loc, + clist ** body_ext_list, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int r; + + cur_token = * indx; + * fld_dsp = NULL; + * fld_lang = NULL; + * fld_loc = NULL; + * body_ext_list = NULL; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_body_fld_dsp_parse(fd, buffer, parser_ctx, &cur_token, fld_dsp, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_body_ext_1part_2_parse(fd, buffer, parser_ctx, &cur_token, + fld_lang, fld_loc, body_ext_list, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; + + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] + ; MUST NOT be returned on non-extensible + ; "BODY" fetch +*/ + +static int +mailimap_body_ext_1part_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_ext_1part ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + + char * fld_md5; + struct mailimap_body_fld_dsp * fld_dsp; + struct mailimap_body_fld_lang * fld_lang; + char * fld_loc; + clist * body_ext_list; + int r; + int res; + + struct mailimap_body_ext_1part * ext_1part; + + cur_token = * indx; + + fld_md5 = NULL; + fld_dsp = NULL; + fld_lang = NULL; + fld_loc = NULL; + body_ext_list = NULL; + + r = mailimap_body_fld_md5_parse(fd, buffer, parser_ctx, &cur_token, &fld_md5, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_body_ext_1part_1_parse(fd, buffer, parser_ctx, &cur_token, + &fld_dsp, + &fld_lang, + &fld_loc, + &body_ext_list, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto free; + } + + ext_1part = mailimap_body_ext_1part_new(fld_md5, fld_dsp, fld_lang, fld_loc, + body_ext_list); + + if (ext_1part == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = ext_1part; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (body_ext_list) { + clist_foreach(body_ext_list, (clist_func) mailimap_body_extension_free, + NULL); + clist_free(body_ext_list); + } + mailimap_body_fld_loc_free(fld_loc); + if (fld_lang) + mailimap_body_fld_lang_free(fld_lang); + if (fld_dsp) + mailimap_body_fld_dsp_free(fld_dsp); + mailimap_body_fld_md5_free(fld_md5); + err: + return res; +} + + +/* + body-ext-mpart = body-fld-param [SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] + ; MUST NOT be returned on non-extensible + ; "BODY" fetch +*/ + +static int +mailimap_body_ext_mpart_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_ext_mpart ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + + struct mailimap_body_fld_dsp * fld_dsp; + struct mailimap_body_fld_lang * fld_lang; + char * fld_loc; + struct mailimap_body_fld_param * fld_param; + clist * body_ext_list; + + struct mailimap_body_ext_mpart * ext_mpart; + int r; + int res; + + cur_token = * indx; + + fld_param = NULL; + fld_dsp = NULL; + fld_lang = NULL; + fld_loc = NULL; + body_ext_list = NULL; + + r = mailimap_body_fld_param_parse(fd, buffer, parser_ctx, &cur_token, &fld_param, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_body_ext_1part_1_parse(fd, buffer, parser_ctx, &cur_token, + &fld_dsp, + &fld_lang, + &fld_loc, + &body_ext_list, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto free; + } + + ext_mpart = mailimap_body_ext_mpart_new(fld_param, fld_dsp, fld_lang, fld_loc, + body_ext_list); + if (ext_mpart == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = ext_mpart; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (body_ext_list) { + clist_foreach(body_ext_list, (clist_func) mailimap_body_extension_free, + NULL); + clist_free(body_ext_list); + } + mailimap_body_fld_loc_free(fld_loc); + if (fld_lang) + mailimap_body_fld_lang_free(fld_lang); + if (fld_dsp) + mailimap_body_fld_dsp_free(fld_dsp); + if (fld_param != NULL) + mailimap_body_fld_param_free(fld_param); + err: + return res; +} + +/* + body-fields = body-fld-param SP body-fld-id SP body-fld-desc SP + body-fld-enc SP body-fld-octets +*/ + +static int +mailimap_body_fields_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_fields ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_body_fields * body_fields; + size_t cur_token; + struct mailimap_body_fld_param * body_fld_param; + char * body_fld_id; + char * body_fld_desc; + struct mailimap_body_fld_enc * body_fld_enc; + uint32_t body_fld_octets; + int r; + int res; + + body_fld_param = NULL; + body_fld_id = NULL; + body_fld_desc = NULL; + body_fld_enc = NULL; + body_fld_octets = 0; + + cur_token = * indx; + + r = mailimap_body_fld_param_parse(fd, buffer, parser_ctx, &cur_token, &body_fld_param, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto fld_param_free; + } + + r = mailimap_body_fld_id_parse(fd, buffer, parser_ctx, &cur_token, &body_fld_id, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto fld_param_free; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto fld_id_free; + } + + r = mailimap_body_fld_desc_parse(fd, buffer, parser_ctx, &cur_token, &body_fld_desc, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto fld_id_free; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto fld_desc_free; + } + + r = mailimap_body_fld_enc_parse(fd, buffer, parser_ctx, &cur_token, &body_fld_enc, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto fld_desc_free; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto fld_enc_free; + } + + r = mailimap_body_fld_octets_parse(fd, buffer, parser_ctx, &cur_token, + &body_fld_octets); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto fld_enc_free; + } + + body_fields = mailimap_body_fields_new(body_fld_param, + body_fld_id, + body_fld_desc, + body_fld_enc, + body_fld_octets); + if (body_fields == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto fld_enc_free; + } + + * result = body_fields; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + fld_enc_free: + mailimap_body_fld_enc_free(body_fld_enc); + fld_desc_free: + mailimap_body_fld_desc_free(body_fld_desc); + fld_id_free: + mailimap_body_fld_id_free(body_fld_id); + fld_param_free: + if (body_fld_param != NULL) + mailimap_body_fld_param_free(body_fld_param); + err: + return res; +} + +/* + body-fld-desc = nstring +*/ + +static int mailimap_body_fld_desc_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, parser_ctx, indx, result, NULL, + progr_rate, progr_fun); +} + +/* + body-fld-dsp = "(" string SP body-fld-param ")" / nil +*/ + +static int +mailimap_body_fld_dsp_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_fld_dsp ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * name; + struct mailimap_body_fld_param * body_fld_param; + struct mailimap_body_fld_dsp * body_fld_dsp; + int res; + int r; + + cur_token = * indx; + name = NULL; + body_fld_param = NULL; + + r = mailimap_nil_parse(fd, buffer, parser_ctx, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + * result = NULL; + * indx = cur_token; + return MAILIMAP_NO_ERROR; + } + + if (r != MAILIMAP_ERROR_PARSE) { + res = r; + goto err; + } + + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + // workaround for exchange + r = mailimap_string_parse(fd, buffer, parser_ctx, &cur_token, &name, NULL, + + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto string_free; + } + + r = mailimap_body_fld_param_parse(fd, buffer, parser_ctx, &cur_token, + &body_fld_param, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto string_free; + } + + goto create_body_fld_dsp; + } + + r = mailimap_string_parse(fd, buffer, parser_ctx, &cur_token, &name, NULL, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + /* workaround for IMAPrev1 Citadel */ + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto string_free; + } + + body_fld_param = NULL; + + goto create_body_fld_dsp; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto string_free; + } + + r = mailimap_body_fld_param_parse(fd, buffer, parser_ctx, &cur_token, + &body_fld_param, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto string_free; + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto string_free; + } + +create_body_fld_dsp: + body_fld_dsp = mailimap_body_fld_dsp_new(name, body_fld_param); + if (body_fld_dsp == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto fld_param_free; + } + + * indx = cur_token; + * result = body_fld_dsp; + + return MAILIMAP_NO_ERROR; + + fld_param_free: + if (body_fld_param != NULL) + mailimap_body_fld_param_free(body_fld_param); + string_free: + mailimap_string_free(name); + err: + return res; +} + +/* + body-fld-enc = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/ + "QUOTED-PRINTABLE") DQUOTE) / string +*/ + +static inline int +mailimap_body_fld_known_enc_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + int * result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int type; + int r; + int res; + + cur_token = * indx; + + r = mailimap_dquote_parse(fd, buffer, parser_ctx, &cur_token); + if (r == MAILIMAP_ERROR_PARSE) { + /* workaround for exchange */ + type = mailimap_encoding_get_token_value(fd, buffer, &cur_token); + + if (type == -1) { + res = MAILIMAP_ERROR_PARSE; + goto err; + } + + * result = type; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + } + else if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + type = mailimap_encoding_get_token_value(fd, buffer, &cur_token); + + if (type == -1) { + res = MAILIMAP_ERROR_PARSE; + goto err; + } + + r = mailimap_dquote_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + * result = type; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + err: + return res; +} + +static int +mailimap_body_fld_enc_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_fld_enc ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int type; + char * value; + struct mailimap_body_fld_enc * body_fld_enc; + int r; + int res; + + cur_token = * indx; + + r = mailimap_body_fld_known_enc_parse(fd, buffer, parser_ctx, &cur_token, + &type, progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) { + value = NULL; + } + else if (r == MAILIMAP_ERROR_PARSE) { + type = MAILIMAP_BODY_FLD_ENC_OTHER; + + r = mailimap_nstring_parse(fd, buffer, parser_ctx, &cur_token, &value, NULL, + progr_rate, progr_fun); + if (r == MAILIMAP_ERROR_PARSE) { + /* workaround for exchange */ + r = mailimap_astring_parse(fd, buffer, parser_ctx, &cur_token, &value, + progr_rate, progr_fun); + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + if (value == NULL) { + type = MAILIMAP_BODY_FLD_ENC_8BIT; + } + } + else { + res = r; + goto err; + } + + body_fld_enc = mailimap_body_fld_enc_new(type, value); + if (body_fld_enc == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto value_free; + } + + * result = body_fld_enc; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + value_free: + if (value) + mailimap_string_free(value); + err: + return res; +} + +/* + body-fld-id = nstring +*/ + +static int mailimap_body_fld_id_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int r; + + r = mailimap_nstring_parse(fd, buffer, parser_ctx, indx, result, NULL, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + return MAILIMAP_NO_ERROR; + + r = mailimap_atom_parse(fd, buffer, parser_ctx, indx, result, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + return MAILIMAP_NO_ERROR; + + return r; +} + + +/* + body-fld-lang = nstring / "(" string *(SP string) ")" +*/ + +/* +"(" string *(SP string) ")" +*/ + +static int +mailimap_body_fld_lang_list_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, clist ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * list; + int r; + int res; + + cur_token = * indx; + + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + list = clist_new(); + if (list == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto err; + } + + while (1) { + char * elt; + + mailimap_space_parse(fd, buffer, &cur_token); + + r = mailimap_string_parse(fd, buffer, parser_ctx, &cur_token, &elt, NULL, + progr_rate, progr_fun); + if (r == MAILIMAP_ERROR_PARSE) + break; + else if (r == MAILIMAP_NO_ERROR) { + r = clist_append(list, elt); + if (r < 0) { + mailimap_string_free(elt); + res = r; + goto list_free; + } + } + else { + res = r; + goto list_free; + } + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto list_free; + } + + * indx = cur_token; + * result = list; + + return MAILIMAP_NO_ERROR; + + list_free: + clist_foreach(list, (clist_func) mailimap_string_free, NULL); + clist_free(list); + err: + return res; +} + +/* + body-fld-lang = nstring / "(" string *(SP string) ")" +*/ + +static int +mailimap_body_fld_lang_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_fld_lang ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + char * value; + clist * list; + struct mailimap_body_fld_lang * fld_lang; + int type; + int r; + int res; + + size_t cur_token; + + cur_token = * indx; + + value = NULL; + list = NULL; + type = MAILIMAP_BODY_FLD_LANG_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_nstring_parse(fd, buffer, parser_ctx, &cur_token, &value, NULL, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_FLD_LANG_SINGLE; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_body_fld_lang_list_parse(fd, buffer, parser_ctx, &cur_token, &list, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_FLD_LANG_LIST; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + fld_lang = mailimap_body_fld_lang_new(type, value, list); + if (fld_lang == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * indx = cur_token; + * result = fld_lang; + + return MAILIMAP_NO_ERROR; + + free: + if (value) + mailimap_nstring_free(value); + if (list) { + clist_foreach(list, (clist_func) mailimap_string_free, NULL); + clist_free(list); + } + err: + return res; +} + +/* + body-fld-lines = number +*/ + +static int mailimap_body_fld_lines_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + uint32_t * result) +{ + return mailimap_number_parse(fd, buffer, indx, result); +} + +/* + body-fld-md5 = nstring +*/ + +static int mailimap_body_fld_md5_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int r; + uint32_t value; + size_t cur_token; + char * md5_value; + + r = mailimap_nstring_parse(fd, buffer, parser_ctx, indx, result, NULL, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + return r; + + cur_token = * indx; + /* workaround for google IMAP */ + r = mailimap_number_parse(fd, buffer, &cur_token, &value); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + r = mailimap_nstring_parse(fd, buffer, parser_ctx, &cur_token, &md5_value, NULL, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + * indx = cur_token; + * result = md5_value; + + return MAILIMAP_NO_ERROR; +} + +static int mailimap_body_fld_loc_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, parser_ctx, indx, result, NULL, + progr_rate, progr_fun); +} + +/* + body-fld-octets = number +*/ + +static int mailimap_body_fld_octets_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + uint32_t * result) +{ + int r; + + r = mailimap_number_parse(fd, buffer, indx, result); + if (r == MAILIMAP_NO_ERROR) + return r; + + // workaround for Microsoft Exchange: it can provides -1 as octets + r = mailimap_token_case_insensitive_parse(fd, buffer, indx, "-1"); + if (r == MAILIMAP_NO_ERROR) { + * result = 0; + return MAILIMAP_NO_ERROR; + } + + // workaround for mbox mail for mac + r = mailimap_nil_parse(fd, buffer, parser_ctx, indx); + if (r == MAILIMAP_NO_ERROR) { + * result = 0; + return MAILIMAP_NO_ERROR; + } + + return MAILIMAP_ERROR_PARSE; +} + +/* + body-fld-param = "(" string SP string *(SP string SP string) ")" / nil +*/ + +/* + string SP string +*/ + +static int +mailimap_single_body_fld_param_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_single_body_fld_param ** + result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_single_body_fld_param * param; + char * name; + char * value; + size_t cur_token; + int r; + int res; + int workaround_used; + + cur_token = * indx; + + name = NULL; + value = NULL; + + r = mailimap_string_parse(fd, buffer, parser_ctx, &cur_token, &name, NULL, + progr_rate, progr_fun); + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_astring_parse(fd, buffer, parser_ctx, &cur_token, &name, + progr_rate, progr_fun); + } + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_name; + } + /* workaround for Lotus Domino - parse "3D"Windows-1252"" */ + workaround_used = 0; + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "\"3D\"Windows-1252\"\""); + if (r == MAILIMAP_NO_ERROR) { + workaround_used = 1; + value = strdup("\"3D\"Windows-1252\"\""); + if (value == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_name; + } + } + + if (!workaround_used) { + // also parse NIL to workaround Exchange issue + r = mailimap_nstring_parse(fd, buffer, parser_ctx, &cur_token, &value, NULL, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_name; + } + + if (value == NULL) { + value = strdup(""); + if (value == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_name; + } + } + } + + param = mailimap_single_body_fld_param_new(name, value); + if (param == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_value; + } + + * result = param; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free_value: + mailimap_string_free(name); + free_name: + mailimap_string_free(value); + err: + return res; +} + +static void mailimap_broken_single_body_fld_param_string_free(char * value) +{ + // do nothing +} + +static int +mailimap_broken_single_body_fld_param_string_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + char * value; + int r; + size_t cur_token; + + cur_token = * indx; + + r = mailimap_string_parse(fd, buffer, parser_ctx, &cur_token, &value, NULL, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) { + mailimap_string_free(value); + * result = ""; + * indx = cur_token; + return r; + } + + r = mailimap_astring_parse(fd, buffer, parser_ctx, &cur_token, &value, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) { + mailimap_astring_free(value); + * result = ""; + * indx = cur_token; + return r; + } + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "\"3D\"Windows-1252\"\""); + if (r == MAILIMAP_NO_ERROR) { + * result = ""; + * indx = cur_token; + return r; + } + + r = mailimap_nstring_parse(fd, buffer, parser_ctx, &cur_token, &value, NULL, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) { + mailimap_nstring_free(value); + * result = ""; + * indx = cur_token; + return r; + } + + return MAILIMAP_ERROR_PARSE; +} + +/* + body-fld-param = "(" string SP string *(SP string SP string) ")" / nil +*/ + +static int +mailimap_body_fld_param_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_body_fld_param ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * param_list; + struct mailimap_body_fld_param * fld_param; + int r; + int res; + + param_list = NULL; + cur_token = * indx; + + r = mailimap_nil_parse(fd, buffer, parser_ctx, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + * result = NULL; + * indx = cur_token; + return MAILIMAP_NO_ERROR; + } + + if (r != MAILIMAP_ERROR_PARSE) { + res = r; + goto err; + } + + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, &cur_token, ¶m_list, + (mailimap_struct_parser *) + mailimap_single_body_fld_param_parse, + (mailimap_struct_destructor *) + mailimap_single_body_fld_param_free, + progr_rate, progr_fun); + if (r == MAILIMAP_ERROR_PARSE) { + // case of empty () + // do nothing, workaround for mbox mail parser + } + else if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r == MAILIMAP_ERROR_PARSE) { + // workaround for broken param list + if (param_list != NULL) { + clist_foreach(param_list, + (clist_func) mailimap_single_body_fld_param_free, + NULL); + clist_free(param_list); + param_list = NULL; + } + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, &cur_token, ¶m_list, + (mailimap_struct_parser *) + mailimap_broken_single_body_fld_param_string_parse, + (mailimap_struct_destructor *) + mailimap_broken_single_body_fld_param_string_free, + progr_rate, progr_fun); + if (param_list != NULL) { + clist_free(param_list); + param_list = NULL; + } + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + } + else if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + if (param_list == NULL) { + * result = NULL; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + } + + fld_param = mailimap_body_fld_param_new(param_list); + if (fld_param == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * indx = cur_token; + * result = fld_param; + + return MAILIMAP_NO_ERROR; + + free: + if (param_list != NULL) { + clist_foreach(param_list, + (clist_func) mailimap_single_body_fld_param_free, + NULL); + clist_free(param_list); + } + err: + return res; +} + +/* + body-type-1part = (body-type-basic / body-type-msg / body-type-text) + [SP body-ext-1part] +*/ + +static int +mailimap_body_type_1part_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_type_1part ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_body_type_1part * body_type_1part; + struct mailimap_body_type_basic * body_type_basic; + struct mailimap_body_type_msg * body_type_msg; + struct mailimap_body_type_text * body_type_text; + struct mailimap_body_ext_1part * body_ext_1part; + int type; + size_t final_token; + int r; + int res; + + cur_token = * indx; + + body_type_basic = NULL; + body_type_msg = NULL; + body_type_text = NULL; + body_ext_1part = NULL; + + type = MAILIMAP_BODY_TYPE_1PART_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_body_type_msg_parse(fd, buffer, parser_ctx, &cur_token, + &body_type_msg, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_TYPE_1PART_MSG; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_body_type_text_parse(fd, buffer, parser_ctx, &cur_token, + &body_type_text, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_TYPE_1PART_TEXT; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_body_type_basic_parse(fd, buffer, parser_ctx, &cur_token, + &body_type_basic, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_TYPE_1PART_BASIC; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + final_token = cur_token; + body_ext_1part = NULL; + + r = mailimap_space_parse(fd, buffer, &cur_token); + + if (r == MAILIMAP_NO_ERROR) { + r = mailimap_body_ext_1part_parse(fd, buffer, parser_ctx, &cur_token, &body_ext_1part, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + final_token = cur_token; + else if (r == MAILIMAP_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto free; + } + } + else if (r == MAILIMAP_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto free; + } + + body_type_1part = mailimap_body_type_1part_new(type, body_type_basic, + body_type_msg, body_type_text, + body_ext_1part); + if (body_type_1part == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * indx = final_token; + * result = body_type_1part; + + return MAILIMAP_NO_ERROR; + + free: + if (body_type_basic) + mailimap_body_type_basic_free(body_type_basic); + if (body_type_msg) + mailimap_body_type_msg_free(body_type_msg); + if (body_type_text) + mailimap_body_type_text_free(body_type_text); + if (body_ext_1part) + mailimap_body_ext_1part_free(body_ext_1part); + err: + return res; +} + +/* + body-type-basic = media-basic SP body-fields + ; MESSAGE subtype MUST NOT be "RFC822" +*/ + +static int +mailimap_body_type_basic_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_type_basic ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + size_t saved_token; + struct mailimap_body_type_basic * body_type_basic; + struct mailimap_media_basic * media_basic; + struct mailimap_body_fields * body_fields; + int r; + int res; + uint32_t body_fld_lines; + + cur_token = * indx; + + media_basic = NULL; + body_fields = NULL; + + r = mailimap_media_basic_parse(fd, buffer, parser_ctx, &cur_token, &media_basic, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_media_basic; + } + + r = mailimap_body_fields_parse(fd, buffer, parser_ctx, &cur_token, &body_fields, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_media_basic; + } + + /* workaround for a bug on lavabit.com IMAP server - begin */ + saved_token = cur_token; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + r = mailimap_body_fld_lines_parse(fd, buffer, parser_ctx, &cur_token, &body_fld_lines); + if (r != MAILIMAP_NO_ERROR) { + cur_token = saved_token; + } + } + else { + cur_token = saved_token; + } + /* workaround for a bug on lavabit.com IMAP server - end */ + + body_type_basic = mailimap_body_type_basic_new(media_basic, body_fields); + if (body_type_basic == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_body_fields; + } + + * indx = cur_token; + * result = body_type_basic; + + return MAILIMAP_NO_ERROR; + + free_body_fields: + mailimap_body_fields_free(body_fields); + free_media_basic: + mailimap_media_basic_free(media_basic); + err: + return res; +} + +/* + body-type-mpart = 1*body SP media-subtype + [SP body-ext-mpart] +*/ + +static int +mailimap_body_type_mpart_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_type_mpart ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_body_type_mpart * body_type_mpart; + clist * body_list; + size_t cur_token; + size_t final_token; + char * media_subtype; + struct mailimap_body_ext_mpart * body_ext_mpart; + int r; + int res; + + cur_token = * indx; + + body_list = NULL; + media_subtype = NULL; + body_ext_mpart = NULL; + + r = mailimap_struct_multiple_parse(fd, buffer, parser_ctx, &cur_token, + &body_list, + (mailimap_struct_parser *) + mailimap_body_parse, + (mailimap_struct_destructor *) + mailimap_body_free, + progr_rate, progr_fun); + if (r == MAILIMAP_ERROR_PARSE) { + body_list = clist_new(); + if (body_list == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto err; + } + } + else if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + else { + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_body_list; + } + } + + r = mailimap_media_subtype_parse(fd, buffer, parser_ctx, &cur_token, &media_subtype, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_body_list; + } + + final_token = cur_token; + + body_ext_mpart = NULL; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + r = mailimap_body_ext_mpart_parse(fd, buffer, parser_ctx, &cur_token, &body_ext_mpart, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + final_token = cur_token; + else if (r == MAILIMAP_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto free_body_list; + } + } + else if (r == MAILIMAP_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto free_body_list; + } + + body_type_mpart = mailimap_body_type_mpart_new(body_list, media_subtype, + body_ext_mpart); + if (body_type_mpart == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_body_ext_mpart; + } + + * result = body_type_mpart; + * indx = final_token; + + return MAILIMAP_NO_ERROR; + + free_body_ext_mpart: + if (body_ext_mpart) + mailimap_body_ext_mpart_free(body_ext_mpart); + mailimap_media_subtype_free(media_subtype); + free_body_list: + clist_foreach(body_list, (clist_func) mailimap_body_free, NULL); + clist_free(body_list); + err: + return res; +} + +/* + body-type-msg = media-message SP body-fields SP envelope + SP body SP body-fld-lines +*/ + +static struct mailimap_body * body_text_new_empty(void) +{ + struct mailimap_body_type_1part * body_1part; + struct mailimap_body_type_text * body_type_text; + struct mailimap_body_fields * body_fields; + struct mailimap_body_fld_enc * enc; + struct mailimap_body * body; + char * media; + + enc = mailimap_body_fld_enc_new(MAILIMAP_BODY_FLD_ENC_7BIT, NULL); + if (enc == NULL) { + return NULL; + } + + body_fields = mailimap_body_fields_new(NULL, NULL, NULL, enc, 0); + if (body_fields == NULL) { + mailimap_body_fld_enc_free(enc); + return NULL; + } + + media = strdup("plain"); + if (media == NULL) { + mailimap_body_fields_free(body_fields); + return NULL; + } + + body_type_text = mailimap_body_type_text_new(media, body_fields, 0); + if (body_type_text == NULL) { + free(media); + mailimap_body_fields_free(body_fields); + return NULL; + } + + body_1part = mailimap_body_type_1part_new(MAILIMAP_BODY_TYPE_1PART_TEXT, + NULL, NULL, body_type_text, + NULL); + if (body_1part == NULL) { + mailimap_body_type_text_free(body_type_text); + return NULL; + } + + body = mailimap_body_new(MAILIMAP_BODY_1PART, body_1part, NULL); + if (body == NULL) { + mailimap_body_type_1part_free(body_1part); + return NULL; + } + + return body; +} + +static int +mailimap_body_type_msg_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_type_msg ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_body_fields * body_fields; + struct mailimap_envelope * envelope; + struct mailimap_body * body; + uint32_t body_fld_lines; + struct mailimap_body_type_msg * body_type_msg; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + body_fields = NULL; + envelope = NULL; + body = NULL; + body_fld_lines = 0; + + r = mailimap_media_message_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_body_fields_parse(fd, buffer, parser_ctx, &cur_token, &body_fields, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto body_fields; + } + + r = mailimap_envelope_parse(fd, buffer, parser_ctx, &cur_token, &envelope, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto body_fields; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_ERROR_PARSE) { + // do nothing + } + else if (r != MAILIMAP_NO_ERROR) { + res = r; + goto envelope; + } + + r = mailimap_body_parse(fd, buffer, parser_ctx, &cur_token, &body, + progr_rate, progr_fun); + if (r == MAILIMAP_ERROR_PARSE) { + /* workaround for Lotus Domino - body malformed */ + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = MAILIMAP_ERROR_PARSE; + goto envelope; + } + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = MAILIMAP_ERROR_PARSE; + goto envelope; + } + + body = body_text_new_empty(); + if (body == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto envelope; + } + } + else if (r != MAILIMAP_NO_ERROR) { + res = r; + goto envelope; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto body; + } + + r = mailimap_body_fld_lines_parse(fd, buffer, parser_ctx, &cur_token, + &body_fld_lines); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto body; + } + + body_type_msg = mailimap_body_type_msg_new(body_fields, envelope, + body, body_fld_lines); + if (body_type_msg == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto body; + } + + * result = body_type_msg; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + body: + mailimap_body_free(body); + envelope: + mailimap_envelope_free(envelope); + body_fields: + mailimap_body_fields_free(body_fields); + err: + return res; +} + +/* + body-type-text = media-text SP body-fields SP body-fld-lines +*/ + +static int +mailimap_body_type_text_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body_type_text ** + result, + size_t progr_rate, + progress_function * progr_fun) +{ + char * media_text; + struct mailimap_body_fields * body_fields; + uint32_t body_fld_lines; + struct mailimap_body_type_text * body_type_text; + size_t cur_token; + int r; + int res; + + media_text = NULL; + body_fields = NULL; + body_fld_lines = 0; + + cur_token = * indx; + + r = mailimap_media_text_parse(fd, buffer, parser_ctx, &cur_token, &media_text, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_media_text; + } + + r = mailimap_body_fields_parse(fd, buffer, parser_ctx, &cur_token, &body_fields, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_media_text; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_body_fields; + } + + r = mailimap_body_fld_lines_parse(fd, buffer, parser_ctx, &cur_token, &body_fld_lines); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_body_fields; + } + + body_type_text = mailimap_body_type_text_new(media_text, body_fields, + body_fld_lines); + if (body_type_text == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_body_fields; + } + + * result = body_type_text; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free_body_fields: + mailimap_body_fields_free(body_fields); + free_media_text: + mailimap_media_text_free(media_text); + err: + return res; +} + + +/* + capability = ("AUTH=" auth-type) / atom + ; New capabilities MUST begin with "X" or be + ; registered with IANA as standard or + ; standards-track +*/ + +static int +mailimap_capability_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_capability ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int type; + char * auth_type; + char * atom; + struct mailimap_capability * cap; + int r; + int res; + + cur_token = * indx; + + auth_type = NULL; + atom = NULL; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "AUTH="); + switch (r) { + case MAILIMAP_NO_ERROR: + type = MAILIMAP_CAPABILITY_AUTH_TYPE; + + r = mailimap_auth_type_parse(fd, buffer, parser_ctx, &cur_token, &auth_type, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + break; + + case MAILIMAP_ERROR_PARSE: + r = mailimap_atom_parse(fd, buffer, parser_ctx, &cur_token, &atom, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + type = MAILIMAP_CAPABILITY_NAME; + break; + + default: + res = r; + goto err; + } + + cap = mailimap_capability_new(type, auth_type, atom); + if (cap == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = cap; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (auth_type) + mailimap_auth_type_free(auth_type); + if (atom) + mailimap_atom_free(atom); + err: + return res; +} + +/* + capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev1" + *(SP capability) + ; IMAP4rev1 servers which offer RFC 1730 + ; compatibility MUST list "IMAP4" as the first + ; capability. +*/ + +/* + SP capability *(SP capability) +*/ + +int mailimap_capability_list_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + clist ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * list; + int r; + + cur_token = * indx; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, &cur_token, &list, + (mailimap_struct_parser *) + mailimap_capability_parse, + (mailimap_struct_destructor *) + mailimap_capability_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * indx = cur_token; + * result = list; + + return MAILIMAP_NO_ERROR; +} + +int +mailimap_capability_data_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_capability_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * cap_list; + struct mailimap_capability_data * cap_data; + int r; + int res; + + cur_token = * indx; + cap_list = NULL; + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "CAPABILITY"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_capability_list_parse(fd, buffer, parser_ctx, &cur_token, + &cap_list, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto err; + } + + cap_data = mailimap_capability_data_new(cap_list); + if (cap_data == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_list; + } + + * result = cap_data; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free_list: + if (cap_list) { + clist_foreach(cap_list, (clist_func) mailimap_capability_free, NULL); + clist_free(cap_list); + } + err: + return res; +} + +/* + UNIMPLEMENTED BECAUSE UNUSED (only in literal) + CHAR8 = %x01-ff + ; any OCTET except NUL, %x00 +*/ + +/* +static gboolean is_char8(gchar ch) +{ + return (ch != 0x00); +} +*/ + + +/* +UNIMPLEMENTED + command = tag SP (command-any / command-auth / command-nonauth / + command-select) CRLF + ; Modal based on state +*/ + +/* +UNIMPLEMENTED + command-any = "CAPABILITY" / "LOGOUT" / "NOOP" / x-command + ; Valid in all states +*/ + +/* +UNIMPLEMENTED + command-auth = append / create / delete / examine / list / lsub / + rename / select / status / subscribe / unsubscribe + ; Valid only in Authenticated or Selected state +*/ + +/* +UNIMPLEMENTED + command-nonauth = login / authenticate + ; Valid only when in Not Authenticated state +*/ + +/* +UNIMPLEMENTED + command-select = "CHECK" / "CLOSE" / "EXPUNGE" / copy / fetch / store / + uid / search + ; Valid only when in Selected state +*/ + +/* + continue-req = "+" SP (resp-text / base64) CRLF +*/ + +int +mailimap_continue_req_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_continue_req ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_resp_text * resp_text; + size_t cur_token; + struct mailimap_continue_req * cont_req; + char * base64; + int type; + int r; + int res; + size_t saved_token; + + cur_token = * indx; + + r = mailimap_plus_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_ERROR_PARSE) { + /* do nothing */ + } + else if (r != MAILIMAP_NO_ERROR) { + return r; + } + + resp_text = NULL; + base64 = NULL; + + type = MAILIMAP_CONTINUE_REQ_ERROR; /* XXX - removes a gcc warning */ + + saved_token = cur_token; + r = mailimap_base64_parse(fd, buffer, parser_ctx, &cur_token, &base64, + progr_rate, progr_fun); + + if (r == MAILIMAP_NO_ERROR) { + type = MAILIMAP_CONTINUE_REQ_BASE64; + + r = mailimap_crlf_parse(fd, buffer, parser_ctx, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMAP_ERROR_PARSE) { + mailimap_base64_free(base64); + base64 = NULL; + cur_token = saved_token; + } + else { + res = r; + goto err; + } + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_resp_text_parse(fd, buffer, parser_ctx, &cur_token, &resp_text, + progr_rate, progr_fun); + + if (r == MAILIMAP_NO_ERROR) { + type = MAILIMAP_CONTINUE_REQ_TEXT; + + r = mailimap_crlf_parse(fd, buffer, parser_ctx, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMAP_ERROR_PARSE) { + mailimap_resp_text_free(resp_text); + resp_text = NULL; + cur_token = saved_token; + } + else { + res = r; + goto err; + } + } + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + cont_req = mailimap_continue_req_new(type, resp_text, base64); + if (cont_req == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = cont_req; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (base64 != NULL) + mailimap_base64_free(base64); + if (resp_text != NULL) + mailimap_resp_text_free(resp_text); + err: + return res; +} + +/* + UNIMPLEMENTED + copy = "COPY" SP set SP mailbox +*/ + +/* + UNIMPLEMENTED + create = "CREATE" SP mailbox + ; Use of INBOX gives a NO error +*/ + +/* + UNIMPLEMENTED + date = date-text / DQUOTE date-text DQUOTE +*/ + +/* + UNIMPLEMENTED + date-day = 1*2DIGIT + ; Day of month +*/ + +/* +static gboolean mailimap_date_day_parse(mailstream * fd, + MMAPString * buffer, + guint32 * indx, + gint * result) +{ + guint32 cur_token; + gint digit; + gint number; + + cur_token = * indx; + + if (!mailimap_digit_parse(fd, buffer, &cur_token, &digit)) + return FALSE; + + number = digit; + + if (mailimap_digit_parse(fd, buffer, &cur_token, &digit)) + number = number * 10 + digit; + + * result = number; + * indx = cur_token; + + return TRUE; +} +*/ + +/* + date-day-fixed = (SP DIGIT) / 2DIGIT + ; Fixed-format version of date-day +*/ + +static int mailimap_date_day_fixed_parse(mailstream * fd, + MMAPString * buffer, + size_t * indx, + int * result) +{ +#ifdef UNSTRICT_SYNTAX + size_t cur_token; + uint32_t day; + int r; + + cur_token = * indx; + + r = mailimap_number_parse(fd, buffer, &cur_token, &day); + if (r != MAILIMAP_NO_ERROR) + return r; + + * indx = cur_token; + * result = day; + + return MAILIMAP_NO_ERROR; + +#else + size_t cur_token; + int r; + + cur_token = * indx; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + int digit; + + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = digit; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + } + else { + int digit1; + int digit2; + + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit1); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit2); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = digit1 * 10 + digit2; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + } +#endif +} + + +/* + date-month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / + "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" +*/ + +static int mailimap_date_month_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, int * result) +{ + size_t cur_token; + int month; + + cur_token = * indx; + + month = mailimap_month_get_token_value(fd, buffer, &cur_token); + if (month == -1) + return MAILIMAP_ERROR_PARSE; + + * result = month; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + UNIMPLEMENTED + date-text = date-day "-" date-month "-" date-year +*/ + +/* +static struct mailimap_date_text * +mailimap_date_text_new(gint day, gint month, gint year) +{ + struct mailimap_date_text * date_text; + + date_text = g_new(struct mailimap_date_text, 1); + if (date_text == NULL) + return NULL; + + date_text->day = day; + date_text->month = month; + date_text->year = year; + + return date_text; +} + +static void mailimap_date_text_free(struct mailimap_date_text * date_text) +{ + g_free(date_text); +} + +static gboolean +mailimap_date_text_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + guint32 * indx, struct mailimap_date_text ** result) +{ + struct mailimap_date_text * date_text; + gint day; + gint month; + gint year; + guint32 cur_token; + + cur_token = * indx; + + if (!mailimap_date_day_parse(fd, buffer, parser_ctx, &cur_token, &day)) + return FALSE; + + if (!mailimap_minus_parse(fd, buffer, parser_ctx, &cur_token)) + return FALSE; + + if (!mailimap_date_month_parse(fd, buffer, parser_ctx, &cur_token, &month)) + return FALSE; + + if (!mailimap_minus_parse(fd, buffer, parser_ctx, &cur_token)) + return FALSE; + + if (!mailimap_date_year_parse(fd, buffer, parser_ctx, &cur_token, &year)) + return FALSE; + + date_text = mailimap_date_text_new(day, month, year); + if (date_text == NULL) + return FALSE; + + * result = date_text; + * indx = cur_token; + + return TRUE; +} +*/ + +/* + date-year = 4DIGIT +*/ + +static int mailimap_date_year_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, int * result) +{ +#ifdef UNSTRICT_SYNTAX + uint32_t year; + int r; + size_t cur_token; + + cur_token = * indx; + + r = mailimap_number_parse(fd, buffer, &cur_token, &year); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = year; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +#else + int i; + size_t cur_token; + int year; + int digit; + int r; + + cur_token = * indx; + year = 0; + + for(i = 0 ; i < 4 ; i ++) { + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); + if (r != MAILIMAP_NO_ERROR) + return r; + year = year * 10 + digit; + } + + * result = year; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +#endif +} + +/* + date-time = DQUOTE date-day-fixed "-" date-month "-" date-year + SP time SP zone DQUOTE +*/ + +static int get_current_timezone_offset(void) +{ + struct tm gmt; + struct tm lt; + int off; + time_t t; + + t = time(NULL); + + if (gmtime_r(&t, &gmt) == NULL) + return 0; + + if (localtime_r(&t, <) == NULL) + return 0; + + off = (int) ((mail_mkgmtime(<) - mail_mkgmtime(&gmt)) * 100 / (60 * 60)); + + return off; +} + +static int mailimap_date_time_no_quote_space_timezone_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, int * p_timezone) +{ + int r; + size_t cur_token; + int zone; + + cur_token = * indx; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_zone_parse(fd, buffer, parser_ctx, &cur_token, &zone); + if (r != MAILIMAP_NO_ERROR) + return r; + + * indx = cur_token; + * p_timezone = zone; + + return MAILIMAP_NO_ERROR; +} + +static int mailimap_date_time_no_quote_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_date_time ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int day; + int month; + int year; + int hour; + int min; + int sec; + int zone; + struct mailimap_date_time * date_time; + size_t cur_token; + int r; + + cur_token = * indx; + + r = mailimap_date_day_fixed_parse(fd, buffer, &cur_token, &day); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_minus_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_month_parse(fd, buffer, parser_ctx, &cur_token, &month); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_minus_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_year_parse(fd, buffer, parser_ctx, &cur_token, &year); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_time_parse(fd, buffer, parser_ctx, &cur_token, &hour, &min, &sec); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_time_no_quote_space_timezone_parse(fd, buffer, parser_ctx, &cur_token, &zone); + if (r == MAILIMAP_ERROR_PARSE) { + zone = get_current_timezone_offset(); + } + else if (r != MAILIMAP_NO_ERROR) { + return r; + } + + date_time = mailimap_date_time_new(day, month, year, hour, min, sec, zone); + if (date_time == NULL) + return MAILIMAP_ERROR_MEMORY; + + * result = date_time; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailimap_hack_date_time_parse(char * str, + struct mailimap_date_time ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + mailstream * fd; + MMAPString * buffer; + struct mailimap_date_time * date_time; + size_t cur_token; + int r; + + fd = NULL; + buffer = mmap_string_new(str); + if (buffer == NULL) { + return MAILIMAP_ERROR_MEMORY; + } + + cur_token = 0; + + r = mailimap_date_time_no_quote_parse(fd, buffer, NULL, &cur_token, &date_time, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + * result = date_time; + + return MAILIMAP_NO_ERROR; +} + +static int mailimap_date_time_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_date_time ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_date_time * date_time; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + r = mailimap_dquote_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_date_time_no_quote_parse(fd, buffer, parser_ctx, &cur_token, + &date_time, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_dquote_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_date_time; + } + + * result = date_time; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + +free_date_time: + mailimap_date_time_free(date_time); +err: + return res; +} + +/* + UNIMPLEMENTED + delete = "DELETE" SP mailbox + ; Use of INBOX gives a NO error +*/ + +/* + digit-nz = %x31-39 + ; 1-9 +*/ + +#ifndef UNSTRICT_SYNTAX +static int is_digit_nz(char ch) +{ + return (ch >= '1') && (ch <= '9'); +} + +static int mailimap_digit_nz_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, int * result) +{ + size_t cur_token; + + cur_token = * indx; + + if (is_digit_nz(buffer->str[cur_token])) { + * result = buffer->str[cur_token] - '0'; + cur_token ++; + * indx = cur_token; + return MAILIMAP_NO_ERROR; + } + else + return MAILIMAP_ERROR_PARSE; +} +#endif + +/* + envelope = "(" env-date SP env-subject SP env-from SP env-sender SP + env-reply-to SP env-to SP env-cc SP env-bcc SP + env-in-reply-to SP env-message-id ")" +*/ + +static int mailimap_envelope_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_envelope ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int r; + r = mailimap_envelope_parse_full(fd, buffer, parser_ctx, indx, result, progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) { + return MAILIMAP_NO_ERROR; + } + else if (r != MAILIMAP_ERROR_PARSE) { + return r; + } + + /* workaround for qq.com IMAP Server. */ + r = mailimap_envelope_parse_workaround_qq_mail(fd, buffer, parser_ctx, indx, result, progr_rate, progr_fun); + return r; +} + +static int mailimap_envelope_parse_full(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_envelope ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * date; + char * subject; + struct mailimap_env_from * from; + struct mailimap_env_sender * sender; + struct mailimap_env_reply_to * reply_to; + struct mailimap_env_to * to; + struct mailimap_env_cc * cc; + struct mailimap_env_bcc * bcc; + char * in_reply_to; + char * message_id; + struct mailimap_envelope * envelope; + int r; + int res; + + date = NULL; + subject = NULL; + from = NULL; + sender = NULL; + reply_to = NULL; + to = NULL; + cc = NULL; + bcc = NULL; + in_reply_to = NULL; + message_id = NULL; + + cur_token = * indx; + + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_env_date_parse(fd, buffer, parser_ctx, &cur_token, &date, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto date; + } + + r = mailimap_env_subject_parse(fd, buffer, parser_ctx, &cur_token, &subject, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto date; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto subject; + } + + r = mailimap_env_from_parse(fd, buffer, parser_ctx, &cur_token, &from, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto subject; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto from; + } + + r = mailimap_env_sender_parse(fd, buffer, parser_ctx, &cur_token, &sender, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto from; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto sender; + } + + r = mailimap_env_reply_to_parse(fd, buffer, parser_ctx, &cur_token, &reply_to, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto sender; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto reply_to; + } + + r = mailimap_env_to_parse(fd, buffer, parser_ctx, &cur_token, &to, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto reply_to; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto to; + } + + r = mailimap_env_cc_parse(fd, buffer, parser_ctx, &cur_token, &cc, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto to; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto cc; + } + + r = mailimap_env_bcc_parse(fd, buffer, parser_ctx, &cur_token, &bcc, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto cc; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto bcc; + } + + r = mailimap_env_in_reply_to_parse(fd, buffer, parser_ctx, &cur_token, &in_reply_to, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto bcc; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto in_reply_to; + } + + r = mailimap_env_message_id_parse(fd, buffer, parser_ctx, &cur_token, &message_id, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto in_reply_to; + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto message_id; + } + + envelope = mailimap_envelope_new(date, subject, from, sender, reply_to, to, + cc, bcc, in_reply_to, message_id); + if (envelope == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto message_id; + } + + * result = envelope; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + message_id: + mailimap_env_message_id_free(message_id); + in_reply_to: + mailimap_env_in_reply_to_free(in_reply_to); + bcc: + mailimap_env_bcc_free(bcc); + cc: + mailimap_env_cc_free(cc); + to: + mailimap_env_to_free(to); + reply_to: + mailimap_env_reply_to_free(reply_to); + sender: + mailimap_env_sender_free(sender); + from: + mailimap_env_from_free(from); + subject: + mailimap_env_subject_free(date); + date: + mailimap_env_date_free(date); + err: + return res; +} + +static int mailimap_envelope_parse_workaround_qq_mail(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_envelope ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * date; + char * subject; + struct mailimap_env_from * from; + char * in_reply_to; + char * message_id; + struct mailimap_envelope * envelope; + int r; + int res; + char * first_string; + char * second_string; + int has_first_string; + int has_second_string; + + date = NULL; + subject = NULL; + from = NULL; + in_reply_to = NULL; + message_id = NULL; + first_string = NULL; + second_string = NULL; + res = MAILIMAP_ERROR_PARSE; + + cur_token = * indx; + + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_env_date_parse(fd, buffer, parser_ctx, &cur_token, &date, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto date; + } + + r = mailimap_env_subject_parse(fd, buffer, parser_ctx, &cur_token, &subject, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto date; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto subject; + } + + r = mailimap_env_from_parse(fd, buffer, parser_ctx, &cur_token, &from, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto subject; + } + + if (from == NULL) { + clist * list; + struct mailimap_address * addr; + + addr = mailimap_address_new("", NULL, "", ""); + if (addr == NULL) { + goto subject; + } + + list = clist_new(); + if (list == NULL) { + mailimap_address_free(addr); + goto subject; + } + + r = clist_append(list, addr); + if (r < 0) { + clist_free(list); + mailimap_address_free(addr); + goto subject; + } + + from = mailimap_env_from_new(list); + if (from == NULL) { + clist_free(list); + mailimap_address_free(addr); + goto subject; + } + } + + while (1) { + clist * list; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_ERROR_PARSE) { + break; + } + else if (r != MAILIMAP_NO_ERROR) { + res = r; + goto from; + } + + r = mailimap_address_list_parse(fd, buffer, parser_ctx, &cur_token, &list, + progr_rate, progr_fun); + if (r == MAILIMAP_ERROR_PARSE) { + break; + } + else if (r != MAILIMAP_NO_ERROR) { + res = r; + goto from; + } + if (list != NULL) { + clist_foreach(list, (clist_func) mailimap_address_free, NULL); + clist_free(list); + } + } + + has_first_string = 0; + r = mailimap_nstring_parse(fd, buffer, parser_ctx, &cur_token, &first_string, NULL, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) { + has_first_string = 1; + } + else if (r == MAILIMAP_ERROR_PARSE) { + // Do nothing. + } + else { + res = r; + goto from; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + // ignore errors. + + has_second_string = 0; + r = mailimap_nstring_parse(fd, buffer, parser_ctx, &cur_token, &second_string, NULL, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) { + has_second_string = 1; + } + else if (r == MAILIMAP_ERROR_PARSE) { + // Do nothing. + } + else { + res = r; + goto first_string; + } + + if (has_first_string && has_second_string) { + in_reply_to = first_string; + message_id = second_string; + } + else if (has_first_string) { + message_id = first_string; + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto second_string; + } + + envelope = mailimap_envelope_new(date, subject, from, NULL, NULL, NULL, + NULL, NULL, in_reply_to, message_id); + if (envelope == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto second_string; + } + + * result = envelope; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + +second_string: + free(second_string); +first_string: + free(first_string); +from: + mailimap_env_from_free(from); +subject: + mailimap_env_subject_free(date); +date: + mailimap_env_date_free(date); +err: + return res; +} + +/* + "(" 1*address ")" / nil +*/ + +static int mailimap_address_list_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + clist ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * address_list; + int r; + int res; + + cur_token = * indx; + + address_list = NULL; + + r = mailimap_nil_parse(fd, buffer, parser_ctx, &cur_token); + switch (r) { + case MAILIMAP_NO_ERROR: + address_list = NULL; + break; + + case MAILIMAP_ERROR_PARSE: + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_multiple_parse(fd, buffer, parser_ctx, &cur_token, &address_list, + (mailimap_struct_parser *) + mailimap_address_parse, + (mailimap_struct_destructor *) + mailimap_address_free, + progr_rate, progr_fun); + if (r == MAILIMAP_ERROR_PARSE) { + address_list = NULL; + } + else if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto address_list; + } + + break; + + default: + res = r; + goto err; + } + + * result = address_list; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + address_list: + if (address_list) { + clist_foreach(address_list, (clist_func) mailimap_address_free, NULL); + clist_free(address_list); + } + err: + return res; +} + +/* + env-bcc = "(" 1*address ")" / nil +*/ + +static int +mailimap_env_bcc_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_env_bcc ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * list; + size_t cur_token; + struct mailimap_env_bcc * env_bcc; + int r; + int res; + + cur_token = * indx; + list = NULL; + + r = mailimap_address_list_parse(fd, buffer, parser_ctx, &cur_token, &list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + env_bcc = mailimap_env_bcc_new(list); + if (env_bcc == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * indx = cur_token; + * result = env_bcc; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimap_address_free, NULL); + clist_free(list); + err: + return res; +} + +/* + env-cc = "(" 1*address ")" / nil +*/ + +static int +mailimap_env_cc_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_env_cc ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * list; + size_t cur_token; + struct mailimap_env_cc * env_cc; + int r; + int res; + + cur_token = * indx; + list = NULL; + + r = mailimap_address_list_parse(fd, buffer, parser_ctx, &cur_token, &list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + env_cc = mailimap_env_cc_new(list); + if (env_cc == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * indx = cur_token; + * result = env_cc; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimap_address_free, NULL); + clist_free(list); + err: + return res; +} + +/* + env-date = nstring +*/ + +static int mailimap_env_date_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, parser_ctx, indx, result, NULL, + progr_rate, progr_fun); +} + +/* + env-from = "(" 1*address ")" / nil +*/ + +static int +mailimap_env_from_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_env_from ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * list; + size_t cur_token; + struct mailimap_env_from * env_from; + int r; + int res; + + cur_token = * indx; + list = NULL; + + r = mailimap_address_list_parse(fd, buffer, parser_ctx, &cur_token, &list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + env_from = mailimap_env_from_new(list); + if (env_from == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * indx = cur_token; + * result = env_from; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimap_address_free, NULL); + clist_free(list); + err: + return res; +} + +/* + env-in-reply-to = nstring +*/ + +static int mailimap_env_in_reply_to_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, parser_ctx, indx, result, NULL, + progr_rate, progr_fun); +} + +/* + env-message-id = nstring +*/ + +static int mailimap_env_message_id_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, parser_ctx, indx, result, NULL, + progr_rate, progr_fun); +} + +/* + env-reply-to = "(" 1*address ")" / nil +*/ + +static int +mailimap_env_reply_to_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_env_reply_to ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * list; + size_t cur_token; + struct mailimap_env_reply_to * env_reply_to; + int r; + int res; + + cur_token = * indx; + list = NULL; + + r = mailimap_address_list_parse(fd, buffer, parser_ctx, &cur_token, &list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + env_reply_to = mailimap_env_reply_to_new(list); + if (env_reply_to == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * indx = cur_token; + * result = env_reply_to; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimap_address_free, NULL); + clist_free(list); + err: + return res; +} + +/* + env-sender = "(" 1*address ")" / nil +*/ + + +static int +mailimap_env_sender_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_env_sender ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * list; + size_t cur_token; + struct mailimap_env_sender * env_sender; + int r; + int res; + + cur_token = * indx; + list = NULL; + + r = mailimap_address_list_parse(fd, buffer, parser_ctx, &cur_token, &list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + env_sender = mailimap_env_sender_new(list); + if (env_sender == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * indx = cur_token; + * result = env_sender; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimap_address_free, NULL); + clist_free(list); + err: + return res; +} + + +/* + env-subject = nstring +*/ + +static int mailimap_env_subject_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, parser_ctx, indx, result, NULL, + progr_rate, progr_fun); +} + + +/* + env-to = "(" 1*address ")" / nil +*/ + +static int mailimap_env_to_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_env_to ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * list; + size_t cur_token; + struct mailimap_env_to * env_to; + int r; + int res; + + cur_token = * indx; + list = NULL; + + r = mailimap_address_list_parse(fd, buffer, parser_ctx, &cur_token, &list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + env_to = mailimap_env_to_new(list); + if (env_to == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * indx = cur_token; + * result = env_to; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimap_address_free, NULL); + clist_free(list); + err: + return res; +} + + +/* + UNIMPLEMENTED + examine = "EXAMINE" SP mailbox +*/ + +/* + UNIMPLEMENTED + fetch = "FETCH" SP set SP ("ALL" / "FULL" / "FAST" / fetch-att / + "(" fetch-att *(SP fetch-att) ")") +*/ + +/* + UNIMPLEMENTED + fetch-att = "ENVELOPE" / "FLAGS" / "INTERNALDATE" / + "RFC822" [".HEADER" / ".SIZE" / ".TEXT"] / + "BODY" ["STRUCTURE"] / "UID" / + "BODY" [".PEEK"] section ["<" number "." nz-number ">"] +*/ + +/* + flag = "\Answered" / "\Flagged" / "\Deleted" / + "\Seen" / "\Draft" / flag-keyword / flag-extension + ; Does not include "\Recent" +*/ + +static int mailimap_flag_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_flag ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_flag * flag; + size_t cur_token; + char * flag_keyword; + char * flag_extension; + int type; + int r; + int res; + + cur_token = * indx; + + flag_keyword = NULL; + flag_extension = NULL; + + type = mailimap_flag_get_token_value(fd, buffer, &cur_token); + if (type == -1) { + r = mailimap_flag_keyword_parse(fd, buffer, parser_ctx, &cur_token, &flag_keyword, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_FLAG_KEYWORD; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_flag_extension_parse(fd, buffer, parser_ctx, &cur_token, + &flag_extension, + progr_rate, progr_fun); + type = MAILIMAP_FLAG_EXTENSION; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + } + + flag = mailimap_flag_new(type, flag_keyword, flag_extension); + if (flag == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = flag; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (flag_keyword != NULL) + mailimap_flag_keyword_free(flag_keyword); + if (flag_extension != NULL) + mailimap_flag_extension_free(flag_extension); + err: + return res; +} + +/* + flag-extension = "\" atom + ; Future expansion. Client implementations + ; MUST accept flag-extension flags. Server + ; implementations MUST NOT generate + ; flag-extension flags except as defined by + ; future standard or standards-track + ; revisions of this specification. +*/ + +static int mailimap_flag_extension_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * atom; + int r; + + cur_token = * indx; + + r = mailimap_char_parse(fd, buffer, &cur_token, '\\'); + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_char_parse(fd, buffer, &cur_token, '/'); + } + if (r != MAILIMAP_NO_ERROR) + return r; + + atom = NULL; + r = mailimap_atom_parse(fd, buffer, parser_ctx, &cur_token, &atom, + progr_rate, progr_fun); + if (r == MAILIMAP_ERROR_PARSE) { + /* workaround for binc IMAP */ + r = mailimap_char_parse(fd, buffer, &cur_token, '*'); + if (r == MAILIMAP_NO_ERROR) { + atom = malloc(2); + if (atom == NULL) + return MAILIMAP_ERROR_MEMORY; + + atom[0] = '*'; + atom[1] = '\0'; + } + } + if (r != MAILIMAP_NO_ERROR) { + free(atom); + return r; + } + + * result = atom; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + flag-fetch = flag / "\Recent" +*/ + +static int +mailimap_flag_fetch_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_flag_fetch ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_flag * flag; + struct mailimap_flag_fetch * flag_fetch; + int type; + int r; + int res; + + cur_token = * indx; + + flag = NULL; + + type = MAILIMAP_FLAG_FETCH_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "\\Recent"); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_FLAG_FETCH_RECENT; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_flag_parse(fd, buffer, parser_ctx, &cur_token, &flag, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_FLAG_FETCH_OTHER; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + flag_fetch = mailimap_flag_fetch_new(type, flag); + if (flag_fetch == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * indx = cur_token; + * result = flag_fetch; + + return MAILIMAP_NO_ERROR; + + free: + if (flag != NULL) + mailimap_flag_free(flag); + err: + return res; +} + +/* + flag-keyword = atom + WARNING : parse astring instead of atom to workaround RockLiffe server : + http://www.rockliffe.com/ +*/ + +static int mailimap_flag_keyword_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ +#if 0 + return mailimap_atom_parse(fd, buffer, parser_ctx, indx, result, + progr_rate, progr_fun); +#endif + return mailimap_astring_parse(fd, buffer, parser_ctx, indx, result, + progr_rate, progr_fun); +} + +/* + flag-list = "(" [flag *(SP flag)] ")" +*/ + +static int mailimap_flag_list_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_flag_list ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * list; + struct mailimap_flag_list * flag_list; + int r; + int res; + + list = NULL; + cur_token = * indx; + + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, &cur_token, &list, + (mailimap_struct_parser *) + mailimap_flag_parse, + (mailimap_struct_destructor *) + mailimap_flag_free, + progr_rate, progr_fun); + + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + flag_list = mailimap_flag_list_new(list); + if (flag_list == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = flag_list; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimap_flag_free, NULL); + clist_free(list); + } + err: + return res; +} + +/* + flag-perm = flag / "\*" +*/ + +static int +mailimap_flag_perm_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_flag_perm ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_flag_perm * flag_perm; + struct mailimap_flag * flag; + int type; + int r; + int res; + + flag = NULL; + cur_token = * indx; + type = MAILIMAP_FLAG_PERM_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "\\*"); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_FLAG_PERM_ALL; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_flag_parse(fd, buffer, parser_ctx, &cur_token, &flag, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_FLAG_PERM_FLAG; + + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + flag_perm = mailimap_flag_perm_new(type, flag); + if (flag_perm == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = flag_perm; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (flag != NULL) + mailimap_flag_free(flag); + err: + return res; +} + +/* + greeting = "*" SP (resp-cond-auth / resp-cond-bye) CRLF +*/ + +int mailimap_greeting_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_greeting ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_resp_cond_auth * resp_cond_auth; + struct mailimap_resp_cond_bye * resp_cond_bye; + struct mailimap_greeting * greeting; + int type; + int r; + int res; + + cur_token = * indx; + resp_cond_bye = NULL; + resp_cond_auth = NULL; + + r = mailimap_star_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + type = MAILIMAP_GREETING_RESP_COND_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_resp_cond_auth_parse(fd, buffer, parser_ctx, &cur_token, &resp_cond_auth, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_GREETING_RESP_COND_AUTH; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_resp_cond_bye_parse(fd, buffer, parser_ctx, &cur_token, + &resp_cond_bye, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_GREETING_RESP_COND_BYE; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_crlf_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + greeting = mailimap_greeting_new(type, resp_cond_auth, resp_cond_bye); + if (greeting == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = greeting; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (resp_cond_auth) + mailimap_resp_cond_auth_free(resp_cond_auth); + if (resp_cond_bye) + mailimap_resp_cond_bye_free(resp_cond_bye); + err: + return res; +} + +/* + header-fld-name = astring +*/ + +static int +mailimap_header_fld_name_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_astring_parse(fd, buffer, parser_ctx, indx, result, + progr_rate, progr_fun); +} + +/* + header-list = "(" header-fld-name *(SP header-fld-name) ")" +*/ + +static int +mailimap_header_list_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_header_list ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_header_list * header_list; + clist * list; + int r; + int res; + + cur_token = * indx; + + list = NULL; + + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, &cur_token, &list, + (mailimap_struct_parser *) + mailimap_header_fld_name_parse, + (mailimap_struct_destructor *) + mailimap_header_fld_name_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + header_list = mailimap_header_list_new(list); + if (header_list == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = header_list; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimap_header_fld_name_free, NULL); + clist_free(list); + err: + return res; +} + +/* +UNIMPLEMENTED + list = "LIST" SP mailbox SP list-mailbox + +UNIMPLEMENTED + list-mailbox = 1*list-char / string + +UNIMPLEMENTED + list-char = ATOM-CHAR / list-wildcards / resp-specials +*/ + +/* + list-wildcards = "%" / "*" +*/ + +static int is_list_wildcards(char ch) +{ + switch (ch) { + case '%': + case '*': + return TRUE; + } + return FALSE; +} + + +/* + literal = "{" number "}" CRLF *CHAR8 + ; Number represents the number of CHAR8s +*/ + +#define MAX_READ_PROGRESS 65536 + +static int mailimap_literal_parse_progress(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context) +{ + size_t cur_token; + uint32_t number; + MMAPString * literal; + uint32_t left; + int r; + int res; + size_t number_token; + bool use_msg_body_handler; + + cur_token = * indx; + use_msg_body_handler = (parser_ctx->msg_body_handler != NULL + && parser_ctx->msg_body_parse_in_progress); + + r = mailimap_oaccolade_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + number_token = cur_token; + + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + if (r == MAILIMAP_ERROR_PARSE) { + // workaround issue with Free servers + r = mailimap_minus_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + number = 0; + } + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_caccolade_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_crlf_parse(fd, buffer, parser_ctx, &cur_token); + if (r == MAILIMAP_ERROR_PARSE) { + /* workaround for Lotus Domino IMAP server */ + mailimap_space_parse(fd, buffer, &cur_token); + mailimap_space_parse(fd, buffer, &cur_token); + } + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + if (use_msg_body_handler) { + literal = mmap_string_new(""); + } + else { + literal = mmap_string_sized_new(number); + } + if (literal == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto err; + } + + left = (uint32_t) (buffer->len - cur_token); + + if (left >= number) { + if (number > 0) { + if (use_msg_body_handler) { + if (!parser_ctx->msg_body_handler(parser_ctx->msg_body_att_type, parser_ctx->msg_body_section, + buffer->str + cur_token, number, + parser_ctx->msg_body_handler_context)) { + res = MAILIMAP_ERROR_MEMORY; + goto free_literal; + } + } + else { + if (mmap_string_append_len(literal, buffer->str + cur_token, + number) == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_literal; + } + } + } + if (progr_rate != 0) { + if (progr_fun != NULL) { + progr_fun(number, number); + } + if (body_progr_fun != NULL) { + body_progr_fun(number, number, context); + } + } + cur_token = cur_token + number; + } + else { + uint32_t needed; + uint32_t current_prog = 0; + uint32_t last_prog = 0; + + needed = number - left; + if (left > 0) { + if (use_msg_body_handler) { + if (!parser_ctx->msg_body_handler(parser_ctx->msg_body_att_type, parser_ctx->msg_body_section, + buffer->str + cur_token, left, + parser_ctx->msg_body_handler_context)) { + res = MAILIMAP_ERROR_MEMORY; + goto free_literal; + } + } + else { + if (mmap_string_append_len(literal, buffer->str + cur_token, + left) == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_literal; + } + } + } + current_prog = left; + + while (needed > 0) { + ssize_t read_bytes; + size_t bytes_to_read; + + bytes_to_read = needed; + if (bytes_to_read > MAX_READ_PROGRESS) { + bytes_to_read = MAX_READ_PROGRESS; + } + if (fd == NULL) { + res = MAILIMAP_ERROR_NEEDS_MORE_DATA; + goto free_literal; + } + + char read_buffer[MAX_READ_PROGRESS]; + if (use_msg_body_handler) { + read_bytes = mailstream_read(fd, read_buffer, bytes_to_read); + if (read_bytes > 0) { + if (!parser_ctx->msg_body_handler(parser_ctx->msg_body_att_type, parser_ctx->msg_body_section, + read_buffer, read_bytes, + parser_ctx->msg_body_handler_context)) { + res = MAILIMAP_ERROR_MEMORY; + goto free_literal; + } + } + } + else { + read_bytes = mailstream_read(fd, literal->str + literal->len, bytes_to_read); + if (read_bytes > 0) { + literal->len += read_bytes; + } + } + + if (read_bytes == -1) { + res = MAILIMAP_ERROR_STREAM; + goto free_literal; + } + needed -= read_bytes; + + if (needed > 0 && mailimap_parser_context_is_rambler_workaround_enabled(parser_ctx)) { + /* workaround issue with Rambler IMAP server */ + char const * search_beg = use_msg_body_handler ? read_buffer : literal->str; + char const * search_end = use_msg_body_handler ? read_buffer + read_bytes : literal->str + literal->len; + char tag_response_end[] = " OK completed\r\n"; + size_t tag_response_end_len = sizeof(tag_response_end) - 1; + /* Looking backward for pattern " UID \d+)\r\n\d+ OK completed\r\n$" */ + if (search_end - search_beg >= tag_response_end_len && + memcmp(search_end - tag_response_end_len, tag_response_end, tag_response_end_len) == 0) { + search_end -= tag_response_end_len; + /* match tag */ + while (search_end > search_beg && is_digit(*(search_end - 1))) search_end--; + /* match closing parenthesis and CRLF */ + if (search_end > search_beg + 3) search_end -= 3; + if (memcmp(search_end, ")\r\n", 3) == 0) { + /* match uid */ + while (search_end > search_beg && is_digit(*(search_end - 1))) search_end--; + if (search_end > search_beg + 5) search_end -= 5; + if (memcmp(search_end, " UID ", 5) == 0) { + /* got invalid server response, no more data will received */ + res = MAILIMAP_ERROR_PARSE; + goto free_literal; + } + } + } + } + + current_prog += read_bytes; + if (current_prog - last_prog > progr_rate) { + if (progr_fun != NULL) { + progr_fun(current_prog, number); + } + if (body_progr_fun != NULL) { + body_progr_fun(current_prog, number, context); + } + last_prog = current_prog; + } + } + + if (!use_msg_body_handler) { + literal->str[number] = 0; + } + + if (mmap_string_truncate(buffer, number_token) == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_literal; + } + + if (mmap_string_append(buffer, "0}\r\n") == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_literal; + } + + cur_token = number_token + 4; + } + if (progr_rate != 0) { + if (progr_fun != NULL) { + progr_fun(number, number); + } + if (body_progr_fun != NULL) { + body_progr_fun(number, number, context); + } + } + + if (fd == NULL) { + if (!has_crlf(buffer, cur_token)) { + res = MAILIMAP_ERROR_NEEDS_MORE_DATA; + goto free_literal; + } + } + else { + if (mailstream_read_line_append(fd, buffer) == NULL) { + res = MAILIMAP_ERROR_STREAM; + goto free_literal; + } + } + + if (mmap_string_ref(literal) < 0) { + res = MAILIMAP_ERROR_MEMORY; + goto free_literal; + } + + * result = literal->str; + if (result_len != NULL) + * result_len = literal->len; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + +free_literal: + mmap_string_free(literal); +err: + return res; +} + +/* + UNIMPLEMENTED + login = "LOGIN" SP userid SP password + + UNIMPLEMENTED + lsub = "LSUB" SP mailbox SP list-mailbox +*/ + +/* + mailbox = "INBOX" / astring + ; INBOX is case-insensitive. All case variants of + ; INBOX (e.g. "iNbOx") MUST be interpreted as INBOX + ; not as an astring. An astring which consists of + ; the case-insensitive sequence "I" "N" "B" "O" "X" + ; is considered to be INBOX and not an astring. + ; Refer to section 5.1 for further + ; semantic details of mailbox names. +*/ + +int +mailimap_mailbox_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * name; + int r; + + cur_token = * indx; + + r = mailimap_astring_parse(fd, buffer, parser_ctx, &cur_token, &name, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = name; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +static int +mailimap_mailbox_gmail_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * name; + int r; + clist * astring_list; + size_t parsed_length; + clistiter * cur; + + cur_token = * indx; + + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, &cur_token, &astring_list, + (mailimap_struct_parser *) + mailimap_astring_parse, + (mailimap_struct_destructor *) + mailimap_astring_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + for(cur = clist_begin(astring_list) ; cur != NULL ; cur = clist_next(cur)) { + char * str; + + str = clist_content(cur); + mailimap_astring_free(str); + } + clist_free(astring_list); + + parsed_length = cur_token - * indx; + name = malloc(parsed_length + 1); + if (name == NULL) { + return MAILIMAP_ERROR_MEMORY; + } + memcpy(name, buffer->str + * indx, parsed_length); + name[parsed_length] = 0; + + * result = name; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list / + "LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) / + "STATUS" SP mailbox SP "(" + [status-att SP number *(SP status-att SP number)] ")" / + number SP "EXISTS" / number SP "RECENT" +*/ + +/* + "FLAGS" SP flag-list +*/ + +static int +mailimap_mailbox_data_flags_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_flag_list ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_flag_list * flag_list; + int r; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "FLAGS"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + flag_list = NULL; + r = mailimap_flag_list_parse(fd, buffer, parser_ctx, &cur_token, &flag_list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = flag_list; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + "LIST" SP mailbox-list +*/ + +static int +mailimap_mailbox_data_list_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_mailbox_list ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_mailbox_list * mb_list; + int r; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "LIST"); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + r = mailimap_mailbox_list_parse(fd, buffer, parser_ctx, &cur_token, &mb_list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + * result = mb_list; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "LSUB" SP mailbox-list +*/ + +static int +mailimap_mailbox_data_lsub_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_mailbox_list ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_mailbox_list * mb_list; + int r; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "LSUB"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_list_parse(fd, buffer, parser_ctx, &cur_token, &mb_list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = mb_list; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "SEARCH" *(SP nz-number) +*/ + + +static int +mailimap_mailbox_data_search_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + clist ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + size_t final_token; + clist * number_list; + int r; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "SEARCH"); + if (r != MAILIMAP_NO_ERROR) + return r; + + final_token = cur_token; + number_list = NULL; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, &cur_token, &number_list, + (mailimap_struct_parser *) + mailimap_nz_number_alloc_parse, + (mailimap_struct_destructor *) + mailimap_number_alloc_free, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + final_token = cur_token; + } + + * result = number_list; + * indx = final_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "STATUS" SP mailbox SP "(" + [status-att SP number *(SP status-att SP number)] ")" +*/ + +/* + status-att SP number +*/ + +static int +mailimap_status_info_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_status_info ** + result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int status_att; + uint32_t value; + struct mailimap_status_info * info; + int r; + + cur_token = * indx; + value = 0; + + r = mailimap_status_att_parse(fd, buffer, parser_ctx, &cur_token, &status_att); + if (r == MAILIMAP_NO_ERROR) { + /* Force parse error when HIGHESTMODSEQ is parsed */ + if (status_att == MAILIMAP_STATUS_ATT_HIGHESTMODSEQ) { + r = MAILIMAP_ERROR_PARSE; + } + } + if (r == MAILIMAP_ERROR_PARSE) { + struct mailimap_extension_data * ext_data; + + cur_token = * indx; + r = mailimap_extension_data_parse(MAILIMAP_EXTENDED_PARSER_STATUS_ATT, + fd, buffer, parser_ctx, &cur_token, &ext_data, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) { + info = mailimap_status_info_new(MAILIMAP_STATUS_ATT_EXTENSION, 0, ext_data); + if (info == NULL) + return MAILIMAP_ERROR_MEMORY; + + * result = info; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + } + } + + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_number_parse(fd, buffer, &cur_token, &value); + if (r != MAILIMAP_NO_ERROR) + return r; + + info = mailimap_status_info_new(status_att, value, NULL); + if (info == NULL) + return MAILIMAP_ERROR_MEMORY; + + * result = info; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "STATUS" SP mailbox SP "(" + [status-att SP number *(SP status-att SP number)] ")" +*/ + +static int +mailimap_mailbox_data_status_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct + mailimap_mailbox_data_status ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * mb; + clist * status_info_list; + struct mailimap_mailbox_data_status * data_status; + int r; + int res; + + cur_token = * indx; + mb = NULL; + status_info_list = NULL; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "STATUS"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_mailbox_gmail_parse(fd, buffer, parser_ctx, &cur_token, &mb, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto mailbox; + } + + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto mailbox; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, &cur_token, + &status_info_list, + (mailimap_struct_parser *) + mailimap_status_info_parse, + (mailimap_struct_destructor *) + mailimap_status_info_free, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto mailbox; + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto status_info_list; + } + + data_status = mailimap_mailbox_data_status_new(mb, status_info_list); + if (data_status == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto status_info_list; + } + + * result = data_status; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + status_info_list: + if (status_info_list != NULL) { + clist_foreach(status_info_list, (clist_func) mailimap_status_info_free, + NULL); + clist_free(status_info_list); + } + mailbox: + mailimap_mailbox_free(mb); + err: + return res; +} + +/* + number SP "EXISTS" +*/ + +static int +mailimap_mailbox_data_exists_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + uint32_t * result) +{ + size_t cur_token; + uint32_t number; + int r; + + cur_token = * indx; + + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "EXISTS"); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = number; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + number SP "RECENT" +*/ + +static int +mailimap_mailbox_data_recent_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + uint32_t * result) +{ + size_t cur_token; + uint32_t number; + int r; + + cur_token = * indx; + + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "RECENT"); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = number; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list / + "LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) / + "STATUS" SP mailbox SP "(" + [status-att SP number *(SP status-att SP number)] ")" / + number SP "EXISTS" / number SP "RECENT" +*/ + +static int +mailimap_mailbox_data_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_mailbox_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int type; + struct mailimap_flag_list * data_flags; + struct mailimap_mailbox_list * data_list; + struct mailimap_mailbox_list * data_lsub; + clist * data_search; + struct mailimap_mailbox_data_status * data_status; + uint32_t data_exists; + uint32_t data_recent; + struct mailimap_extension_data * data_extension; + + struct mailimap_mailbox_data * mailbox_data; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + data_flags = NULL; + data_list = NULL; + data_lsub = NULL; + data_search = NULL; + data_status = NULL; + data_exists = 0; + data_recent = 0; + data_extension = NULL; + + type = MAILIMAP_MAILBOX_DATA_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_mailbox_data_flags_parse(fd, buffer, parser_ctx, &cur_token, + &data_flags, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MAILBOX_DATA_FLAGS; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_mailbox_data_list_parse(fd, buffer, parser_ctx, &cur_token, + &data_list, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MAILBOX_DATA_LIST; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_mailbox_data_lsub_parse(fd, buffer, parser_ctx, &cur_token, + &data_lsub, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MAILBOX_DATA_LSUB; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_mailbox_data_search_parse(fd, buffer, parser_ctx, &cur_token, + &data_search, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MAILBOX_DATA_SEARCH; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_mailbox_data_status_parse(fd, buffer, parser_ctx, &cur_token, + &data_status, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MAILBOX_DATA_STATUS; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_mailbox_data_exists_parse(fd, buffer, parser_ctx, &cur_token, + &data_exists); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MAILBOX_DATA_EXISTS; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_mailbox_data_recent_parse(fd, buffer, parser_ctx, &cur_token, + &data_recent); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MAILBOX_DATA_RECENT; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_extension_data_parse(MAILIMAP_EXTENDED_PARSER_MAILBOX_DATA, + fd, buffer, parser_ctx, &cur_token, &data_extension, progr_rate, + progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MAILBOX_DATA_EXTENSION_DATA; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + mailbox_data = mailimap_mailbox_data_new(type, data_flags, data_list, + data_lsub, data_search, + data_status, + data_exists, data_recent, + data_extension); + + if (mailbox_data == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = mailbox_data; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (data_flags != NULL) + mailimap_flag_list_free(data_flags); + if (data_list != NULL) + mailimap_mailbox_list_free(data_list); + if (data_lsub != NULL) + mailimap_mailbox_list_free(data_lsub); + if (data_search != NULL) + mailimap_mailbox_data_search_free(data_search); + if (data_status != NULL) + mailimap_mailbox_data_status_free(data_status); + if (data_extension != NULL) + mailimap_extension_data_free(data_extension); + err: + return res; +} + +/* + mailbox-list = "(" [mbx-list-flags] ")" SP + (DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox +*/ + +/* + DQUOTE QUOTED-CHAR DQUOTE +*/ + +static int +mailimap_mailbox_list_quoted_char_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + char * result) +{ + size_t cur_token; + char ch; + int r; + + cur_token = * indx; + + r = mailimap_dquote_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_quoted_char_parse(fd, buffer, parser_ctx, &cur_token, &ch); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_dquote_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + * indx = cur_token; + * result = ch; + + return MAILIMAP_NO_ERROR; +} + +int +mailimap_mailbox_list_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_mailbox_list ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_mailbox_list * mb_list; + struct mailimap_mbx_list_flags * mb_flag_list; + char ch; + char * mb; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + mb_flag_list = NULL; + ch = 0; + mb = NULL; + + r = mailimap_mbx_list_flags_parse(fd, buffer, parser_ctx, &cur_token, + &mb_flag_list, progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list_flags; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list_flags; + } + + r = mailimap_mailbox_list_quoted_char_parse(fd, buffer, parser_ctx, &cur_token, &ch); + if (r == MAILIMAP_ERROR_PARSE) + r = mailimap_nil_parse(fd, buffer, parser_ctx, &cur_token); + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list_flags; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list_flags; + } + + r = mailimap_mailbox_parse(fd, buffer, parser_ctx, &cur_token, &mb, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list_flags; + } + + mb_list = mailimap_mailbox_list_new(mb_flag_list, ch, mb); + if (mb_list == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_mailbox; + } + + * result = mb_list; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free_mailbox: + mailimap_mailbox_free(mb); + free_list_flags: + if (mb_flag_list != NULL) + mailimap_mbx_list_flags_free(mb_flag_list); + err: + return res; +} + +/* + mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag + *(SP mbx-list-oflag) / + mbx-list-oflag *(SP mbx-list-oflag) +*/ + +static int +mailimap_mbx_list_flags_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_mbx_list_flags ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_mbx_list_flags * mbx_list_flag; + size_t cur_token; + clist * oflags; + clist * oflags_2; + int sflag; + int type; + int r; + int res; + size_t final_token; + int try_sflag; + + cur_token = * indx; + final_token = cur_token; + + oflags = clist_new(); + if (oflags == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto err; + } + + sflag = MAILIMAP_MBX_LIST_SFLAG_ERROR; + oflags_2 = NULL; + + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, &cur_token, + &oflags_2, + (mailimap_struct_parser *) + mailimap_mbx_list_oflag_no_sflag_parse, + (mailimap_struct_destructor *) + mailimap_mbx_list_oflag_free, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto free; + } + + try_sflag = 1; + if (r == MAILIMAP_NO_ERROR) { + clist_concat(oflags, oflags_2); + clist_free(oflags_2); + + final_token = cur_token; + try_sflag = 0; + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) + try_sflag = 1; + } + + type = MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG; + if (try_sflag) { + r = mailimap_mbx_list_sflag_parse(fd, buffer, parser_ctx, &cur_token, &sflag); + switch (r) { + case MAILIMAP_ERROR_PARSE: + type = MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG; + break; + + case MAILIMAP_NO_ERROR: + type = MAILIMAP_MBX_LIST_FLAGS_SFLAG; + + final_token = cur_token; + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, &cur_token, + &oflags_2, + (mailimap_struct_parser *) mailimap_mbx_list_oflag_parse, + (mailimap_struct_destructor *) mailimap_mbx_list_oflag_free, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto err; + } + + if (r == MAILIMAP_NO_ERROR) { + clist_concat(oflags, oflags_2); + clist_free(oflags_2); + + final_token = cur_token; + } + } + + break; + + default: + res = r; + goto free; + } + } + + if ((clist_count(oflags) == 0) && (type == MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG)) { + res = MAILIMAP_ERROR_PARSE; + goto free; + } + + cur_token = final_token; + mbx_list_flag = mailimap_mbx_list_flags_new(type, oflags, sflag); + if (mbx_list_flag == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = mbx_list_flag; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + +free: + clist_foreach(oflags, (clist_func) mailimap_mbx_list_oflag_free, NULL); + clist_free(oflags); +err: + return res; +} + +/* + mbx-list-oflag = "\Noinferiors" / flag-extension + ; Other flags; multiple possible per LIST response +*/ + +static int +mailimap_mbx_list_oflag_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_mbx_list_oflag ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int type; + size_t cur_token; + struct mailimap_mbx_list_oflag * oflag; + char * flag_ext; + int r; + int res; + + cur_token = * indx; + flag_ext = NULL; + type = MAILIMAP_MBX_LIST_OFLAG_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "\\Noinferiors"); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "/Noinferiors"); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_flag_extension_parse(fd, buffer, parser_ctx, &cur_token, + &flag_ext, progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + oflag = mailimap_mbx_list_oflag_new(type, flag_ext); + if (oflag == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = oflag; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (flag_ext != NULL) + mailimap_flag_extension_free(flag_ext); + err: + return res; +} + +static int +mailimap_mbx_list_oflag_no_sflag_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_mbx_list_oflag ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int sflag_type; + int r; + + cur_token = * indx; + + r = mailimap_mbx_list_sflag_parse(fd, buffer, parser_ctx, &cur_token, &sflag_type); + if (r == MAILIMAP_NO_ERROR) + return MAILIMAP_ERROR_PARSE; + + return mailimap_mbx_list_oflag_parse(fd, buffer, parser_ctx, indx, result, + progr_rate, progr_fun); +} + + +/* + mbx-list-sflag = "\Noselect" / "\Marked" / "\Unmarked" + ; Selectability flags; only one per LIST response +*/ + +static int +mailimap_mbx_list_sflag_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + int * result) +{ + int type; + size_t cur_token; + + cur_token = * indx; + + type = mailimap_mbx_list_sflag_get_token_value(fd, buffer, &cur_token); + if (type == -1) + return MAILIMAP_ERROR_PARSE; + + * result = type; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" / + "VIDEO") DQUOTE) / string) SP media-subtype + ; Defined in [MIME-IMT] +*/ + +/* + DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" / + "VIDEO") DQUOTE +*/ + +static int +mailimap_media_basic_standard_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + int * result) +{ + size_t cur_token; + int type; + int r; + + cur_token = * indx; + + r = mailimap_dquote_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + type = mailimap_media_basic_get_token_value(fd, buffer, &cur_token); + if (type == -1) + return MAILIMAP_ERROR_PARSE; + + r = mailimap_dquote_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + * indx = cur_token; + * result = type; + + return MAILIMAP_NO_ERROR; +} + +/* + media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" / + "VIDEO") DQUOTE) / string) SP media-subtype + ; Defined in [MIME-IMT] +*/ + +static int +mailimap_media_basic_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_media_basic ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int type; + char * basic_type; + char * subtype; + struct mailimap_media_basic * media_basic; + int r; + int res; + + cur_token = * indx; + + basic_type = NULL; + subtype = NULL; + + type = MAILIMAP_MEDIA_BASIC_OTHER; + r = mailimap_media_basic_standard_parse(fd, buffer, parser_ctx, &cur_token, + &type); + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_string_parse(fd, buffer, parser_ctx, &cur_token, &basic_type, NULL, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MEDIA_BASIC_OTHER; + } + + // workaround for mbox mail for mac + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_nil_parse(fd, buffer, parser_ctx, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + type = MAILIMAP_MEDIA_BASIC_APPLICATION; + } + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_basic_type; + } + + r = mailimap_media_subtype_parse(fd, buffer, parser_ctx, &cur_token, &subtype, + progr_rate, progr_fun); + if (r == MAILIMAP_ERROR_PARSE) { + // workaround for mbox mail for mac + } + else if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_basic_type; + } + + if (r == MAILIMAP_ERROR_PARSE) { + // workaround for mbox mail for mac + r = mailimap_nil_parse(fd, buffer, parser_ctx, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + subtype = strdup("DATA"); // application data + if (subtype == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_basic_type; + } + } + } + + media_basic = mailimap_media_basic_new(type, basic_type, subtype); + if (media_basic == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_subtype; + } + + * result = media_basic; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free_subtype: + mailimap_media_subtype_free(subtype); + free_basic_type: + if (basic_type != NULL) + mailimap_string_free(basic_type); + err: + return res; +} + + +/* + media-message = DQUOTE "MESSAGE" DQUOTE SP DQUOTE "RFC822" DQUOTE + ; Defined in [MIME-IMT] +*/ + +static int +mailimap_media_message_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx) +{ + size_t cur_token; + int r; + + cur_token = * indx; + + r = mailimap_dquote_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "MESSAGE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_dquote_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_dquote_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "RFC822"); + if (r == MAILIMAP_ERROR_PARSE) { + // workaround for IMAP server "Bigfoot" + // * OK [CAPABILITY IMAP4REV1 LITERAL+ SASL-IR LOGIN-REFERRALS AUTH=LOGIN ID] mail16c25 IMAP4rev1 Bigfoot + // 01 id + // * ID ("name", "Bigfoot", "version", "1.0", "os", "Linux", "os-version", "2.6", "vendor", "Megamailservers.com", "author", "Derek Snider") + // * OK ID completed + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "DELIVERY-STATUS"); + } + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_dquote_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + media-subtype = string + ; Defined in [MIME-IMT] +*/ + +static int +mailimap_media_subtype_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_string_parse(fd, buffer, parser_ctx, indx, result, NULL, + progr_rate, progr_fun); +} + +/* + media-text = DQUOTE "TEXT" DQUOTE SP media-subtype + ; Defined in [MIME-IMT] +*/ + +static int mailimap_media_text_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * media_subtype; + int r; + + cur_token = * indx; + + r = mailimap_dquote_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "TEXT"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_dquote_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_media_subtype_parse(fd, buffer, parser_ctx, &cur_token, &media_subtype, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = media_subtype; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + message-data = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att)) +*/ + + +static int +mailimap_message_data_parse_progress(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_message_data ** result, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context) +{ + size_t cur_token; + uint32_t number; + int type; + struct mailimap_msg_att * msg_att; + struct mailimap_message_data * msg_data; + int r; + int res; + + cur_token = * indx; + msg_att = NULL; + + r = mailimap_nz_number_parse(fd, buffer, parser_ctx, &cur_token, &number); + if (r == MAILIMAP_ERROR_PARSE) { + // workaround for Zoho Mail IMAP server. sometimes returns negative message numbers + + r = mailimap_minus_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + number = 0; + } + else if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + type = MAILIMAP_MESSAGE_DATA_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "EXPUNGE"); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MESSAGE_DATA_EXPUNGE; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "FETCH"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_msg_att_parse_progress(fd, buffer, parser_ctx, &cur_token, &msg_att, + progr_rate, progr_fun, body_progr_fun, items_progr_fun, context, msg_att_handler, msg_att_context); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + if (items_progr_fun != NULL) { + (* items_progr_fun)(0, 0, context); + } + + type = MAILIMAP_MESSAGE_DATA_FETCH; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + msg_data = mailimap_message_data_new(number, type, msg_att); + if (msg_data == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_msg_att; + } + + * result = msg_data; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free_msg_att: + if (msg_att != NULL) + mailimap_msg_att_free(msg_att); + err: + return res; +} + +/* + msg-att = "(" (msg-att-dynamic / msg-att-static) + *(SP (msg-att-dynamic / msg-att-static)) ")" +*/ + +/* + msg-att-dynamic / msg-att-static +*/ + +static int +mailimap_msg_att_item_parse_progress(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_msg_att_item ** result, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context) +{ + int type; + struct mailimap_msg_att_dynamic * msg_att_dynamic; + struct mailimap_msg_att_static * msg_att_static; + struct mailimap_extension_data * msg_att_extension; + size_t cur_token; + struct mailimap_msg_att_item * item; + int r; + int res; + + cur_token = * indx; + + msg_att_dynamic = NULL; + msg_att_static = NULL; + msg_att_extension = NULL; + + type = MAILIMAP_MSG_ATT_ITEM_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_msg_att_dynamic_parse(fd, buffer, parser_ctx, &cur_token, + &msg_att_dynamic, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_ITEM_DYNAMIC; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_static_parse_progress(fd, buffer, parser_ctx, &cur_token, + &msg_att_static, + progr_rate, progr_fun, + body_progr_fun, items_progr_fun, context, msg_att_handler, msg_att_context); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_ITEM_STATIC; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_extension_data_parse(MAILIMAP_EXTENDED_PARSER_FETCH_DATA, + fd, buffer, parser_ctx, &cur_token, &msg_att_extension, progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_ITEM_EXTENSION; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + item = mailimap_msg_att_item_new(type, msg_att_dynamic, msg_att_static, msg_att_extension); + if (item == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = item; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (msg_att_extension != NULL) + mailimap_extension_data_free(msg_att_extension); + if (msg_att_dynamic != NULL) + mailimap_msg_att_dynamic_free(msg_att_dynamic); + if (msg_att_static != NULL) + mailimap_msg_att_static_free(msg_att_static); + err: + return res; +} + +/* + msg-att = "(" (msg-att-dynamic / msg-att-static) + *(SP (msg-att-dynamic / msg-att-static)) ")" +*/ + +static int +mailimap_msg_att_parse_progress(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_msg_att ** result, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context) +{ + size_t cur_token; + clist * list; + struct mailimap_msg_att * msg_att; + int r; + int res; + + cur_token = * indx; + list = NULL; + + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse_progress(fd, buffer, parser_ctx, &cur_token, &list, + (mailimap_struct_parser_progress *) + mailimap_msg_att_item_parse_progress, + (mailimap_struct_destructor *) + mailimap_msg_att_item_free, + progr_rate, progr_fun, + body_progr_fun, items_progr_fun, + context, msg_att_handler, msg_att_context); + if (r != MAILIMAP_NO_ERROR) { + if (mailimap_parser_context_is_qip_workaround_enabled(parser_ctx)) { + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + // QIP returns "* num FETCH ()" response for storeFlags operations. + + list = clist_new(); + if (list == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + goto ok; + } + } + + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + ok: + msg_att = mailimap_msg_att_new(list); + if (msg_att == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * indx = cur_token; + * result = msg_att; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimap_msg_att_item_free, NULL); + clist_free(list); + err: + return res; +} + +/* + msg-att-dynamic = "FLAGS" SP "(" [flag-fetch *(SP flag-fetch)] ")" + ; MAY change for a message +*/ + + +static int +mailimap_msg_att_dynamic_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_msg_att_dynamic ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * list; + struct mailimap_msg_att_dynamic * msg_att_dyn; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + list = NULL; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "FLAGS"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, &cur_token, + &list, + (mailimap_struct_parser *) + mailimap_flag_fetch_parse, + (mailimap_struct_destructor *) + mailimap_flag_fetch_free, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + msg_att_dyn = mailimap_msg_att_dynamic_new(list); + if (msg_att_dyn == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = msg_att_dyn; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimap_flag_fetch_free, NULL); + clist_free(list); + } + err: + return res; +} + +/* + msg-att-static = "ENVELOPE" SP envelope / "INTERNALDATE" SP date-time / + "RFC822" [".HEADER" / ".TEXT"] SP nstring / + "RFC822.SIZE" SP number / "BODY" ["STRUCTURE"] SP body / + "BODY" section ["<" number ">"] SP nstring / + "UID" SP uniqueid + ; MUST NOT change for a message +*/ + +/* + "ENVELOPE" SP envelope +*/ + + +static int +mailimap_msg_att_envelope_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_envelope ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_envelope * env; + int r; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "ENVELOPE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_envelope_parse(fd, buffer, parser_ctx, &cur_token, &env, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * indx = cur_token; + * result = env; + + return MAILIMAP_NO_ERROR; +} + + +/* + "INTERNALDATE" SP date-time +*/ + + +static int +mailimap_msg_att_internaldate_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_date_time ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_date_time * date_time; + int r; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "INTERNALDATE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_time_parse(fd, buffer, parser_ctx, &cur_token, &date_time, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = date_time; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "RFC822" SP nstring +*/ + +static int +mailimap_msg_att_rfc822_parse_progress(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context) +{ + size_t cur_token; + char * rfc822_message; + int r; + size_t length; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "RFC822"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + parser_ctx->msg_body_parse_in_progress = true; + parser_ctx->msg_body_att_type = MAILIMAP_MSG_ATT_RFC822; + + r = mailimap_nstring_parse_progress(fd, buffer, parser_ctx, &cur_token, &rfc822_message, &length, + progr_rate, progr_fun, body_progr_fun, items_progr_fun, context, msg_att_handler, msg_att_context); + + parser_ctx->msg_body_parse_in_progress = false; + parser_ctx->msg_body_att_type = 0; + + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = rfc822_message; + if (result_len != NULL) + * result_len = length; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "RFC822" ".HEADER" SP nstring +*/ + +static int +mailimap_msg_att_rfc822_header_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * rfc822_header; + int r; + size_t length; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "RFC822"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + ".HEADER"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_nstring_parse(fd, buffer, parser_ctx, &cur_token, &rfc822_header, &length, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = rfc822_header; + if (result_len != NULL) + * result_len = length; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "RFC822" ".TEXT" SP nstring +*/ + +static int +mailimap_msg_att_rfc822_text_parse_progress(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context) +{ + size_t cur_token; + char * rfc822_text; + int r; + size_t length; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "RFC822"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + ".TEXT"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + parser_ctx->msg_body_parse_in_progress = true; + parser_ctx->msg_body_att_type = MAILIMAP_MSG_ATT_RFC822_TEXT; + + r = mailimap_nstring_parse_progress(fd, buffer, parser_ctx, &cur_token, &rfc822_text, &length, + progr_rate, progr_fun, body_progr_fun, items_progr_fun, context, msg_att_handler, msg_att_context); + + parser_ctx->msg_body_parse_in_progress = false; + parser_ctx->msg_body_att_type = 0; + + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = rfc822_text; + if (result_len != NULL) + * result_len = length; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "RFC822.SIZE" SP number +*/ + +static int +mailimap_msg_att_rfc822_size_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, uint32_t * result) +{ + size_t cur_token; + uint32_t number; + int r; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "RFC822.SIZE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = number; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "BODY" SP body +*/ + + +static int +mailimap_msg_att_body_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_body ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_body * body; + size_t cur_token; + int r; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "BODY"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_body_parse(fd, buffer, parser_ctx, &cur_token, &body, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = body; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "BODY" "STRUCTURE" SP body +*/ + + +static int +mailimap_msg_att_bodystructure_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_body ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_body * body; + size_t cur_token; + int r; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "BODY"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "STRUCTURE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_body_parse(fd, buffer, parser_ctx, &cur_token, &body, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = body; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "BODY" section ["<" number ">"] SP nstring +*/ + +static int +mailimap_msg_att_body_section_parse_progress(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_msg_att_body_section ** + result, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context) +{ + size_t cur_token; + uint32_t number; + struct mailimap_section * section; + char * body_part; + struct mailimap_msg_att_body_section * msg_att_body_section; + int r; + int res; + size_t length; + + cur_token = * indx; + + section = NULL; + number = 0; + body_part = NULL; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "BODY"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_section_parse(fd, buffer, parser_ctx, &cur_token, §ion, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_lower_parse(fd, buffer, parser_ctx, &cur_token); + switch (r) { + case MAILIMAP_NO_ERROR: + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_section; + } + + r = mailimap_greater_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_section; + } + break; + + case MAILIMAP_ERROR_PARSE: + break; + + default: + return r; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_section; + } + + msg_att_body_section = + mailimap_msg_att_body_section_new(section, number, NULL, 0); + if (msg_att_body_section == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_section; + } + + parser_ctx->msg_body_parse_in_progress = true; + parser_ctx->msg_body_att_type = MAILIMAP_MSG_ATT_BODY_SECTION; + parser_ctx->msg_body_section = msg_att_body_section; + + r = mailimap_nstring_parse_progress(fd, buffer, parser_ctx, &cur_token, &body_part, &length, + progr_rate, progr_fun, body_progr_fun, items_progr_fun, context, msg_att_handler, msg_att_context); + + parser_ctx->msg_body_parse_in_progress = false; + parser_ctx->msg_body_att_type = 0; + parser_ctx->msg_body_section = NULL; + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_att_body_section; + } + + msg_att_body_section->sec_body_part = body_part; + msg_att_body_section->sec_length = length; + + * result = msg_att_body_section; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free_att_body_section: + msg_att_body_section->sec_section = NULL; + mailimap_msg_att_body_section_free(msg_att_body_section); + free_section: + if (section != NULL) + mailimap_section_free(section); + err: + return res; +} + +/* + "UID" SP uniqueid +*/ + +static int +mailimap_msg_att_uid_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + uint32_t * result) +{ + size_t cur_token; + uint32_t uid; + int r; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uniqueid_parse(fd, buffer, parser_ctx, &cur_token, &uid); + if (r != MAILIMAP_NO_ERROR) + return r; + + * indx = cur_token; + * result = uid; + + return MAILIMAP_NO_ERROR; +} + +/* + msg-att-static = "ENVELOPE" SP envelope / "INTERNALDATE" SP date-time / + "RFC822" [".HEADER" / ".TEXT"] SP nstring / + "RFC822.SIZE" SP number / "BODY" ["STRUCTURE"] SP body / + "BODY" section ["<" number ">"] SP nstring / + "UID" SP uniqueid + ; MUST NOT change for a message +*/ + +static int +mailimap_msg_att_static_parse_progress(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_msg_att_static ** result, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context) +{ + size_t cur_token; + struct mailimap_envelope * env; + struct mailimap_date_time * internal_date; + char * rfc822; + char * rfc822_header; + char * rfc822_text; + uint32_t rfc822_size; + struct mailimap_body * bodystructure; + struct mailimap_body * body; + struct mailimap_msg_att_body_section * body_section; + uint32_t uid; + struct mailimap_msg_att_static * msg_att_static; + int type; + int r; + int res; + size_t length; + + cur_token = * indx; + + env = NULL; + internal_date = NULL; + rfc822 = NULL; + rfc822_header = NULL; + rfc822_text = NULL; + rfc822_size = 0; + length = 0; + bodystructure = NULL; + body = NULL; + body_section = NULL; + uid = 0; + + type = MAILIMAP_MSG_ATT_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_msg_att_envelope_parse(fd, buffer, parser_ctx, &cur_token, &env, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_ENVELOPE; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_internaldate_parse(fd, buffer, parser_ctx, &cur_token, + &internal_date, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_INTERNALDATE; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_rfc822_parse_progress(fd, buffer, parser_ctx, &cur_token, + &rfc822, &length, + progr_rate, progr_fun, + body_progr_fun, items_progr_fun, context, msg_att_handler, msg_att_context); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_RFC822; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_rfc822_header_parse(fd, buffer, parser_ctx, &cur_token, + &rfc822_header, &length, + progr_rate, progr_fun); + type = MAILIMAP_MSG_ATT_RFC822_HEADER; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_rfc822_text_parse_progress(fd, buffer, parser_ctx, &cur_token, + &rfc822_text, &length, + progr_rate, progr_fun, + body_progr_fun, items_progr_fun, context, msg_att_handler, msg_att_context); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_RFC822_TEXT; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_rfc822_size_parse(fd, buffer, parser_ctx, &cur_token, + &rfc822_size); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_RFC822_SIZE; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_body_parse(fd, buffer, parser_ctx, &cur_token, + &body, progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_BODY; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_bodystructure_parse(fd, buffer, parser_ctx, &cur_token, + &bodystructure, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_BODYSTRUCTURE; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_body_section_parse_progress(fd, buffer, parser_ctx, &cur_token, + &body_section, + progr_rate, progr_fun, + body_progr_fun, items_progr_fun, context, msg_att_handler, msg_att_context); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_BODY_SECTION; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_uid_parse(fd, buffer, parser_ctx, &cur_token, + &uid); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_UID; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + msg_att_static = mailimap_msg_att_static_new(type, env, internal_date, + rfc822, rfc822_header, + rfc822_text, length, + rfc822_size, bodystructure, + body, body_section, uid); + if (msg_att_static == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = msg_att_static; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (env) + mailimap_msg_att_envelope_free(env); + if (internal_date) + mailimap_msg_att_internaldate_free(internal_date); + if (rfc822) + mailimap_msg_att_rfc822_free(rfc822); + if (rfc822_header) + mailimap_msg_att_rfc822_header_free(rfc822_header); + if (rfc822_text) + mailimap_msg_att_rfc822_text_free(rfc822_text); + if (bodystructure) + mailimap_msg_att_bodystructure_free(bodystructure); + if (body) + mailimap_msg_att_body_free(body); + if (body_section) + mailimap_msg_att_body_section_free(body_section); + err: + return res; +} + +/* + nil = "NIL" +*/ + +int mailimap_nil_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx) +{ + return mailimap_token_case_insensitive_parse(fd, buffer, indx, "NIL"); +} + +/* + nstring = string / nil +*/ + +static int mailimap_nstring_parse_progress(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context) +{ + int r; + + r = mailimap_string_parse_progress(fd, buffer, parser_ctx, indx, result, result_len, + progr_rate, progr_fun, + body_progr_fun, items_progr_fun, context, msg_att_handler, msg_att_context); + switch (r) { + case MAILIMAP_NO_ERROR: + return MAILIMAP_NO_ERROR; + + case MAILIMAP_ERROR_PARSE: + r = mailimap_nil_parse(fd, buffer, parser_ctx, indx); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + * result = NULL; + if (result_len != NULL) + * result_len = 0; + return MAILIMAP_NO_ERROR; + + default: + return r; + } +} + +int mailimap_nstring_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse_progress(fd, buffer, parser_ctx, indx, result, result_len, progr_rate, progr_fun, + NULL, NULL, NULL, NULL, NULL); +} + +/* + number = 1*DIGIT + ; Unsigned 32-bit integer + ; (0 <= n < 4,294,967,296) +*/ + +int +mailimap_number_parse(mailstream * fd, MMAPString * buffer, + size_t * indx, uint32_t * result) +{ + size_t cur_token; + int digit; + uint32_t number; + int parsed; + int r; + int negative; + + cur_token = * indx; + parsed = FALSE; + +#ifdef UNSTRICT_SYNTAX + mailimap_space_parse(fd, buffer, &cur_token); +#endif + + negative = 0; + r = mailimap_char_parse(fd, buffer, &cur_token, '-'); + if (r == MAILIMAP_NO_ERROR) { + negative = 1; + } + + number = 0; + while (1) { + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); + if (r == MAILIMAP_ERROR_PARSE) + break; + else if (r == MAILIMAP_NO_ERROR) { + number *= 10; + number += digit; + parsed = TRUE; + } + else + return r; + } + + if (negative) { + number = 0; + } + + if (!parsed) + return MAILIMAP_ERROR_PARSE; + + * result = number; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + nz-number = digit-nz *DIGIT + ; Non-zero unsigned 32-bit integer + ; (0 < n < 4,294,967,296) +*/ + +int +mailimap_nz_number_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, uint32_t * result) +{ +#ifdef UNSTRICT_SYNTAX + size_t cur_token; + uint32_t number; + int r; + + cur_token = * indx; + + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) + return r; + +#if 0 // don't fail if zero + if (number == 0) + return MAILIMAP_ERROR_PARSE; +#endif + +#else + size_t cur_token; + int digit; + uint32_t number; + int r; + + cur_token = * indx; + + r = mailimap_digit_nz_parse(fd, buffer, parser_ctx, &cur_token, &digit); + if (r != MAILIMAP_NO_ERROR) + return r; + + number = digit; + + while (1) { + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); + if (r == MAILIMAP_ERROR_PARSE) + break; + else if (r == MAILIMAP_NO_ERROR) { + number *= 10; + number += (guint32) digit; + } + else + return r; + } +#endif + + * result = number; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + password = astring +*/ + +/* + quoted = DQUOTE *QUOTED-CHAR DQUOTE +*/ + +static int +mailimap_quoted_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + char ch; + size_t cur_token; + MMAPString * gstr_quoted; + int r; + int res; + bool use_msg_body_handler; + + cur_token = * indx; + + use_msg_body_handler = (parser_ctx->msg_body_handler != NULL + && parser_ctx->msg_body_parse_in_progress); + +#ifdef UNSTRICT_SYNTAX + r = mailimap_space_parse(fd, buffer, &cur_token); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; +#endif + + r = mailimap_dquote_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + gstr_quoted = mmap_string_new(""); + if (gstr_quoted == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto err; + } + + while (1) { + if (cur_token >= buffer->len) { + if (fd == NULL) { + if (!has_crlf(buffer, cur_token)) { + res = MAILIMAP_ERROR_NEEDS_MORE_DATA; + goto free; + } + } + else if (mailstream_read_line_append(fd, buffer) == NULL) { + res = MAILIMAP_ERROR_PARSE; + goto free; + } + } + + r = mailimap_quoted_char_parse(fd, buffer, parser_ctx, &cur_token, &ch); + if (r == MAILIMAP_ERROR_PARSE) + break; + else if (r == MAILIMAP_NO_ERROR) { + if (use_msg_body_handler) { + if (!parser_ctx->msg_body_handler(parser_ctx->msg_body_att_type, parser_ctx->msg_body_section, + &ch, 1, + parser_ctx->msg_body_handler_context)) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + } + else { + if (mmap_string_append_c(gstr_quoted, ch) == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + } + } + else { + res = r; + goto free; + } + } + + r = mailimap_dquote_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + if (mmap_string_ref(gstr_quoted) < 0) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * indx = cur_token; + * result = gstr_quoted->str; + + return MAILIMAP_NO_ERROR; + + free: + mmap_string_free(gstr_quoted); + err: + return res; +} + +/* + QUOTED-CHAR = / + "\" quoted-specials +*/ + +static int is_quoted_specials(char ch); + +int +mailimap_quoted_char_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char * result) +{ + size_t cur_token; + int r; + + cur_token = * indx; + + if (cur_token >= buffer->len) + return MAILIMAP_ERROR_PARSE; + + if (!is_quoted_specials(buffer->str[cur_token])) { + * result = buffer->str[cur_token]; + cur_token ++; + * indx = cur_token; + return MAILIMAP_NO_ERROR; + } + else if (buffer->str[cur_token] == '\\') { + char quoted_special; + + r = mailimap_char_parse(fd, buffer, &cur_token, '\\'); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + r = mailimap_quoted_specials_parse(fd, buffer, parser_ctx, &cur_token, + "ed_special); + if (r != MAILIMAP_NO_ERROR) { + * result = '\\'; + * indx = cur_token; + return MAILIMAP_NO_ERROR; + } + + * result = quoted_special; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + } + else { + return MAILIMAP_ERROR_PARSE; + } +} + +/* + quoted-specials = DQUOTE / "\" +*/ + +static int is_quoted_specials(char ch) +{ + return (ch == '\"') || (ch == '\\'); +} + +static int +mailimap_quoted_specials_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char * result) +{ + size_t cur_token; + + cur_token = * indx; + + if (cur_token >= buffer->len) + return MAILIMAP_ERROR_PARSE; + + if (is_quoted_specials(buffer->str[cur_token])) { + * result = buffer->str[cur_token]; + cur_token ++; + * indx = cur_token; + return MAILIMAP_NO_ERROR; + } + else + return MAILIMAP_ERROR_PARSE; +} + +/* + UNIMPLEMENTED + rename = "RENAME" SP mailbox SP mailbox + ; Use of INBOX as a destination gives a NO error +*/ + +/* + response = *(continue-req / response-data) response-done +*/ + +/* + continue-req / response-data +*/ + +static int +mailimap_cont_req_or_resp_data_parse_progress(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_cont_req_or_resp_data ** + result, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context) +{ + size_t cur_token; + struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data; + struct mailimap_continue_req * cont_req; + struct mailimap_response_data * resp_data; + int type; + int r; + int res; + + cur_token = * indx; + + cont_req = NULL; + resp_data = NULL; + type = MAILIMAP_RESP_ERROR; /* XXX - removes a gcc warning */ + + // skip blank lines (workaround for exchange) + while (1) { + r = mailimap_crlf_parse(fd, buffer, parser_ctx, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + if (fd == NULL) { + if (!has_crlf(buffer, cur_token)) { + res = MAILIMAP_ERROR_NEEDS_MORE_DATA; + goto free; + } + } + else if (mailstream_read_line_append(fd, buffer) == NULL) { + res = MAILIMAP_ERROR_STREAM; + goto free; + } + continue; + } + break; + } + + r = mailimap_continue_req_parse(fd, buffer, parser_ctx, &cur_token, &cont_req, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_CONT_REQ; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_response_data_parse_progress(fd, buffer, parser_ctx, &cur_token, &resp_data, + progr_rate, progr_fun, + body_progr_fun, items_progr_fun, + context, msg_att_handler, msg_att_context); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_RESP_DATA; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + /* + multi-lines response + read another response line because after that token, + there must have something (continue-req, response-data or response-done) + */ + + if (fd == NULL) { + if (!has_crlf(buffer, cur_token)) { + res = MAILIMAP_ERROR_NEEDS_MORE_DATA; + goto free; + } + } + else if (mailstream_read_line_append(fd, buffer) == NULL) { + res = MAILIMAP_ERROR_STREAM; + goto free; + } + + if ((cont_req == NULL) && (resp_data == NULL)) { + cont_req_or_resp_data = NULL; + } + else { + cont_req_or_resp_data = + mailimap_cont_req_or_resp_data_new(type, cont_req, resp_data); + if (cont_req_or_resp_data == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + } + + * result = cont_req_or_resp_data; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (cont_req != NULL) + mailimap_continue_req_free(cont_req); + if (resp_data != NULL) + mailimap_response_data_free(resp_data); + err: + return res; +} + +/* static */ int +mailimap_cont_req_or_resp_data_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_cont_req_or_resp_data ** + result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_cont_req_or_resp_data_parse_progress(fd, buffer, parser_ctx, indx, result, + progr_rate, + progr_fun, + NULL, NULL, NULL, NULL, NULL); +} + +/* + response = *(continue-req / response-data) response-done +*/ + +static int +mailimap_response_parse_progress(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_response ** result, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context) +{ + size_t cur_token; + clist * cont_req_or_resp_data_list; + struct mailimap_response * resp; + struct mailimap_response_done * resp_done; + int r; + int res; + clistiter * iter; + + cur_token = * indx; + cont_req_or_resp_data_list = NULL; + resp_done = NULL; + + r = mailimap_struct_multiple_parse_progress(fd, buffer, parser_ctx, + &cur_token, &cont_req_or_resp_data_list, + (mailimap_struct_parser_progress *) + mailimap_cont_req_or_resp_data_parse_progress, + (mailimap_struct_destructor *) + mailimap_cont_req_or_resp_data_free, + progr_rate, progr_fun, + body_progr_fun, + items_progr_fun, + context, + msg_att_handler, + msg_att_context); + + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; + + if (r == MAILIMAP_NO_ERROR) { + for(iter = clist_begin(cont_req_or_resp_data_list) ; iter != NULL ; iter = clist_next(iter)) { + struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data = clist_content(iter); + if (cont_req_or_resp_data->rsp_type != MAILIMAP_RESP_RESP_DATA) { + continue; + } + if (cont_req_or_resp_data->rsp_data.rsp_resp_data->rsp_type == MAILIMAP_RESP_DATA_TYPE_COND_BYE) { + res = MAILIMAP_ERROR_STREAM; + goto free_list; + } + } + } + + r = mailimap_response_done_parse(fd, buffer, parser_ctx, &cur_token, &resp_done, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list; + } + + resp = mailimap_response_new(cont_req_or_resp_data_list, resp_done); + if (resp == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_resp_done; + } + + * result = resp; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + +free_resp_done: + mailimap_response_done_free(resp_done); +free_list: + if (cont_req_or_resp_data_list != NULL) { + clist_foreach(cont_req_or_resp_data_list, + (clist_func) mailimap_cont_req_or_resp_data_free, NULL); + clist_free(cont_req_or_resp_data_list); + } + return res; +} + +int +mailimap_response_parse_with_context(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_response ** result, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context) +{ + return mailimap_response_parse_progress(fd, buffer, parser_ctx, indx, result, + 4096, NULL, + body_progr_fun, items_progr_fun, context, + msg_att_handler, msg_att_context); +} + +int +mailimap_response_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_response ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_response_parse_progress(fd, buffer, parser_ctx, indx, result, + progr_rate, progr_fun, + NULL, NULL, NULL, NULL, NULL); +} + +/* + response-data = "*" SP (resp-cond-state / resp-cond-bye / + mailbox-data / message-data / capability-data) CRLF +*/ + +static int +mailimap_response_data_parse_progress(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_response_data ** result, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context) +{ + struct mailimap_response_data * resp_data; + size_t cur_token; + int type; + struct mailimap_resp_cond_state * cond_state; + struct mailimap_resp_cond_bye * cond_bye; + struct mailimap_mailbox_data * mb_data; + struct mailimap_message_data * msg_data; + struct mailimap_capability_data * cap_data; + struct mailimap_extension_data * ext_data; + int r; + int res; + int msg_att_handled; + + cond_state = NULL; + cond_bye = NULL; + mb_data = NULL; + msg_data = NULL; + cap_data = NULL; + ext_data = NULL; + + cur_token = * indx; + + r = mailimap_star_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + type = MAILIMAP_RESP_DATA_TYPE_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_resp_cond_state_parse(fd, buffer, parser_ctx, &cur_token, &cond_state, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_DATA_TYPE_COND_STATE; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_resp_cond_bye_parse(fd, buffer, parser_ctx, &cur_token, &cond_bye, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_DATA_TYPE_COND_BYE; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_mailbox_data_parse(fd, buffer, parser_ctx, &cur_token, &mb_data, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_message_data_parse_progress(fd, buffer, parser_ctx, &cur_token, &msg_data, + progr_rate, progr_fun, body_progr_fun, items_progr_fun, context, msg_att_handler, msg_att_context); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_capability_data_parse(fd, buffer, parser_ctx, &cur_token, &cap_data, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_extension_data_parse(MAILIMAP_EXTENDED_PARSER_RESPONSE_DATA, + fd, buffer, parser_ctx, &cur_token, &ext_data, progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_DATA_TYPE_EXTENSION_DATA; + } + + if (r != MAILIMAP_NO_ERROR) { + if (fd != NULL) { + mailstream_log_error(fd, buffer->str + cur_token, buffer->len - cur_token); + } + res = r; + goto err; + } + + r = mailimap_crlf_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + msg_att_handled = 0; + if (msg_data != NULL) { + if (msg_data->mdt_type == MAILIMAP_MESSAGE_DATA_FETCH) { + if (msg_att_handler != NULL) { + msg_data->mdt_msg_att->att_number = msg_data->mdt_number; + msg_att_handler(msg_data->mdt_msg_att, msg_att_context); + mailimap_message_data_free(msg_data); + msg_data = NULL; + msg_att_handled = 1; + } + } + } + + if (msg_att_handled) { + resp_data = NULL; + } + else { + resp_data = mailimap_response_data_new(type, cond_state, + cond_bye, mb_data, + msg_data, cap_data, ext_data); + if (resp_data == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + } + + * result = resp_data; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (cond_state) + mailimap_resp_cond_state_free(cond_state); + if (cond_bye) + mailimap_resp_cond_bye_free(cond_bye); + if (mb_data) + mailimap_mailbox_data_free(mb_data); + if (msg_data) + mailimap_message_data_free(msg_data); + if (cap_data) + mailimap_capability_data_free(cap_data); + if (ext_data) + mailimap_extension_data_free(ext_data); + err: + return res; +} + +int +mailimap_response_data_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_response_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_response_data_parse_progress(fd, buffer, parser_ctx, indx, result, + progr_rate, progr_fun, + NULL, NULL, NULL, NULL, NULL); +} + +/* + response-done = response-tagged / response-fatal +*/ + +static int +mailimap_response_done_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_response_done ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int type; + struct mailimap_response_done * resp_done; + size_t cur_token; + struct mailimap_response_tagged * tagged; + struct mailimap_response_fatal * fatal; + int r; + int res; + + cur_token = * indx; + + tagged = NULL; + fatal = NULL; + + type = MAILIMAP_RESP_DONE_TYPE_ERROR; /* removes a gcc warning */ + + r = mailimap_response_tagged_parse(fd, buffer, parser_ctx, &cur_token, &tagged, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_DONE_TYPE_TAGGED; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_response_fatal_parse(fd, buffer, parser_ctx, &cur_token, &fatal, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_DONE_TYPE_FATAL; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + resp_done = mailimap_response_done_new(type, tagged, fatal); + if (resp_done == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = resp_done; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (tagged == NULL) + mailimap_response_tagged_free(tagged); + if (fatal == NULL) + mailimap_response_fatal_free(fatal); + err: + return res; +} + +/* + response-fatal = "*" SP resp-cond-bye CRLF + ; Server closes connection immediately +*/ + +static int +mailimap_response_fatal_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_response_fatal ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_resp_cond_bye * cond_bye; + struct mailimap_response_fatal * fatal; + size_t cur_token; + int res; + int r; + + cur_token = * indx; + + r = mailimap_star_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_resp_cond_bye_parse(fd, buffer, parser_ctx, &cur_token, &cond_bye, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_crlf_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + fatal = mailimap_response_fatal_new(cond_bye); + if (fatal == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = fatal; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + mailimap_resp_cond_bye_free(cond_bye); + err: + return res; +} + +/* + response-tagged = tag SP resp-cond-state CRLF +*/ + +static int +mailimap_response_tagged_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_response_tagged ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * tag; + struct mailimap_resp_cond_state * cond_state; + struct mailimap_response_tagged * resp_tagged; + int r; + int res; + + cur_token = * indx; + cond_state = NULL; + + r = mailimap_tag_parse(fd, buffer, parser_ctx, &cur_token, &tag, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_tag; + } + + r = mailimap_resp_cond_state_parse(fd, buffer, parser_ctx, &cur_token, &cond_state, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_tag; + } + + resp_tagged = mailimap_response_tagged_new(tag, cond_state); + if (resp_tagged == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_cond_state; + } + + * result = resp_tagged; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free_cond_state: + mailimap_resp_cond_state_free(cond_state); + free_tag: + mailimap_tag_free(tag); + err: + return res; +} + +/* + resp-cond-auth = ("OK" / "PREAUTH") SP resp-text + ; Authentication condition +*/ + +static int +mailimap_resp_cond_auth_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_resp_cond_auth ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_resp_cond_auth * cond_auth; + size_t cur_token; + struct mailimap_resp_text * text; + int type; + int r; + int res; + + cur_token = * indx; + text = NULL; + + type = MAILIMAP_RESP_COND_AUTH_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "OK"); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_COND_AUTH_OK; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "PREAUTH"); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_COND_AUTH_PREAUTH; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_resp_text_parse(fd, buffer, parser_ctx, &cur_token, &text, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + cond_auth = mailimap_resp_cond_auth_new(type, text); + if (cond_auth == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = cond_auth; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + mailimap_resp_text_free(text); + err: + return res; +} + +/* + resp-cond-bye = "BYE" SP resp-text +*/ + +static int +mailimap_resp_cond_bye_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_resp_cond_bye ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_resp_cond_bye * cond_bye; + struct mailimap_resp_text * text; + int r; + int res; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "BYE"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_resp_text_parse(fd, buffer, parser_ctx, &cur_token, &text, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + cond_bye = mailimap_resp_cond_bye_new(text); + if (cond_bye == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * indx = cur_token; + * result = cond_bye; + + return MAILIMAP_NO_ERROR; + + free: + mailimap_resp_text_free(text); + err: + return res; +} + +/* + resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text + ; Status condition +*/ + +static int +mailimap_resp_cond_state_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_resp_cond_state ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_resp_cond_state * cond_state; + size_t cur_token; + struct mailimap_resp_text * text; + int type; + int r; + int res; + + cur_token = * indx; + text = NULL; + + type = mailimap_resp_cond_state_get_token_value(fd, buffer, &cur_token); + if (type == -1) { + res = MAILIMAP_ERROR_PARSE; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_resp_text_parse(fd, buffer, parser_ctx, &cur_token, &text, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + cond_state = mailimap_resp_cond_state_new(type, text); + if (cond_state == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = cond_state; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + mailimap_resp_text_free(text); + err: + return res; +} + + +/* + resp-specials = "]" +*/ + +static int is_resp_specials(char ch) +{ + switch (ch) { + case ']': + return TRUE; + }; + return FALSE; +} + +/* + resp-text = ["[" resp-text-code "]" SP] text +*/ + +/* "[" resp-text-code "]" */ + +static int +mailimap_resp_text_resp_text_code_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_resp_text_code ** + result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_resp_text_code * text_code; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + r = mailimap_obracket_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + text_code = NULL; + r = mailimap_resp_text_code_parse(fd, buffer, parser_ctx, &cur_token, &text_code, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cbracket_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto free; + } + + * result = text_code; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + mailimap_resp_text_code_free(text_code); + err: + return res; +} + +/* + resp-text = ["[" resp-text-code "]" SP] text +*/ + +static int +mailimap_resp_text_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_resp_text ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_resp_text_code * text_code; + struct mailimap_resp_text * resp_text; + char * text; + int r; + int res; + + cur_token = * indx; + text = NULL; + text_code = NULL; + + r = mailimap_resp_text_resp_text_code_parse(fd, buffer, parser_ctx, &cur_token, + &text_code, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; + + r = mailimap_text_parse(fd, buffer, parser_ctx, &cur_token, &text, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto free_resp_text_code; + } + + resp_text = mailimap_resp_text_new(text_code, text); + if (resp_text == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_text; + } + + * result = resp_text; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free_resp_text_code: + if (text_code != NULL) + mailimap_resp_text_code_free(text_code); + free_text: + mailimap_text_free(text); + return res; +} + +/* + resp-text-code = "ALERT" / + "BADCHARSET" [SP "(" astring *(SP astring) ")" ] / + capability-data / "PARSE" / + "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" / + "READ-ONLY" / "READ-WRITE" / "TRYCREATE" / + "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number / + "UNSEEN" SP nz-number / + atom [SP 1*] +*/ + +/* + ALERT / PARSE / READ-ONLY / READ-WRITE / TRYCREATE +*/ + +static int +mailimap_resp_text_code_1_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + int * result) +{ + int id; + size_t cur_token; + + cur_token = * indx; + + id = mailimap_resp_text_code_1_get_token_value(fd, buffer, &cur_token); + + if (id == -1) + return MAILIMAP_ERROR_PARSE; + + * result = id; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + "BADCHARSET" [SP "(" astring *(SP astring) ")" ] +*/ + +/* + SP "(" astring *(SP astring) ")" +*/ + +static int +mailimap_resp_text_code_badcharset_1_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + clist ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * charset; + int r; + int res; + + cur_token = * indx; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, &cur_token, &charset, + (mailimap_struct_parser *) + mailimap_astring_parse, + (mailimap_struct_destructor *) + mailimap_astring_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto charset; + } + + * indx = cur_token; + * result = charset; + + return MAILIMAP_NO_ERROR; + + charset: + clist_foreach(charset, (clist_func) mailimap_string_free, NULL); + clist_free(charset); + err: + return res; +} + +/* + "BADCHARSET" [SP "(" astring *(SP astring) ")" ] +*/ + +static int +mailimap_resp_text_code_badcharset_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + clist ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * charset; + int r; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "BADCHARSET"); + if (r != MAILIMAP_NO_ERROR) + return r; + + charset = NULL; + + r = mailimap_resp_text_code_badcharset_1_parse(fd, buffer, parser_ctx, &cur_token, + &charset, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; + + * result = charset; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" +*/ + +static int +mailimap_resp_text_code_permanentflags_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + clist ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * flaglist; + int r; + int res; + + cur_token = * indx; + + flaglist = NULL; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "PERMANENTFLAGS"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, &cur_token, &flaglist, + (mailimap_struct_parser *) + mailimap_flag_perm_parse, + (mailimap_struct_destructor *) + mailimap_flag_perm_free, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + * indx = cur_token; + * result = flaglist; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(flaglist, (clist_func) mailimap_flag_perm_free, NULL); + clist_free(flaglist); + err: + return res; +} + + +/* + "UIDNEXT" SP nz-number / + "UIDVALIDITY" SP nz-number / + "UNSEEN" SP nz-number +*/ + +static int +mailimap_resp_text_code_number_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_resp_text_code ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int type; + uint32_t number; + struct mailimap_resp_text_code * resp_text_code; + int r; + + cur_token = * indx; + + resp_text_code = NULL; + + type = mailimap_resp_text_code_2_get_token_value(fd, buffer, &cur_token); + if (type == -1) + return MAILIMAP_ERROR_PARSE; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_nz_number_parse(fd, buffer, parser_ctx, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) + return r; + + switch (type) { + case MAILIMAP_RESP_TEXT_CODE_UIDNEXT: + resp_text_code = mailimap_resp_text_code_new(type, NULL, NULL, NULL, + number, 0, 0, NULL , NULL, NULL); + break; + case MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY: + resp_text_code = mailimap_resp_text_code_new(type, NULL, NULL, NULL, + 0, number, 0, NULL , NULL, NULL); + break; + case MAILIMAP_RESP_TEXT_CODE_UNSEEN: + resp_text_code = mailimap_resp_text_code_new(type, NULL, NULL, NULL, + 0, 0, number, NULL , NULL, NULL); + break; + } + + if (resp_text_code == NULL) + return MAILIMAP_ERROR_MEMORY; + + * result = resp_text_code; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + atom [SP 1*] +*/ + +static int is_text_char(char ch); + +/* + any TEXT-CHAR except "]" +*/ + +static int is_text_char_1(char ch) +{ + if (ch == ']') + return FALSE; + return is_text_char(ch); +} + +/* + 1* +*/ + +static int +mailimap_resp_text_code_other_1_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * value; + int r; + + cur_token = * indx; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_resp_text_code_other_2_parse(fd, buffer, parser_ctx, &cur_token, + &value, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = value; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + atom [SP 1*] +*/ + +static int +mailimap_resp_text_code_other_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_resp_text_code ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * atom; + char * value; + struct mailimap_resp_text_code * resp_text_code; + int r; + int res; + + cur_token = * indx; + atom = NULL; + value = NULL; + + r = mailimap_atom_parse(fd, buffer, parser_ctx, &cur_token, &atom, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_resp_text_code_other_1_parse(fd, buffer, parser_ctx, &cur_token, + &value, progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto err; + } + + resp_text_code = mailimap_resp_text_code_new(MAILIMAP_RESP_TEXT_CODE_OTHER, + NULL, NULL, NULL, + 0, 0, 0, atom, value, NULL); + if (resp_text_code == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_value; + } + + * result = resp_text_code; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free_value: + if (value != NULL) + free(value); + mailimap_atom_free(atom); + err: + return res; +} + + + +/* + resp-text-code = "ALERT" / + "BADCHARSET" [SP "(" astring *(SP astring) ")" ] / + capability-data / "PARSE" / + "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" / + "READ-ONLY" / "READ-WRITE" / "TRYCREATE" / + "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number / + "UNSEEN" SP nz-number / + atom [SP 1*] +*/ + +static int +mailimap_resp_text_code_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_resp_text_code ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_resp_text_code * resp_text_code; + clist * badcharset; + clist * permanentflags; + struct mailimap_capability_data * cap_data; + struct mailimap_extension_data * ext_data; + int type; + int r; + int res; + + cur_token = * indx; + + resp_text_code = NULL; + badcharset = NULL; + cap_data = NULL; + ext_data = NULL; + permanentflags = NULL; + + type = MAILIMAP_RESP_TEXT_CODE_OTHER; + r = mailimap_resp_text_code_1_parse(fd, buffer, parser_ctx, &cur_token, &type); + if (r == MAILIMAP_NO_ERROR) { + /* do nothing */ + } + + if (r == MAILIMAP_ERROR_PARSE) { + + r = mailimap_resp_text_code_badcharset_parse(fd, buffer, parser_ctx, &cur_token, + &badcharset, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_TEXT_CODE_BADCHARSET; + } + + if (r == MAILIMAP_ERROR_PARSE) { + + r = mailimap_capability_data_parse(fd, buffer, parser_ctx, &cur_token, + &cap_data, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_resp_text_code_permanentflags_parse(fd, buffer, parser_ctx, &cur_token, + &permanentflags, + progr_rate, + progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_resp_text_code_number_parse(fd, buffer, parser_ctx, &cur_token, + &resp_text_code, + progr_rate, progr_fun); + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_extension_data_parse(MAILIMAP_EXTENDED_PARSER_RESP_TEXT_CODE, + fd, buffer, parser_ctx, &cur_token, &ext_data, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_TEXT_CODE_EXTENSION; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_resp_text_code_other_parse(fd, buffer, parser_ctx, &cur_token, + &resp_text_code, + progr_rate, progr_fun); + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + if (resp_text_code == NULL) { + resp_text_code = mailimap_resp_text_code_new(type, + badcharset, cap_data, + permanentflags, + 0, 0, 0, NULL, NULL, ext_data); + if (resp_text_code == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + } + + * result = resp_text_code; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + +free: + if (permanentflags) { + clist_foreach(permanentflags, + (clist_func) mailimap_flag_perm_free, NULL); + clist_free(permanentflags); + } + if (cap_data) + mailimap_capability_data_free(cap_data); + if (badcharset) { + clist_foreach(badcharset, (clist_func) mailimap_astring_free, NULL); + clist_free(badcharset); + } + if (ext_data) + mailimap_extension_data_free(ext_data); +err: + return res; +} + +/* + UNIMPLEMENTED + search = "SEARCH" [SP "CHARSET" SP astring] 1*(SP search-key) + ; CHARSET argument to MUST be registered with IANA +*/ + +/* + UNIMPLEMENTED + search-key = "ALL" / "ANSWERED" / "BCC" SP astring / + "BEFORE" SP date / "BODY" SP astring / + "CC" SP astring / "DELETED" / "FLAGGED" / + "FROM" SP astring / "KEYWORD" SP flag-keyword / "NEW" / + "OLD" / "ON" SP date / "RECENT" / "SEEN" / + "SINCE" SP date / "SUBJECT" SP astring / + "TEXT" SP astring / "TO" SP astring / + "UNANSWERED" / "UNDELETED" / "UNFLAGGED" / + "UNKEYWORD" SP flag-keyword / "UNSEEN" / + ; Above this line were in [IMAP2] + "DRAFT" / "HEADER" SP header-fld-name SP astring / + "LARGER" SP number / "NOT" SP search-key / + "OR" SP search-key SP search-key / + "SENTBEFORE" SP date / "SENTON" SP date / + "SENTSINCE" SP date / "SMALLER" SP number / + "UID" SP set / "UNDRAFT" / set / + "(" search-key *(SP search-key) ")" +*/ + +/* + section = "[" [section-spec] "]" +*/ + +static int +mailimap_section_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_section ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_section_spec * section_spec; + size_t cur_token; + struct mailimap_section * section; + int r; + int res; + + cur_token = * indx; + + section_spec = NULL; + + r = mailimap_obracket_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_section_spec_parse(fd, buffer, parser_ctx, &cur_token, §ion_spec, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimap_cbracket_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + if (section_spec == NULL) + section = NULL; + else { + section = mailimap_section_new(section_spec); + if (section == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + } + + * result = section; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + mailimap_section_spec_free(section_spec); + err: + return res; +} + +/* + section-msgtext = "HEADER" / "HEADER.FIELDS" [".NOT"] SP header-list / + "TEXT" + ; top-level or MESSAGE/RFC822 part +*/ + +static int +mailimap_section_msgtext_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_section_msgtext ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int type; + struct mailimap_header_list * header_list; + struct mailimap_section_msgtext * msgtext; + int r; + int res; + + cur_token = * indx; + + header_list = NULL; + + type = mailimap_section_msgtext_get_token_value(fd, buffer, &cur_token); + if (type == -1) { + res = MAILIMAP_ERROR_PARSE; + goto err; + } + + if (type == MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS) { + r = mailimap_header_list_parse(fd, buffer, parser_ctx, &cur_token, &header_list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + } + else if (type == MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT) { + r = mailimap_header_list_parse(fd, buffer, parser_ctx, &cur_token, &header_list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + } + + msgtext = mailimap_section_msgtext_new(type, header_list); + if (msgtext == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_header_list; + } + + * result = msgtext; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free_header_list: + if (header_list) + mailimap_header_list_free(header_list); + err: + return res; +} + +/* + section-part = nz-number *("." nz-number) + ; body part nesting +*/ + +static int +mailimap_section_part_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_section_part ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_section_part * section_part; + size_t cur_token; + clist * section_id; + int r; + int res; + + cur_token = * indx; + section_id = NULL; + + r = mailimap_struct_list_parse(fd, buffer, parser_ctx, &cur_token, §ion_id, '.', + (mailimap_struct_parser *) + mailimap_nz_number_alloc_parse, + (mailimap_struct_destructor *) + mailimap_number_alloc_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + section_part = mailimap_section_part_new(section_id); + if (section_part == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_section_id; + } + + * result = section_part; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free_section_id: + clist_foreach(section_id, (clist_func) mailimap_number_alloc_free, NULL); + clist_free(section_id); + err: + return res; +} + +/* + section-spec = section-msgtext / (section-part ["." section-text]) +*/ + +static int +mailimap_section_spec_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_section_spec ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int type; + struct mailimap_section_msgtext * section_msgtext; + struct mailimap_section_part * section_part; + struct mailimap_section_text * section_text; + struct mailimap_section_spec * section_spec; + size_t cur_token; + int r; + int res; + size_t final_token; + + cur_token = * indx; + + section_msgtext = NULL; + section_part = NULL; + section_text = NULL; + + r = mailimap_section_msgtext_parse(fd, buffer, parser_ctx, &cur_token, + §ion_msgtext, + progr_rate, progr_fun); + switch (r) { + case MAILIMAP_NO_ERROR: + type = MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT; + break; + + case MAILIMAP_ERROR_PARSE: + + r = mailimap_section_part_parse(fd, buffer, parser_ctx, &cur_token, + §ion_part, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + final_token = cur_token; + + type = MAILIMAP_SECTION_SPEC_SECTION_PART; + + r = mailimap_dot_parse(fd, buffer, parser_ctx, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + r = mailimap_section_text_parse(fd, buffer, parser_ctx, &cur_token, §ion_text, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) { + final_token = cur_token; + } + else if (r != MAILIMAP_ERROR_PARSE) { + res = r; + goto err; + } + } + else if (r != MAILIMAP_ERROR_PARSE) { + res = r; + goto err; + } + + cur_token = final_token; + break; + + default: + res = r; + goto err; + } + + section_spec = mailimap_section_spec_new(type, section_msgtext, + section_part, section_text); + if (section_spec == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = section_spec; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (section_msgtext) + mailimap_section_msgtext_free(section_msgtext); + if (section_part) + mailimap_section_part_free(section_part); + if (section_text) + mailimap_section_text_free(section_text); + err: + return res; +} + +/* + section-text = section-msgtext / "MIME" + ; text other than actual body part (headers, etc.) +*/ + +static int +mailimap_section_text_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_section_text ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_section_msgtext * section_msgtext; + size_t cur_token; + struct mailimap_section_text * section_text; + int type; + int r; + int res; + + cur_token = * indx; + + section_msgtext = NULL; + + type = MAILIMAP_SECTION_TEXT_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_section_msgtext_parse(fd, buffer, parser_ctx, &cur_token, §ion_msgtext, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT; + + if (r == MAILIMAP_ERROR_PARSE) { + r= mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "MIME"); + + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_SECTION_TEXT_MIME; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + section_text = mailimap_section_text_new(type, section_msgtext); + if (section_text == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = section_text; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (section_msgtext) + mailimap_section_msgtext_free(section_msgtext); + err: + return res; +} + +/* + UNIMPLEMENTED + select = "SELECT" SP mailbox +*/ + +/* + UNIMPLEMENTED + sequence-num = nz-number / "*" + ; * is the largest number in use. For message + ; sequence numbers, it is the number of messages + ; in the mailbox. For unique identifiers, it is + ; the unique identifier of the last message in + ; the mailbox. +*/ + +/* + UNIMPLEMENTED + set = sequence-num / (sequence-num ":" sequence-num) / + (set "," set) + ; Identifies a set of messages. For message + ; sequence numbers, these are consecutive + ; numbers from 1 to the number of messages in + ; the mailbox + ; Comma delimits individual numbers, colon + ; delimits between two numbers inclusive. + ; Example: 2,4:7,9,12:* is 2,4,5,6,7,9,12,13, + ; 14,15 for a mailbox with 15 messages. +*/ + +/* + UNIMPLEMENTED + status = "STATUS" SP mailbox SP "(" status-att *(SP status-att) ")" +*/ + +/* + status-att = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" / + "UNSEEN" +*/ + +int mailimap_status_att_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, int * result) +{ + int type; + size_t cur_token; + + cur_token = * indx; + + type = mailimap_status_att_get_token_value(fd, buffer, &cur_token); + + if (type == -1) + return MAILIMAP_ERROR_PARSE; + + * result = type; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + UNIMPLEMENTED + store = "STORE" SP set SP store-att-flags +*/ + +/* + UNIMPLEMENTED + store-att-flags = (["+" / "-"] "FLAGS" [".SILENT"]) SP + (flag-list / (flag *(SP flag))) +*/ + +/* + string = quoted / literal +*/ + +static int +mailimap_string_parse_progress(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context) +{ + size_t cur_token; + char * string; + int r; + size_t len; + + cur_token = * indx; + + string = NULL; + len = 0; + + r = mailimap_quoted_parse(fd, buffer, parser_ctx, &cur_token, &string, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + len = strlen(string); + else if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_literal_parse_progress(fd, buffer, parser_ctx, &cur_token, &string, &len, + progr_rate, progr_fun, body_progr_fun, items_progr_fun, context, msg_att_handler, msg_att_context); + } + + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = string; + if (result_len != NULL) + * result_len = len; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +int +mailimap_string_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_string_parse_progress(fd, buffer, parser_ctx, indx, result, + result_len, progr_rate, progr_fun, + NULL, NULL, NULL, NULL, NULL); +} + +/* + UNIMPLEMENTED + subscribe = "SUBSCRIBE" SP mailbox +*/ + +/* + tag = 1* +*/ + +/* + any ASTRING-CHAR except "+" +*/ + +static int is_tag_char(char ch) +{ + if (ch == '+') + return FALSE; + return is_astring_char(ch); +} + +/* + tag = 1* +*/ + +static int mailimap_tag_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * tag; + int r; + + cur_token = * indx; + + r = mailimap_custom_string_parse(fd, buffer, parser_ctx, &cur_token, &tag, + is_tag_char); + if (r != MAILIMAP_NO_ERROR) + return r; + + * indx = cur_token; + * result = tag; + + return MAILIMAP_NO_ERROR; +} + +/* + text = 1*TEXT-CHAR +*/ + +static int mailimap_text_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_custom_string_parse(fd, buffer, parser_ctx, indx, result, + is_text_char); +} + + +/* + TEXT-CHAR = +*/ + +static int is_text_char(char ch) +{ + if ((ch == '\r') || (ch == '\n')) + return FALSE; + + return is_char(ch); +} + +/* + time = 2DIGIT ":" 2DIGIT ":" 2DIGIT + ; Hours minutes seconds +*/ + +/* + 2DIGIT +*/ + +static int mailimap_2digit_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, int * result) +{ +#ifndef UNSTRICT_SYNTAX + int digit; + int two_digit; + size_t cur_token; + int r; + + cur_token = * indx; + + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); + if (r != MAILIMAP_NO_ERROR) + return r; + + two_digit = digit; + + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); + if (r != MAILIMAP_NO_ERROR) + return r; + + two_digit = two_digit * 10 + digit; + + * result = two_digit; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +#else + uint32_t number; + size_t cur_token; + int r; + + cur_token = * indx; + + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) + return r; + + * indx = cur_token; + * result = number; + + return MAILIMAP_NO_ERROR; +#endif +} + +/* + time = 2DIGIT ":" 2DIGIT ":" 2DIGIT + ; Hours minutes seconds +*/ + +static int mailimap_time_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + int * phour, int * pmin, int * psec) +{ + size_t cur_token; + int hour; + int min; + int sec; + int r; + + cur_token = * indx; + + r = mailimap_2digit_parse(fd, buffer, parser_ctx, &cur_token, &hour); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_colon_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_2digit_parse(fd, buffer, parser_ctx, &cur_token, &min); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_colon_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_2digit_parse(fd, buffer, parser_ctx, &cur_token, &sec); + if (r != MAILIMAP_NO_ERROR) + return r; + + * phour = hour; + * pmin = min; + * psec = sec; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + UNIMPLEMENTED + uid = "UID" SP (copy / fetch / search / store) + ; Unique identifiers used instead of message + ; sequence numbers +*/ + +/* + uniqueid = nz-number + ; Strictly ascending +*/ + +int mailimap_uniqueid_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, uint32_t * result) +{ + return mailimap_nz_number_parse(fd, buffer, parser_ctx, indx, result); +} + +/* + UNIMPLEMENTED + unsubscribe = "UNSUBSCRIBE" SP mailbox +*/ + +/* + UNIMPLEMENTED + userid = astring +*/ + +/* + UNIMPLEMENTED + x-command = "X" atom +*/ + +/* + zone = ("+" / "-") 4DIGIT + ; Signed four-digit value of hhmm representing + ; hours and minutes east of Greenwich (that is, + ; the amount that the given time differs from + ; Universal Time). Subtracting the timezone + ; from the given time will give the UT form. + ; The Universal Time zone is "+0000". +*/ + +static int mailimap_zone_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, int * result) +{ + size_t cur_token; + uint32_t zone; +#ifndef UNSTRICT_SYNTAX + int i; + int digit; +#endif + int sign; + int r; + + cur_token = * indx; + + sign = 1; + r = mailimap_plus_parse(fd, buffer, parser_ctx, &cur_token); + if (r == MAILIMAP_NO_ERROR) + sign = 1; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_minus_parse(fd, buffer, parser_ctx, &cur_token); + if (r == MAILIMAP_NO_ERROR) + sign = -1; + } + + if (r != MAILIMAP_NO_ERROR) + return r; + +#ifdef UNSTRICT_SYNTAX + r = mailimap_number_parse(fd, buffer, &cur_token, &zone); + if (r != MAILIMAP_NO_ERROR) + return r; +#else + zone = 0; + for(i = 0 ; i < 4 ; i ++) { + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); + if (r != MAILIMAP_NO_ERROR) + return r; + zone = zone * 10 + digit; + } +#endif + + zone *= sign; + + * result = zone; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_uint64_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, uint64_t * result) +{ + size_t cur_token; + int digit; + uint64_t number; + int parsed; + int r; + + cur_token = * indx; + parsed = 0; + + mailimap_space_parse(fd, buffer, &cur_token); + + number = 0; + while (1) { + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); + if (r == MAILIMAP_ERROR_PARSE) + break; + else if (r == MAILIMAP_NO_ERROR) { + number *= 10; + number += digit; + parsed = 1; + } + else + return r; + } + + if (!parsed) + return MAILIMAP_ERROR_PARSE; + + * result = number; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_mod_sequence_value_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, uint64_t * result) +{ + return mailimap_uint64_parse(fd, buffer, parser_ctx, indx, result); +} + +static int mailimap_seq_number_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, uint32_t * result) +{ + int r; + uint32_t value; + size_t cur_token; + + cur_token = * indx; + + r = mailimap_nz_number_parse(fd, buffer, parser_ctx, &cur_token, &value); + if (r == MAILIMAP_NO_ERROR) { + * indx = cur_token; + * result = value; + return MAILIMAP_NO_ERROR; + } + r = mailimap_star_parse(fd, buffer, parser_ctx, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + * indx = cur_token; + * result = 0; + return MAILIMAP_NO_ERROR; + } + + return MAILIMAP_ERROR_PARSE; +} + +static int mailimap_seq_range_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, uint32_t * result_left, uint32_t * result_right) +{ + size_t cur_token; + int r; + uint32_t left; + uint32_t right; + + cur_token = * indx; + r = mailimap_seq_number_parse(fd, buffer, parser_ctx, &cur_token, &left); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + r = mailimap_colon_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + r = mailimap_seq_number_parse(fd, buffer, parser_ctx, &cur_token, &right); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + * indx = cur_token; + * result_left = left; + * result_right = right; + + return MAILIMAP_NO_ERROR; +} + +static int mailimap_set_item_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_set_item ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int r; + uint32_t value; + uint32_t left; + uint32_t right; + size_t cur_token; + + cur_token = * indx; + + r = mailimap_seq_range_parse(fd, buffer, parser_ctx, &cur_token, &left, &right); + if (r == MAILIMAP_NO_ERROR) { + struct mailimap_set_item * item; + + item = mailimap_set_item_new(left, right); + if (item == NULL) { + return MAILIMAP_ERROR_MEMORY; + } + * result = item; + * indx = cur_token; + return MAILIMAP_NO_ERROR; + } + + r = mailimap_seq_number_parse(fd, buffer, parser_ctx, &cur_token, &value); + if (r == MAILIMAP_NO_ERROR) { + struct mailimap_set_item * item; + + item = mailimap_set_item_new(value, value); + if (item == NULL) { + return MAILIMAP_ERROR_MEMORY; + } + * result = item; + * indx = cur_token; + return MAILIMAP_NO_ERROR; + } + + return MAILIMAP_ERROR_PARSE; +} + +int mailimap_set_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, struct mailimap_set ** result) +{ + size_t cur_token; + struct mailimap_set * set; + clist * item_list; + int r; + + cur_token = * indx; + + r = mailimap_struct_list_parse(fd, buffer, parser_ctx, &cur_token, &item_list, + ',', (mailimap_struct_parser *) mailimap_set_item_parse, (mailimap_struct_destructor *)mailimap_set_item_free, + 0, NULL); + if (r != MAILIMAP_NO_ERROR) + return r; + + set = mailimap_set_new(item_list); + if (set == NULL) { + clist_foreach(item_list, (clist_func) mailimap_set_item_free, NULL); + clist_free(item_list); + return MAILIMAP_ERROR_MEMORY; + } + + * indx = cur_token; + * result = set; + + return MAILIMAP_NO_ERROR; +} + +static int has_crlf(MMAPString * buffer, size_t index) +{ + while (index < buffer->len) { + if (buffer->str[index] == '\n') + return 1; + index ++; + } + return 0; +} + diff --git a/Sources/libetpan/low-level/imap/mailimap_parser.h b/Sources/libetpan/low-level/imap/mailimap_parser.h new file mode 100644 index 00000000..fa4fbc56 --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_parser.h @@ -0,0 +1,221 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_parser.h,v 1.17 2011/03/30 13:29:49 hoa Exp $ + */ + +#ifndef MAILIMAP_PARSER_H + +#define MAILIMAP_PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_types.h" + +int mailimap_greeting_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_greeting ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_response_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_response ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_response_parse_with_context(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_response ** result, + mailprogress_function * body_progr_fun, + mailprogress_function * items_progr_fun, + void * context, + mailimap_msg_att_handler * msg_att_handler, + void * msg_att_context); + +int +mailimap_continue_req_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_continue_req ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_response_data_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_response_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +typedef int mailimap_struct_parser(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, void * result, + size_t progr_rate, + progress_function * progr_fun); + +typedef void mailimap_struct_destructor(void * result); + +int +mailimap_mailbox_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); +int +mailimap_mailbox_list_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_mailbox_list ** result, + size_t progr_rate, + progress_function * progr_fun); + +int mailimap_nstring_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_string_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_struct_spaced_list_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, clist ** result, + mailimap_struct_parser * parser, + mailimap_struct_destructor * destructor, + size_t progr_rate, + progress_function * progr_fun); + +int mailimap_oparenth_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx); + +int mailimap_cparenth_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx); + +int mailimap_atom_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_astring_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + char ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_number_parse(mailstream * fd, MMAPString * buffer, + size_t * indx, uint32_t * result); + +int +mailimap_nz_number_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, uint32_t * result); + +int +mailimap_struct_list_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, clist ** result, + char symbol, + mailimap_struct_parser * parser, + mailimap_struct_destructor * destructor, + size_t progr_rate, + progress_function * progr_fun); + +int mailimap_uniqueid_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, uint32_t * result); + +int mailimap_colon_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx); + +int mailimap_dquote_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx); + +int +mailimap_quoted_char_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char * result); + +int mailimap_nil_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx); + +int +mailimap_struct_multiple_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, clist ** result, + mailimap_struct_parser * parser, + mailimap_struct_destructor * destructor, + size_t progr_rate, + progress_function * progr_fun); + +int mailimap_capability_data_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_capability_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +int mailimap_capability_list_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + clist ** result, + size_t progr_rate, + progress_function * progr_fun); + +int mailimap_status_att_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, int * result); + +int mailimap_nz_number_alloc_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + uint32_t ** result, + size_t progr_rate, + progress_function * progr_fun); + +int mailimap_mod_sequence_value_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, uint64_t * result); + +int mailimap_uint64_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, uint64_t * result); + +int mailimap_set_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, struct mailimap_set ** result); + +LIBETPAN_EXPORT +int mailimap_hack_date_time_parse(char * str, + struct mailimap_date_time ** result, + size_t progr_rate, + progress_function * progr_fun); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/mailimap_print.c b/Sources/libetpan/low-level/imap/mailimap_print.c new file mode 100644 index 00000000..49281350 --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_print.c @@ -0,0 +1,1619 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_print.c,v 1.15 2008/02/17 13:13:28 hoa Exp $ + */ +#ifdef DEBUG +#include "mailimap_print.h" + +#include + +static void mailimap_body_fields_print(struct mailimap_body_fields * + body_fields); +static void mailimap_envelope_print(struct mailimap_envelope * env); +static void mailimap_body_print(struct mailimap_body * body); +static void mailimap_body_fld_enc_print(struct mailimap_body_fld_enc * + fld_enc); + +static int indent_size = 0; + +static void indent() +{ + indent_size ++; +} + +static void unindent() +{ + indent_size --; +} + +static void print_indent() +{ + int i; + + for (i = 0 ; i < indent_size ; i++) + printf(" "); +} + + +static void mailimap_body_fld_lang_print(struct mailimap_body_fld_lang * + fld_lang) +{ + clistiter * cur; + + print_indent(); + printf("body-fld-lang { "); + + switch (fld_lang->lg_type) { + case MAILIMAP_BODY_FLD_LANG_SINGLE: + printf("%s ", fld_lang->lg_data.lg_single); + break; + + case MAILIMAP_BODY_FLD_LANG_LIST: + for(cur = clist_begin(fld_lang->lg_data.lg_list) ; + cur != NULL ; cur = clist_next(cur)) { + char * lang; + + lang = clist_content(cur); + + printf("%s ", lang); + } + break; + } + + print_indent(); + printf("}\n"); +} + +static void +mailimap_single_body_fld_param_print(struct mailimap_single_body_fld_param * + single) +{ + printf("(%s = %s)", single->pa_name, single->pa_value); +} + +static void mailimap_body_fld_param_print(struct mailimap_body_fld_param * + fld_param) +{ + clistiter * cur; + + print_indent(); + printf("body-fld-param { "); + + for(cur = clist_begin(fld_param->pa_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_single_body_fld_param * single; + + single = clist_content(cur); + + mailimap_single_body_fld_param_print(single); + printf(" "); + } + printf("\n"); +} + +static void mailimap_body_fld_dsp_print(struct mailimap_body_fld_dsp * fld_dsp) +{ + print_indent(); + printf("body-fld-dsp {\n"); + indent(); + + print_indent(); + printf("name { %s }\n", fld_dsp->dsp_type); + + mailimap_body_fld_param_print(fld_dsp->dsp_attributes); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_body_extension_list_print(clist * ext_list); + +static void mailimap_body_extension_print(struct mailimap_body_extension * ext) +{ + print_indent(); + printf("body-extention {\n"); + indent(); + + switch (ext->ext_type) { + case MAILIMAP_BODY_EXTENSION_NSTRING: + print_indent(); + printf("%s\n", ext->ext_data.ext_nstring); + break; + case MAILIMAP_BODY_EXTENSION_NUMBER: + print_indent(); + printf("%i\n", ext->ext_data.ext_number); + break; + case MAILIMAP_BODY_EXTENSION_LIST: + mailimap_body_extension_list_print(ext->ext_data.ext_body_extension_list); + break; + } + + unindent(); + print_indent(); + printf("}\n"); + +} + +static void mailimap_body_extension_list_print(clist * ext_list) +{ + clistiter * cur; + + print_indent(); + printf("body-extention-list {\n"); + indent(); + + for (cur = clist_begin(ext_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_body_extension * ext; + + ext = clist_content(cur); + + mailimap_body_extension_print(ext); + } + + unindent(); + print_indent(); + printf("}"); +} + +static void mailimap_body_ext_1part_print(struct mailimap_body_ext_1part * + body_ext_1part) +{ + print_indent(); + printf("body-type-1part {\n"); + indent(); + + print_indent(); + printf("md5 { %s }\n", body_ext_1part->bd_md5); + if (body_ext_1part->bd_disposition) { + mailimap_body_fld_dsp_print(body_ext_1part->bd_disposition); + if (body_ext_1part->bd_language) { + mailimap_body_fld_lang_print(body_ext_1part->bd_language); + + if (body_ext_1part->bd_extension_list) + mailimap_body_extension_list_print(body_ext_1part->bd_extension_list); + } + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_body_type_text_print(struct mailimap_body_type_text * + body_type_text) +{ + print_indent(); + printf("body-type-text {\n"); + indent(); + + print_indent(); + printf("media-text { %s }\n", body_type_text->bd_media_text); + mailimap_body_fields_print(body_type_text->bd_fields); + print_indent(); + printf("lines { %i }\n", body_type_text->bd_lines); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_body_type_msg_print(struct mailimap_body_type_msg * + body_type_msg) +{ + print_indent(); + printf("body-type-msg {\n"); + indent(); + + mailimap_body_fields_print(body_type_msg->bd_fields); + mailimap_envelope_print(body_type_msg->bd_envelope); + mailimap_body_print(body_type_msg->bd_body); + + print_indent(); + printf("lines { %i }\n", body_type_msg->bd_lines); + + unindent(); + print_indent(); + printf("}\n"); +} + + +static void mailimap_body_fld_enc_print(struct mailimap_body_fld_enc * fld_enc) +{ + print_indent(); + printf("body-fld-enc { "); + + switch (fld_enc->enc_type) { + case MAILIMAP_BODY_FLD_ENC_7BIT: + print_indent(); + printf("7bit"); + break; + case MAILIMAP_BODY_FLD_ENC_8BIT: + printf("8bit"); + break; + case MAILIMAP_BODY_FLD_ENC_BINARY: + printf("binary"); + break; + case MAILIMAP_BODY_FLD_ENC_BASE64: + printf("base64"); + break; + case MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE: + printf("quoted-printable"); + break; + case MAILIMAP_BODY_FLD_ENC_OTHER: + printf("%s", fld_enc->enc_value); + break; + } + + printf("}\n"); +} + +static void mailimap_body_fields_print(struct mailimap_body_fields * + body_fields) +{ + print_indent(); + printf("body-fields {\n"); + indent(); + + mailimap_body_fld_param_print(body_fields->bd_parameter); + + print_indent(); + printf("body-fld-id { %s }\n", body_fields->bd_id); + printf("body-fld-desc { %s }\n", body_fields->bd_description); + mailimap_body_fld_enc_print(body_fields->bd_encoding); + printf("body-fld-octets { %i }\n", body_fields->bd_size); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_media_basic_print(struct mailimap_media_basic * + media_basic) +{ + print_indent(); + printf("media-basic {"); + + switch (media_basic->med_type) { + case MAILIMAP_MEDIA_BASIC_APPLICATION: + printf("application"); + break; + case MAILIMAP_MEDIA_BASIC_AUDIO: + printf("audio"); + break; + case MAILIMAP_MEDIA_BASIC_IMAGE: + printf("image"); + break; + case MAILIMAP_MEDIA_BASIC_MESSAGE: + printf("message"); + break; + case MAILIMAP_MEDIA_BASIC_VIDEO: + printf("video"); + break; + case MAILIMAP_MEDIA_BASIC_OTHER: + printf("%s", media_basic->med_basic_type); + break; + } + printf(" / %s }\n", media_basic->med_subtype); +} + +static void mailimap_body_type_basic_print(struct mailimap_body_type_basic * + body_type_basic) +{ + print_indent(); + printf("body-type-basic {\n"); + indent(); + + mailimap_media_basic_print(body_type_basic->bd_media_basic); + mailimap_body_fields_print(body_type_basic->bd_fields); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_body_type_1part_print(struct mailimap_body_type_1part * + body_type_1part) +{ + print_indent(); + printf("body-type-1part {\n"); + indent(); + + switch (body_type_1part->bd_type) { + case MAILIMAP_BODY_TYPE_1PART_BASIC: + mailimap_body_type_basic_print(body_type_1part->bd_data.bd_type_basic); + break; + + case MAILIMAP_BODY_TYPE_1PART_MSG: + mailimap_body_type_msg_print(body_type_1part->bd_data.bd_type_msg); + break; + + case MAILIMAP_BODY_TYPE_1PART_TEXT: + mailimap_body_type_text_print(body_type_1part->bd_data.bd_type_text); + break; + } + + if (body_type_1part->bd_ext_1part != NULL) + mailimap_body_ext_1part_print(body_type_1part->bd_ext_1part); + + unindent(); + print_indent(); + printf("\n"); +} + +static void mailimap_body_ext_mpart(struct mailimap_body_ext_mpart * ext_mpart) +{ + print_indent(); + printf("body-ext-mpart {\n"); + indent(); + + mailimap_body_fld_param_print(ext_mpart->bd_parameter); + if (ext_mpart->bd_disposition) { + mailimap_body_fld_dsp_print(ext_mpart->bd_disposition); + if (ext_mpart->bd_language) { + mailimap_body_fld_lang_print(ext_mpart->bd_language); + + if (ext_mpart->bd_extension_list) + mailimap_body_extension_list_print(ext_mpart->bd_extension_list); + } + } + + unindent(); + print_indent(); + printf("\n"); +} + +static void mailimap_body_type_mpart_print(struct mailimap_body_type_mpart * + mpart) +{ + clistiter * cur; + + print_indent(); + printf("body-type-mpart {\n"); + indent(); + + for(cur = clist_begin(mpart->bd_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_body * body; + + body = clist_content(cur); + + mailimap_body_print(body); + } + + printf("media-subtype { %s }\n", mpart->bd_media_subtype); + + if (mpart->bd_ext_mpart) + mailimap_body_ext_mpart(mpart->bd_ext_mpart); + + unindent(); + print_indent(); + printf("}\n"); +} + + +static void mailimap_body_print(struct mailimap_body * body) +{ + print_indent(); + printf("body {\n"); + indent(); + + switch (body->bd_type) { + case MAILIMAP_BODY_1PART: + mailimap_body_type_1part_print(body->bd_data.bd_body_1part); + break; + case MAILIMAP_BODY_MPART: + mailimap_body_type_mpart_print(body->bd_data.bd_body_mpart); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_date_time_print(struct mailimap_date_time * date_time) +{ + print_indent(); + printf("date-time { %i/%i/%i - %i:%i:%i %i }\n", + date_time->dt_day, date_time->dt_month, date_time->dt_year, + date_time->dt_hour, date_time->dt_min, date_time->dt_month, + date_time->dt_zone); +} + +static void mailimap_address_print(struct mailimap_address * address) +{ + print_indent(); + printf("address { name: %s, addr: %s, mailbox: %s, host: %s) }\n", + address->ad_personal_name, address->ad_source_route, + address->ad_mailbox_name, address->ad_host_name); +} + +static void mailimap_envelope_address_list_print(clist * address) +{ + clistiter * cur; + + print_indent(); + printf("envelope-address-list {\n"); + indent(); + + for(cur = clist_begin(address) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_address * addr; + + addr = clist_content(cur); + + mailimap_address_print(addr); + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_envelope_print(struct mailimap_envelope * env) +{ + print_indent(); + printf("envelope {\n"); + indent(); + + print_indent(); + printf("date { %s }\n", env->env_date); + + print_indent(); + printf("subject { %s }\n", env->env_subject); + + print_indent(); + printf("from {\n"); + indent(); + mailimap_envelope_address_list_print(env->env_from->frm_list); + unindent(); + print_indent(); + printf("}\n"); + + print_indent(); + printf("sender {\n"); + indent(); + mailimap_envelope_address_list_print(env->env_sender->snd_list); + unindent(); + print_indent(); + printf("}\n"); + + print_indent(); + printf("reply-to {\n"); + indent(); + mailimap_envelope_address_list_print(env->env_reply_to->rt_list); + unindent(); + print_indent(); + printf("}\n"); + + print_indent(); + printf("to {\n"); + indent(); + mailimap_envelope_address_list_print(env->env_to->to_list); + unindent(); + print_indent(); + printf("}\n"); + + print_indent(); + printf("cc {\n"); + indent(); + mailimap_envelope_address_list_print(env->env_cc->cc_list); + unindent(); + print_indent(); + printf("}\n"); + + print_indent(); + printf("bcc {\n"); + indent(); + mailimap_envelope_address_list_print(env->env_bcc->bcc_list); + unindent(); + print_indent(); + printf("}\n"); + + printf("in-reply-to { %s }\n", env->env_in_reply_to); + printf("message-id { %s }\n", env->env_message_id); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_header_list_print(struct mailimap_header_list * + header_list) +{ + clistiter * cur; + + print_indent(); + printf("header-list { "); + for(cur = clist_begin(header_list->hdr_list) ; cur != NULL ; + cur = clist_next(cur)) + printf("%s ", (char *) clist_content(cur)); + printf("}\n"); +} + +static void mailimap_section_msgtext_print(struct mailimap_section_msgtext * + section_msgtext) +{ + print_indent(); + printf("section-msgtext {\n"); + indent(); + + switch(section_msgtext->sec_type) { + case MAILIMAP_SECTION_MSGTEXT_HEADER: + print_indent(); + printf("header\n"); + break; + + case MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS: + print_indent(); + printf("header fields {"); + indent(); + mailimap_header_list_print(section_msgtext->sec_header_list); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT: + print_indent(); + printf("header fields not {"); + indent(); + mailimap_header_list_print(section_msgtext->sec_header_list); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_SECTION_MSGTEXT_TEXT: + print_indent(); + printf("text\n"); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_section_part_print(struct mailimap_section_part * + section_part) +{ + clistiter * cur; + + print_indent(); + printf("section-part { "); + + for(cur = clist_begin(section_part->sec_id) ; + cur != NULL ; cur = clist_next(cur)) { + printf("%i", * ((uint32_t *) clist_content(cur))); + if (clist_next(cur) != NULL) + printf("."); + } + printf(" }\n"); +} + +static void mailimap_section_text_print(struct mailimap_section_text * + section_text) +{ + print_indent(); + printf("section-text {\n"); + indent(); + + switch (section_text->sec_type) { + case MAILIMAP_SECTION_TEXT_MIME: + print_indent(); + printf("MIME"); + break; + case MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT: + mailimap_section_msgtext_print(section_text->sec_msgtext); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_section_spec_print(struct mailimap_section_spec * + section_spec) +{ + print_indent(); + printf("section-spec {"); + indent(); + + switch(section_spec->sec_type) { + case MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT: + mailimap_section_msgtext_print(section_spec->sec_data.sec_msgtext); + break; + case MAILIMAP_SECTION_SPEC_SECTION_PART: + mailimap_section_part_print(section_spec->sec_data.sec_part); + if (section_spec->sec_text != NULL) + mailimap_section_text_print(section_spec->sec_text); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_section_print(struct mailimap_section * section) +{ + print_indent(); + printf("section {\n"); + indent(); + + if (section != NULL) + if (section->sec_spec != NULL) + mailimap_section_spec_print(section->sec_spec); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_msg_att_body_section_print(struct + mailimap_msg_att_body_section * + msg_att_body_section) +{ + print_indent(); + printf("msg-att-body-section {\n"); + indent(); + + mailimap_section_print(msg_att_body_section->sec_section); + printf("origin-octet: %i\n", msg_att_body_section->sec_origin_octet); + printf("body-part: %s\n", msg_att_body_section->sec_body_part); + + unindent(); + print_indent(); + printf("}\n"); +} + + +static void mailimap_msg_att_static_print(struct mailimap_msg_att_static * + msg_att_static) +{ + print_indent(); + printf("msg-att-static {\n"); + indent(); + + switch (msg_att_static->att_type) { + + case MAILIMAP_MSG_ATT_ENVELOPE: + print_indent(); + printf("envelope {\n"); + indent(); + print_indent(); + mailimap_envelope_print(msg_att_static->att_data.att_env); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_INTERNALDATE: + print_indent(); + printf("internaldate {\n"); + indent(); + print_indent(); + mailimap_date_time_print(msg_att_static->att_data.att_internal_date); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_RFC822: + print_indent(); + printf("rfc822 {\n"); + printf("%s\n", msg_att_static->att_data.att_rfc822.att_content); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_RFC822_HEADER: + print_indent(); + printf("rfc822-header {\n"); + printf("%s\n", msg_att_static->att_data.att_rfc822_header.att_content); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_RFC822_TEXT: + print_indent(); + printf("rfc822-text {\n"); + printf("%s\n", msg_att_static->att_data.att_rfc822_text.att_content); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_RFC822_SIZE: + print_indent(); + printf("rfc822-size { %i }\n", msg_att_static->att_data.att_rfc822_size); + break; + + case MAILIMAP_MSG_ATT_BODY: + print_indent(); + printf("body {\n"); + indent(); + print_indent(); + mailimap_body_print(msg_att_static->att_data.att_body); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_BODYSTRUCTURE: + print_indent(); + printf("bodystructure {\n"); + indent(); + print_indent(); + mailimap_body_print(msg_att_static->att_data.att_bodystructure); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_BODY_SECTION: + print_indent(); + printf("body-section {\n"); + indent(); + print_indent(); + mailimap_msg_att_body_section_print(msg_att_static->att_data.att_body_section); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_UID: + printf("uid { %i }\n", msg_att_static->att_data.att_uid); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_flag_print(struct mailimap_flag * flag); + +static void mailimap_flag_fetch_print(struct mailimap_flag_fetch * flag) +{ + print_indent(); + printf("flag fetch {\n"); + indent(); + + switch (flag->fl_type) { + case MAILIMAP_FLAG_FETCH_RECENT: + printf("recent\n"); + break; + case MAILIMAP_FLAG_FETCH_OTHER: + print_indent(); + printf("flag {\n"); + indent(); + mailimap_flag_print(flag->fl_flag); + unindent(); + print_indent(); + printf("}\n"); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_msg_att_dynamic_print(struct mailimap_msg_att_dynamic * + dynamic) +{ + clistiter * cur; + + print_indent(); + printf("msg-att-dynamic {\n"); + indent(); + + for(cur = clist_begin(dynamic->att_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_flag_fetch * flag; + + flag = (struct mailimap_flag_fetch *) clist_content(cur); + mailimap_flag_fetch_print(flag); + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_msg_att_item_print(struct mailimap_msg_att_item * item) +{ + print_indent(); + printf("msg-att-item {\n"); + indent(); + + switch (item->att_type) { + case MAILIMAP_MSG_ATT_ITEM_DYNAMIC: + mailimap_msg_att_dynamic_print(item->att_data.att_dyn); + break; + case MAILIMAP_MSG_ATT_ITEM_STATIC: + mailimap_msg_att_static_print(item->att_data.att_static); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_msg_att_print(struct mailimap_msg_att * msg_att) +{ + clistiter * cur; + + print_indent(); + printf("msg-att {\n"); + indent(); + + for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_msg_att_item * item; + + item = clist_content(cur); + + mailimap_msg_att_item_print(item); + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_message_data_print(struct mailimap_message_data * + msg_data) +{ + print_indent(); + printf("message-data {\n"); + indent(); + + switch (msg_data->mdt_type) { + case MAILIMAP_MESSAGE_DATA_EXPUNGE: + print_indent(); + printf("expunged { %i }\n", msg_data->mdt_number); + break; + case MAILIMAP_MESSAGE_DATA_FETCH: + print_indent(); + printf("message-number { %i }\n", msg_data->mdt_number); + mailimap_msg_att_print(msg_data->mdt_msg_att); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_status_att_print(int status_att) +{ + print_indent(); + printf("status-att { "); + + switch(status_att) { + case MAILIMAP_STATUS_ATT_MESSAGES: + printf("messages"); + break; + case MAILIMAP_STATUS_ATT_RECENT: + printf("recent"); + break; + case MAILIMAP_STATUS_ATT_UIDNEXT: + printf("uidnext"); + break; + case MAILIMAP_STATUS_ATT_UIDVALIDITY: + printf("status att uidvalidity"); + break; + case MAILIMAP_STATUS_ATT_UNSEEN: + printf("status att unseen"); + break; + } + + printf(" \n"); +} + +static void +mailimap_status_info_print(struct mailimap_status_info * info) +{ + print_indent(); + printf("status-info {\n"); + indent(); + + mailimap_status_att_print(info->st_att); + + print_indent(); + printf("value { %i }\n", info->st_value); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void +mailimap_mailbox_data_status_print(struct mailimap_mailbox_data_status * + mb_data_status) +{ + clistiter * cur; + + print_indent(); + printf("mailbox-data-status {\n"); + indent(); + + print_indent(); + printf("mailbox { %s }\n", mb_data_status->st_mailbox); + + for(cur = clist_begin(mb_data_status->st_info_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailimap_status_info * info; + + info = clist_content(cur); + + mailimap_status_info_print(info); + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_mbx_list_oflag_print(struct mailimap_mbx_list_oflag * + oflag) +{ + print_indent(); + printf("mbx-list-oflag { "); + + switch (oflag->of_type) { + case MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS: + printf("noinferiors"); + break; + case MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT: + printf("%s", oflag->of_flag_ext); + break; + } + + printf(" }\n"); +} + +static void mailimap_mbx_list_sflag_print(int sflag) +{ + print_indent(); + printf("mbx-list-sflag { "); + + switch (sflag) { + case MAILIMAP_MBX_LIST_SFLAG_MARKED: + printf("marked"); + break; + case MAILIMAP_MBX_LIST_SFLAG_NOSELECT: + printf("noselected"); + break; + case MAILIMAP_MBX_LIST_SFLAG_UNMARKED: + printf("unmarked"); + break; + } + + printf(" }\n"); +} + +static void mailimap_mbx_list_flags_print(struct mailimap_mbx_list_flags * + mbx_list_flags) +{ + clistiter * cur; + + print_indent(); + printf("mbx-list-flags {"); + indent(); + + if (mbx_list_flags->mbf_type == MAILIMAP_MBX_LIST_FLAGS_SFLAG) + mailimap_mbx_list_sflag_print(mbx_list_flags->mbf_sflag); + + for(cur = clist_begin(mbx_list_flags->mbf_oflags) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_mbx_list_oflag * oflag; + + oflag = clist_content(cur); + + mailimap_mbx_list_oflag_print(oflag); + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_mailbox_list_print(struct mailimap_mailbox_list * mb_list) +{ + print_indent(); + printf("mailbox-list {\n"); + indent(); + + mailimap_mbx_list_flags_print(mb_list->mb_flag); + printf("dir-separator { %c }\n", mb_list->mb_delimiter); + printf("mailbox { %s }\n", mb_list->mb_name); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_flag_list_print(struct mailimap_flag_list * flag_list) +{ + clistiter * cur; + + print_indent(); + printf("flag-list {\n"); + indent(); + + for(cur = clist_begin(flag_list->fl_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_flag * flag; + + flag = clist_content(cur); + + print_indent(); + mailimap_flag_print(flag); + printf("\n"); + } + + unindent(); + print_indent(); + printf("}\n"); +} + + +static void mailimap_mailbox_data_print(struct mailimap_mailbox_data * mb_data) +{ + clistiter * cur; + + print_indent(); + printf("mailbox-data {\n"); + indent(); + + switch (mb_data->mbd_type) { + case MAILIMAP_MAILBOX_DATA_FLAGS: + print_indent(); + printf("flags {\n"); + indent(); + mailimap_flag_list_print(mb_data->mbd_data.mbd_flags); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MAILBOX_DATA_LIST: + print_indent(); + printf("list {\n"); + indent(); + mailimap_mailbox_list_print(mb_data->mbd_data.mbd_list); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MAILBOX_DATA_LSUB: + print_indent(); + printf("lsub {\n"); + indent(); + mailimap_mailbox_list_print(mb_data->mbd_data.mbd_lsub); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MAILBOX_DATA_SEARCH: + print_indent(); + printf("search { "); + for(cur = clist_begin(mb_data->mbd_data.mbd_search) ; + cur != NULL ; cur = clist_next(cur)) { + uint32_t * id; + + id = clist_content(cur); + printf("%i ", * id); + } + printf(" }\n"); + break; + + case MAILIMAP_MAILBOX_DATA_STATUS: + print_indent(); + printf("status {\n"); + indent(); + mailimap_mailbox_data_status_print(mb_data->mbd_data.mbd_status); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MAILBOX_DATA_EXISTS: + print_indent(); + printf("exists { %i }\n", mb_data->mbd_data.mbd_exists); + break; + + case MAILIMAP_MAILBOX_DATA_RECENT: + print_indent(); + printf("recent { %i }\n", mb_data->mbd_data.mbd_recent); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void +mailimap_resp_text_code_print(struct mailimap_resp_text_code * text_code); + +static void mailimap_resp_text_print(struct mailimap_resp_text * resp_text); + +static void mailimap_resp_cond_bye_print(struct mailimap_resp_cond_bye * + resp_cond_bye) +{ + print_indent(); + printf("resp-cond-bye {\n"); + indent(); + mailimap_resp_text_print(resp_cond_bye->rsp_text); + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_resp_cond_state_print(struct mailimap_resp_cond_state * + resp_cond_state) +{ + print_indent(); + printf("resp-cond-state {\n"); + indent(); + + switch(resp_cond_state->rsp_type) { + case MAILIMAP_RESP_COND_STATE_OK: + print_indent(); + printf("OK\n"); + break; + case MAILIMAP_RESP_COND_STATE_NO: + print_indent(); + printf("NO\n"); + break; + case MAILIMAP_RESP_COND_STATE_BAD: + print_indent(); + printf("BAD\n"); + break; + } + + mailimap_resp_text_print(resp_cond_state->rsp_text); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_capability_data_print(struct mailimap_capability_data * + cap_data); + +static void mailimap_response_data_print(struct mailimap_response_data * + resp_data) +{ + print_indent(); + printf("response-data {\n"); + indent(); + + switch (resp_data->rsp_type) { + case MAILIMAP_RESP_DATA_TYPE_COND_STATE: + mailimap_resp_cond_state_print(resp_data->rsp_data.rsp_cond_state); + break; + case MAILIMAP_RESP_DATA_TYPE_COND_BYE: + mailimap_resp_cond_bye_print(resp_data->rsp_data.rsp_bye); + break; + case MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA: + mailimap_mailbox_data_print(resp_data->rsp_data.rsp_mailbox_data); + break; + case MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA: + mailimap_message_data_print(resp_data->rsp_data.rsp_message_data); + break; + case MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA: + mailimap_capability_data_print(resp_data->rsp_data.rsp_capability_data); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_flag_print(struct mailimap_flag * flag) +{ + printf("flag { "); + + switch (flag->fl_type) { + case MAILIMAP_FLAG_ANSWERED: + printf("answered"); + break; + + case MAILIMAP_FLAG_FLAGGED: + printf("flagged"); + break; + + case MAILIMAP_FLAG_DELETED: + printf("deleted"); + break; + + case MAILIMAP_FLAG_SEEN: + printf("seen"); + break; + + case MAILIMAP_FLAG_DRAFT: + printf("flag draft"); + break; + + case MAILIMAP_FLAG_KEYWORD: + printf("keyword { %s }", flag->fl_data.fl_keyword); + break; + + case MAILIMAP_FLAG_EXTENSION: + printf("extention { %s }", flag->fl_data.fl_extension); + break; + } + + printf(" }"); +} + +static void mailimap_flag_perm_print(struct mailimap_flag_perm * flag_perm) +{ + print_indent(); + printf("flag-perm { "); + + switch (flag_perm->fl_type) { + case MAILIMAP_FLAG_PERM_FLAG: + mailimap_flag_print(flag_perm->fl_flag); + break; + + case MAILIMAP_FLAG_PERM_ALL: + printf("all"); + break; + } + + printf(" }\n"); +} + +static void mailimap_capability_print(struct mailimap_capability * cap) +{ + print_indent(); + printf("capability { "); + + switch (cap->cap_type) { + case MAILIMAP_CAPABILITY_AUTH_TYPE: + printf("auth { %s }", cap->cap_data.cap_auth_type); + break; + case MAILIMAP_CAPABILITY_NAME: + printf("atom { %s }", cap->cap_data.cap_name); + break; + } + + printf(" }\n"); +} + +static void mailimap_capability_data_print(struct mailimap_capability_data * + cap_data) +{ + clistiter * cur; + + print_indent(); + printf("capability-data {\n"); + indent(); + + for(cur = clist_begin(cap_data->cap_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_capability * cap; + + cap = clist_content(cur); + + mailimap_capability_print(cap); + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void +mailimap_resp_text_code_print(struct mailimap_resp_text_code * text_code) +{ + clistiter * cur; + + print_indent(); + printf("resp-text-code {\n"); + indent(); + + switch (text_code->rc_type) { + case MAILIMAP_RESP_TEXT_CODE_BADCHARSET: + print_indent(); + printf("badcharset { "); + for(cur = clist_begin(text_code->rc_data.rc_badcharset) ; cur != NULL ; + cur = clist_next(cur)) + printf("%s ", (char *) clist_content(cur)); + printf("}\n"); + break; + + case MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA: + print_indent(); + printf("capability {\n"); + indent(); + mailimap_capability_data_print(text_code->rc_data.rc_cap_data); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS: + print_indent(); + printf("permanent-flags {\n"); + indent(); + cur = clist_begin(text_code->rc_data.rc_perm_flags); + while (cur != NULL) { + mailimap_flag_perm_print(clist_content(cur)); + cur = clist_next(cur); + } + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_RESP_TEXT_CODE_READ_ONLY: + print_indent(); + printf("readonly\n"); + break; + + case MAILIMAP_RESP_TEXT_CODE_READ_WRITE: + print_indent(); + printf("readwrite\n"); + break; + + case MAILIMAP_RESP_TEXT_CODE_TRY_CREATE: + print_indent(); + printf("trycreate\n"); + break; + + case MAILIMAP_RESP_TEXT_CODE_UIDNEXT: + print_indent(); + printf("uidnext { %i }\n", text_code->rc_data.rc_uidnext); + break; + + case MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY: + print_indent(); + printf("uidvalidity { %i }\n", text_code->rc_data.rc_uidvalidity); + break; + + case MAILIMAP_RESP_TEXT_CODE_UNSEEN: + print_indent(); + printf("unseen { %i }\n", text_code->rc_data.rc_first_unseen); + break; + + case MAILIMAP_RESP_TEXT_CODE_OTHER: + print_indent(); + printf("other { %s = %s }\n", + text_code->rc_data.rc_atom.atom_name, + text_code->rc_data.rc_atom.atom_value); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_resp_text_print(struct mailimap_resp_text * resp_text) +{ + print_indent(); + printf("resp-text {\n"); + indent(); + + if (resp_text->rsp_code) + mailimap_resp_text_code_print(resp_text->rsp_code); + print_indent(); + printf("text { %s }\n", resp_text->rsp_text); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_continue_req_print(struct mailimap_continue_req * + cont_req) +{ + print_indent(); + printf("continue-req {\n"); + indent(); + + switch (cont_req->cr_type) { + case MAILIMAP_CONTINUE_REQ_TEXT: + print_indent(); + printf("resp-text {\n"); + indent(); + mailimap_resp_text_print(cont_req->cr_data.cr_text); + unindent(); + print_indent(); + printf("}\n"); + break; + case MAILIMAP_CONTINUE_REQ_BASE64: + printf("base64 { %s }\n", cont_req->cr_data.cr_base64); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_cont_req_or_resp_data_print(struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data) +{ + print_indent(); + printf("cont-req-or-resp-data {\n"); + indent(); + + switch (cont_req_or_resp_data->rsp_type) { + case MAILIMAP_RESP_CONT_REQ: + mailimap_continue_req_print(cont_req_or_resp_data->rsp_data.rsp_cont_req); + break; + case MAILIMAP_RESP_RESP_DATA: + mailimap_response_data_print(cont_req_or_resp_data->rsp_data.rsp_resp_data); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_response_tagged_print(struct mailimap_response_tagged * + tagged) +{ + print_indent(); + printf("response-tagged {\n"); + indent(); + + print_indent(); + printf("tag { %s }\n", tagged->rsp_tag); + mailimap_resp_cond_state_print(tagged->rsp_cond_state); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_response_fatal_print(struct mailimap_response_fatal * + fatal) +{ + print_indent(); + printf("response-fatal {\n"); + indent(); + + mailimap_resp_cond_bye_print(fatal->rsp_bye); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_response_done_print(struct mailimap_response_done * + resp_done) +{ + print_indent(); + printf("response-done {\n"); + indent(); + + switch (resp_done->rsp_type) { + case MAILIMAP_RESP_DONE_TYPE_TAGGED: + mailimap_response_tagged_print(resp_done->rsp_data.rsp_tagged); + break; + case MAILIMAP_RESP_DONE_TYPE_FATAL: + mailimap_response_fatal_print(resp_done->rsp_data.rsp_fatal); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +void mailimap_response_print(struct mailimap_response * resp) +{ + clistiter * cur; + + print_indent(); + printf("response {\n"); + indent(); + + for(cur = clist_begin(resp->rsp_cont_req_or_resp_data_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_cont_req_or_resp_data * resp; + + resp = clist_content(cur); + + mailimap_cont_req_or_resp_data_print(resp); + } + + mailimap_response_done_print(resp->rsp_resp_done); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_resp_cond_auth_print(struct mailimap_resp_cond_auth * + cond_auth) +{ + print_indent(); + printf("resp-cond-auth {\n"); + indent(); + + switch (cond_auth->rsp_type) { + case MAILIMAP_RESP_COND_AUTH_OK: + print_indent(); + printf("OK\n"); + case MAILIMAP_RESP_COND_AUTH_PREAUTH: + print_indent(); + printf("PREAUTH\n"); + } + mailimap_resp_text_print(cond_auth->rsp_text); + + unindent(); + print_indent(); + printf("}\n"); +} + +void mailimap_greeting_print(struct mailimap_greeting * greeting) +{ + print_indent(); + printf("greeting {\n"); + indent(); + + switch(greeting->gr_type) { + case MAILIMAP_GREETING_RESP_COND_AUTH: + mailimap_resp_cond_auth_print(greeting->gr_data.gr_auth); + break; + case MAILIMAP_GREETING_RESP_COND_BYE: + mailimap_resp_cond_bye_print(greeting->gr_data.gr_bye); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} +#else /* DEBUG */ + +typedef int iso_c_forbids_an_empty_source_file; + +#endif /* DEBUG */ diff --git a/Sources/libetpan/low-level/imap/mailimap_print.h b/Sources/libetpan/low-level/imap/mailimap_print.h new file mode 100644 index 00000000..050322ed --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_print.h @@ -0,0 +1,54 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_print.h,v 1.6 2004/11/21 21:53:36 hoa Exp $ + */ + +#ifndef MAILIMAP_PRINT_H + +#define MAILIMAP_PRINT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_types.h" + +void mailimap_response_print(struct mailimap_response * resp); + +void mailimap_greeting_print(struct mailimap_greeting * greeting); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/mailimap_sender.c b/Sources/libetpan/low-level/imap/mailimap_sender.c new file mode 100644 index 00000000..b3d5b12a --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_sender.c @@ -0,0 +1,3358 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_sender.c,v 1.32 2010/11/28 17:01:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailstream.h" +#include "mailimap_keywords.h" +#include "mailimap_sender.h" +#include "mailimap_parser.h" +#include "clist.h" +#include "mail.h" +#include "base64.h" +#include + +#include +#include +#include + +/* + TODO : + implement progression for literal +*/ + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + + + +static int is_ascii(const char * str); + +static int mailimap_atom_send(mailstream * fd, const char * atom); + +static int mailimap_auth_type_send(mailstream * fd, const char * auth_type); + +static int mailimap_base64_send(mailstream * fd, const char * base64); + + +static int mailimap_date_send(mailstream * fd, + struct mailimap_date * date); + +static int mailimap_date_day_send(mailstream * fd, int day); + +static int mailimap_date_month_send(mailstream * fd, int month); + + +/* +static gboolean mailimap_date_text_send(mailstream * fd, + struct mailimap_date_text * date_text); +*/ + + +static int mailimap_date_year_send(mailstream *fd, int year); + +static int +mailimap_date_time_send(mailstream * fd, + struct mailimap_date_time * date_time); + +static int mailimap_digit_send(mailstream * fd, int digit); + + + +static int +mailimap_fetch_type_send(mailstream * fd, + struct mailimap_fetch_type * fetch_type); + + +static int mailimap_fetch_att_send(mailstream * fd, + struct mailimap_fetch_att * fetch_att); + + +static int mailimap_flag_send(mailstream * fd, + struct mailimap_flag * flag); + + +static int mailimap_flag_extension_send(mailstream * fd, + const char * flag_extension); + + +static int mailimap_flag_keyword_send(mailstream * fd, + const char * flag_keyword); + + +static int mailimap_flag_list_send(mailstream * fd, + struct mailimap_flag_list * flag_list); + + + +static int mailimap_header_fld_name_send(mailstream * fd, const char * header); + + +static int +mailimap_header_list_send(mailstream * fd, + struct mailimap_header_list * header_list); + +static int mailimap_password_send(mailstream * fd, const char * pass); + +static int mailimap_quoted_char_send(mailstream * fd, char ch); + +static int +mailimap_section_send(mailstream * fd, + struct mailimap_section * section); + +static int +mailimap_section_msgtext_send(mailstream * fd, + struct mailimap_section_msgtext * + section_msgtext); + + +static int +mailimap_section_part_send(mailstream * fd, + struct mailimap_section_part * section); + + +static int +mailimap_section_spec_send(mailstream * fd, + struct mailimap_section_spec * section_spec); + + +static int +mailimap_section_text_send(mailstream * fd, + struct mailimap_section_text * section_text); + + +static int +mailimap_sequence_num_send(mailstream * fd, uint32_t sequence_num); + + +static int mailimap_set_item_send(mailstream * fd, + struct mailimap_set_item * item); + + +static int mailimap_status_att_send(mailstream * fd, int * status_att); + + + +static int +mailimap_store_att_flags_send(mailstream * fd, + struct mailimap_store_att_flags * store_flags); + + +static int mailimap_userid_send(mailstream * fd, const char * user); + +static int mailimap_astring_literalplus_send(mailstream * fd, const char * astring, + int literalplus_enabled); + +static int +mailimap_literalplus_count_send(mailstream * fd, size_t count); + +static int search_key_notoplevel_send(mailstream * fd, + struct mailimap_search_key * key); + +static int search_key_literalplus_notoplevel_send(mailstream * fd, + struct mailimap_search_key * key); + + + + + + + + + + + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + + + + +static inline int mailimap_sized_token_send_with_context(mailstream * fd, const char * atom, + size_t len, + mailprogress_function * progr_fun, + void * context); + +static inline int mailimap_sized_token_send(mailstream * fd, const char * atom, + size_t len) +{ + return mailimap_sized_token_send_with_context(fd, atom, len, NULL, NULL); +} + +static inline int mailimap_sized_token_send_with_context(mailstream * fd, const char * atom, + size_t len, + mailprogress_function * progr_fun, + void * context) +{ + if (mailstream_send_data_crlf_with_context(fd, atom, len, progr_fun, context) == -1) + return MAILIMAP_ERROR_STREAM; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_token_send(mailstream * fd, const char * atom) +{ + return mailimap_sized_token_send(fd, atom, strlen(atom)); +} + +int mailimap_char_send(mailstream * fd, char ch) +{ + if (mailstream_write(fd, &ch, 1) == -1) + return MAILIMAP_ERROR_STREAM; + + return MAILIMAP_NO_ERROR; +} + +static int +mailimap_struct_list_send(mailstream * fd, clist * list, + char symbol, + mailimap_struct_sender * sender) +{ + clistiter * cur; + void * elt; + int r; + + cur = clist_begin(list); + + if (cur == NULL) + return MAILIMAP_NO_ERROR; + + elt = clist_content(cur); + r = (* sender)(fd, elt); + if (r != MAILIMAP_NO_ERROR) + return r; + cur = clist_next(cur); + + while (cur != NULL) { + r = mailimap_char_send(fd, symbol); + if (r != MAILIMAP_NO_ERROR) + return r; + elt = clist_content(cur); + r = (* sender)(fd, elt); + if (r != MAILIMAP_NO_ERROR) + return r; + cur = clist_next(cur); + } + + return MAILIMAP_NO_ERROR; +} + + +int +mailimap_struct_spaced_list_send(mailstream * fd, clist * list, + mailimap_struct_sender * sender) +{ + return mailimap_struct_list_send(fd, list, ' ', sender); +} + +int mailimap_space_send(mailstream * fd) +{ + return mailimap_char_send(fd, ' '); +} + +int mailimap_crlf_send(mailstream * fd) +{ + int r; + + r = mailimap_char_send(fd, '\r'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, '\n'); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_oparenth_send(mailstream * fd) +{ + return mailimap_char_send(fd, '('); +} + +int mailimap_cparenth_send(mailstream * fd) +{ + return mailimap_char_send(fd, ')'); +} + +static int mailimap_dquote_send(mailstream * fd) +{ + return mailimap_char_send(fd, '"'); +} + +/* + address = "(" addr-name SP addr-adl SP addr-mailbox SP + addr-host ")" + + addr-adl = nstring + ; Holds route from [RFC-822] route-addr if + ; non-NIL + + addr-host = nstring + ; NIL indicates [RFC-822] group syntax. + ; Otherwise, holds [RFC-822] domain name + + addr-mailbox = nstring + ; NIL indicates end of [RFC-822] group; if + ; non-NIL and addr-host is NIL, holds + ; [RFC-822] group name. + ; Otherwise, holds [RFC-822] local-part + ; after removing [RFC-822] quoting + + addr-name = nstring + ; If non-NIL, holds phrase from [RFC-822] + ; mailbox after removing [RFC-822] quoting +*/ + +/* +=> append = "APPEND" SP mailbox [SP flag-list] [SP date-time] SP + literal +*/ + +int mailimap_append_send(mailstream * fd, + const char * mailbox, + struct mailimap_flag_list * flag_list, + struct mailimap_date_time * date_time, + size_t literal_size) +{ + int r; + + r = mailimap_token_send(fd, "APPEND"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_mailbox_send(fd, mailbox); + if (r != MAILIMAP_NO_ERROR) + return r; + if (flag_list != NULL) { + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_flag_list_send(fd, flag_list); + if (r != MAILIMAP_NO_ERROR) + return r; + } + if (date_time != NULL) { + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_time_send(fd, date_time); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_literal_count_send(fd, literal_size); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + astring = 1*ASTRING-CHAR / string + +=> ASTRING-CHAR = ATOM-CHAR / resp-specials +*/ + +static int is_atom(const char * str) +{ + if (* str == '\0') + return 0; + + while (* str != '\0') { + unsigned char uch = (unsigned char) * str; + + if (uch != '-') { + if (!isalnum(uch)) + return 0; + } + + str ++; + } + + return 1; +} + +static int mailimap_literalplus_send(mailstream * fd, const char * literal) +{ + size_t len; + size_t literal_len; + int r; + + len = strlen(literal); + literal_len = mailstream_get_data_crlf_size(literal, len); + + r = mailimap_literalplus_count_send(fd, literal_len); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_literal_data_send(fd, literal, literal_len, 0, NULL); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +static int mailimap_astring_literalplus_send(mailstream * fd, const char * astring, + int literalplus_enabled) +{ + if (is_ascii(astring) || !literalplus_enabled) { + return mailimap_astring_send(fd, astring); + } + else { + return mailimap_literalplus_send(fd, astring); + } +} + +int mailimap_astring_send(mailstream * fd, const char * astring) +{ + /* + workaround for buggy Courier-IMAP that does not accept + quoted-strings for fields name but prefer atoms. + */ + if (is_atom(astring)) + return mailimap_atom_send(fd, astring); + else + return mailimap_quoted_send(fd, astring); +} + +/* +=> atom = 1*ATOM-CHAR +*/ + +static int mailimap_atom_send(mailstream * fd, const char * atom) +{ + return mailimap_token_send(fd, atom); +} + +/* +=> ATOM-CHAR = +*/ + +/* +=> atom-specials = "(" / ")" / "{" / SP / CTL / list-wildcards / + quoted-specials / resp-specials +*/ + +/* +=> authenticate = "AUTHENTICATE" SP auth-type *(CRLF base64) +*/ + +int mailimap_authenticate_send(mailstream * fd, + const char * auth_type) +{ + int r; + + r = mailimap_token_send(fd, "AUTHENTICATE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_auth_type_send(fd, auth_type); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_authenticate_resp_send(mailstream * fd, + const char * base64) +{ + int r; + + r = mailimap_base64_send(fd, base64); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> auth-type = atom + ; Defined by [SASL] +*/ + +static int mailimap_auth_type_send(mailstream * fd, const char * auth_type) +{ + return mailimap_atom_send(fd, auth_type); +} + + +/* +=> base64 = *(4base64-char) [base64-terminal] +*/ + +static int mailimap_base64_send(mailstream * fd, const char * base64) +{ + return mailimap_token_send(fd, base64); +} + +/* +=> base64-char = ALPHA / DIGIT / "+" / "/" + ; Case-sensitive + + base64-terminal = (2base64-char "==") / (3base64-char "=") + + body = "(" (body-type-1part / body-type-mpart) ")" + + body-extension = nstring / number / + "(" body-extension *(SP body-extension) ")" + ; Future expansion. Client implementations + ; MUST accept body-extension fields. Server + ; implementations MUST NOT generate + ; body-extension fields except as defined by + ; future standard or standards-track + ; revisions of this specification. + + body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] + ; MUST NOT be returned on non-extensible + ; "BODY" fetch + + body-ext-mpart = body-fld-param [SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] + ; MUST NOT be returned on non-extensible + ; "BODY" fetch + + body-fields = body-fld-param SP body-fld-id SP body-fld-desc SP + body-fld-enc SP body-fld-octets + + body-fld-desc = nstring + + body-fld-dsp = "(" string SP body-fld-param ")" / nil + + body-fld-enc = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/ + "QUOTED-PRINTABLE") DQUOTE) / string + + body-fld-id = nstring + + body-fld-lang = nstring / "(" string *(SP string) ")" + + body-fld-lines = number + + body-fld-md5 = nstring + + body-fld-octets = number + + body-fld-param = "(" string SP string *(SP string SP string) ")" / nil + + body-type-1part = (body-type-basic / body-type-msg / body-type-text) + [SP body-ext-1part] + + body-type-basic = media-basic SP body-fields + ; MESSAGE subtype MUST NOT be "RFC822" + + body-type-mpart = 1*body SP media-subtype + [SP body-ext-mpart] + + body-type-msg = media-message SP body-fields SP envelope + SP body SP body-fld-lines + + body-type-text = media-text SP body-fields SP body-fld-lines + + capability = ("AUTH=" auth-type) / atom + ; New capabilities MUST begin with "X" or be + ; registered with IANA as standard or + ; standards-track + + capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev1" + *(SP capability) + ; IMAP4rev1 servers which offer RFC 1730 + ; compatibility MUST list "IMAP4" as the first + ; capability. + + CHAR8 = %x01-ff + ; any OCTET except NUL, %x00 +*/ + +/* +=> command = tag SP (command-any / command-auth / command-nonauth / + command-select) CRLF + ; Modal based on state +*/ + +/* +=> command-any = "CAPABILITY" / "LOGOUT" / "NOOP" / x-command + ; Valid in all states +*/ + +int mailimap_capability_send(mailstream * fd) +{ + int r; + + r = mailimap_token_send(fd, "CAPABILITY"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_logout_send(mailstream * fd) +{ + int r; + + r = mailimap_token_send(fd, "LOGOUT"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_noop_send(mailstream * fd) +{ + int r; + + r = mailimap_token_send(fd, "NOOP"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> command-auth = append / create / delete / examine / list / lsub / + rename / select / status / subscribe / unsubscribe + ; Valid only in Authenticated or Selected state +*/ + +/* +=> command-nonauth = login / authenticate + ; Valid only when in Not Authenticated state +*/ + +/* +=> command-select = "CHECK" / "CLOSE" / "EXPUNGE" / copy / fetch / store / + uid / search + ; Valid only when in Selected state +*/ + +int mailimap_check_send(mailstream * fd) +{ + int r; + + r = mailimap_token_send(fd, "CHECK"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_close_send(mailstream * fd) +{ + int r; + + r = mailimap_token_send(fd, "CLOSE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_expunge_send(mailstream * fd) +{ + int r; + + r = mailimap_token_send(fd, "EXPUNGE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + continue-req = "+" SP (resp-text / base64) CRLF +*/ + +/* +=> copy = "COPY" SP set SP mailbox +*/ + +int mailimap_copy_send(mailstream * fd, + struct mailimap_set * set, + const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "COPY"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_set_send(fd, set); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_uid_copy_send(mailstream * fd, + struct mailimap_set * set, + const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return mailimap_copy_send(fd, set, mb); +} + +/* + => move = "MOVE" SP sequence-set SP mailbox + */ + +int mailimap_move_send(mailstream * fd, + struct mailimap_set * set, + const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "MOVE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_set_send(fd, set); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_uid_move_send(mailstream * fd, + struct mailimap_set * set, + const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return mailimap_move_send(fd, set, mb); +} + +/* +=> create = "CREATE" SP mailbox + ; Use of INBOX gives a NO error +*/ + +int mailimap_create_send(mailstream * fd, + const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "CREATE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> date = date-text / DQUOTE date-text DQUOTE +*/ + +static int mailimap_date_send(mailstream * fd, + struct mailimap_date * date) +{ + int r; + + r = mailimap_date_day_send(fd, date->dt_day); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '-'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_month_send(fd, date->dt_month); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '-'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_year_send(fd, date->dt_year); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> date-day = 1*2DIGIT + ; Day of month +*/ + +static int mailimap_date_day_send(mailstream * fd, int day) +{ + return mailimap_number_send(fd, day); +} + +/* +=> date-day-fixed = (SP DIGIT) / 2DIGIT + ; Fixed-format version of date-day +*/ + +static int mailimap_date_day_fixed_send(mailstream * fd, int day) +{ + int r; + + if (day < 10) { + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_number_send(fd, day); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; + } + else + return mailimap_number_send(fd, day); +} + +/* +=> date-month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / + "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" +*/ + +static int mailimap_date_month_send(mailstream * fd, int month) +{ + const char * name; + int r; + + name = mailimap_month_get_token_str(month); + + if (name == NULL) + return MAILIMAP_ERROR_INVAL; + + r = mailimap_token_send(fd, name); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> date-text = date-day "-" date-month "-" date-year +*/ + +/* +static gboolean mailimap_date_text_send(mailstream * fd, + struct mailimap_date_text * date_text) +{ + if (!mailimap_date_day_send(fd, date_text->day)) + return FALSE; + if (!mailimap_char_send(fd, '-')) + return FALSE; + if (!mailimap_date_month_send(fd, date_text->month)) + return FALSE; + if (!mailimap_char_send(fd, '-')) + return FALSE; + if (!mailimap_date_year_send(fd, date_text->year)) + return FALSE; + + return TRUE; +} +*/ + +/* +=> date-year = 4DIGIT +*/ + +static int mailimap_fixed_digit_send(mailstream * fd, + int num, int count) +{ + int r; + + if (count == 0) + return MAILIMAP_NO_ERROR; + + r = mailimap_fixed_digit_send(fd, num / 10, count - 1); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_digit_send(fd, num % 10); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +static int mailimap_date_year_send(mailstream * fd, int year) +{ + int r; + + r = mailimap_fixed_digit_send(fd, year, 4); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> date-time = DQUOTE date-day-fixed "-" date-month "-" date-year + SP time SP zone DQUOTE +*/ + +static int +mailimap_date_time_send(mailstream * fd, + struct mailimap_date_time * date_time) +{ + int r; + int zone; + + r = mailimap_dquote_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_day_fixed_send(fd, date_time->dt_day); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '-'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_month_send(fd, date_time->dt_month); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '-'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_year_send(fd, date_time->dt_year); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_fixed_digit_send(fd, date_time->dt_hour, 2); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, ':'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_fixed_digit_send(fd, date_time->dt_min, 2); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, ':'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_fixed_digit_send(fd, date_time->dt_sec, 2); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (date_time->dt_zone < 0) { + r = mailimap_char_send(fd, '-'); + if (r != MAILIMAP_NO_ERROR) + return r; + zone = -date_time->dt_zone; + } + else { + r = mailimap_char_send(fd, '+'); + if (r != MAILIMAP_NO_ERROR) + return r; + zone = date_time->dt_zone; + } + + r = mailimap_fixed_digit_send(fd, zone, 4); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_dquote_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> delete = "DELETE" SP mailbox + ; Use of INBOX gives a NO error +*/ + +int mailimap_delete_send(mailstream * fd, const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "DELETE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + +digit + +digit-nz = %x31-39 + ; 1-9 +*/ + +static int mailimap_digit_send(mailstream * fd, int digit) +{ + return mailimap_char_send(fd, digit + '0'); +} + + +/* + envelope = "(" env-date SP env-subject SP env-from SP env-sender SP + env-reply-to SP env-to SP env-cc SP env-bcc SP + env-in-reply-to SP env-message-id ")" + + env-bcc = "(" 1*address ")" / nil + + env-cc = "(" 1*address ")" / nil + + env-date = nstring + + env-from = "(" 1*address ")" / nil + + env-in-reply-to = nstring + + env-message-id = nstring + + env-reply-to = "(" 1*address ")" / nil + + env-sender = "(" 1*address ")" / nil + + env-subject = nstring + + env-to = "(" 1*address ")" / nil +*/ + +/* +=> examine = "EXAMINE" SP mailbox +*/ + +int mailimap_examine_send(mailstream * fd, const char * mb, int condstore) +{ + int r; + + r = mailimap_token_send(fd, "EXAMINE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (condstore) { + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_oparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_send(fd, "CONDSTORE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_cparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + return MAILIMAP_NO_ERROR; +} + +/* +=> fetch = "FETCH" SP set SP ("ALL" / "FULL" / "FAST" / fetch-att / + "(" fetch-att *(SP fetch-att) ")") +*/ + +static int +mailimap_fetch_att_list_send(mailstream * fd, clist * fetch_att_list); + +static int +mailimap_fetch_type_send(mailstream * fd, + struct mailimap_fetch_type * fetch_type) +{ + switch (fetch_type->ft_type) { + case MAILIMAP_FETCH_TYPE_ALL: + return mailimap_token_send(fd, "ALL"); + case MAILIMAP_FETCH_TYPE_FULL: + return mailimap_token_send(fd, "FULL"); + case MAILIMAP_FETCH_TYPE_FAST: + return mailimap_token_send(fd, "FAST"); + case MAILIMAP_FETCH_TYPE_FETCH_ATT: + return mailimap_fetch_att_send(fd, fetch_type->ft_data.ft_fetch_att); + case MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST: + return mailimap_fetch_att_list_send(fd, + fetch_type->ft_data.ft_fetch_att_list); + default: + /* should not happen */ + return MAILIMAP_ERROR_INVAL; + } +} + +int mailimap_fetch_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type) +{ + int r; + + r = mailimap_token_send(fd, "FETCH"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_set_send(fd, set); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_fetch_type_send(fd, fetch_type); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int +mailimap_uid_fetch_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type) +{ + int r; + + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return mailimap_fetch_send(fd, set, fetch_type); +} + +/* currently porting */ + +static int +mailimap_fetch_att_list_send(mailstream * fd, clist * fetch_att_list) +{ + int r; + + r = mailimap_oparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_struct_spaced_list_send(fd, fetch_att_list, + (mailimap_struct_sender *) + mailimap_fetch_att_send); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_cparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> fetch-att = "ENVELOPE" / "FLAGS" / "INTERNALDATE" / + "RFC822" [".HEADER" / ".SIZE" / ".TEXT"] / + "BODY" ["STRUCTURE"] / "UID" / + "BODY" [".PEEK"] section ["<" number "." nz-number ">"] +*/ + +static int mailimap_fetch_att_send(mailstream * fd, + struct mailimap_fetch_att * fetch_att) +{ + int r; + + switch(fetch_att->att_type) { + case MAILIMAP_FETCH_ATT_ENVELOPE: + return mailimap_token_send(fd, "ENVELOPE"); + + case MAILIMAP_FETCH_ATT_FLAGS: + return mailimap_token_send(fd, "FLAGS"); + + case MAILIMAP_FETCH_ATT_INTERNALDATE: + return mailimap_token_send(fd, "INTERNALDATE"); + + case MAILIMAP_FETCH_ATT_RFC822: + return mailimap_token_send(fd, "RFC822"); + + case MAILIMAP_FETCH_ATT_RFC822_HEADER: + return mailimap_token_send(fd, "RFC822.HEADER"); + + case MAILIMAP_FETCH_ATT_RFC822_SIZE: + return mailimap_token_send(fd, "RFC822.SIZE"); + + case MAILIMAP_FETCH_ATT_RFC822_TEXT: + return mailimap_token_send(fd, "RFC822.TEXT"); + + case MAILIMAP_FETCH_ATT_BODY: + return mailimap_token_send(fd, "BODY"); + + case MAILIMAP_FETCH_ATT_BODYSTRUCTURE: + return mailimap_token_send(fd, "BODYSTRUCTURE"); + + case MAILIMAP_FETCH_ATT_UID: + return mailimap_token_send(fd, "UID"); + + case MAILIMAP_FETCH_ATT_BODY_SECTION: + + r = mailimap_token_send(fd, "BODY"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_section_send(fd, fetch_att->att_section); + if (r != MAILIMAP_NO_ERROR) + return r; + if (fetch_att->att_size != 0) { + r = mailimap_char_send(fd, '<'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_number_send(fd, fetch_att->att_offset); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, '.'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_number_send(fd, fetch_att->att_size); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, '>'); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + return MAILIMAP_NO_ERROR; + + case MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION: + r = mailimap_token_send(fd, "BODY.PEEK"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_section_send(fd, fetch_att->att_section); + if (r != MAILIMAP_NO_ERROR) + return r; + if (fetch_att->att_size != 0) { + r = mailimap_char_send(fd, '<'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_number_send(fd, fetch_att->att_offset); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, '.'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_number_send(fd, fetch_att->att_size); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, '>'); + if (r != MAILIMAP_NO_ERROR) + return r; + } + return MAILIMAP_NO_ERROR; + + case MAILIMAP_FETCH_ATT_EXTENSION: + r = mailimap_token_send(fd, fetch_att->att_extension); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + default: + /* should not happen */ + return MAILIMAP_ERROR_INVAL; + } +} + +/* +=> flag = "\Answered" / "\Flagged" / "\Deleted" / + "\Seen" / "\Draft" / flag-keyword / flag-extension + ; Does not include "\Recent" +*/ + +/* +enum { + FLAG_ANSWERED, + FLAG_FLAGGED, + FLAG_DELETED, + FLAG_SEEN, + FLAG_DRAFT, + FLAG_KEYWORD, + FLAG_EXTENSION +}; + +struct mailimap_flag { + gint type; + gchar * flag_keyword; + gchar * flag_extension; +}; +*/ + +static int mailimap_flag_send(mailstream * fd, + struct mailimap_flag * flag) +{ + switch(flag->fl_type) { + case MAILIMAP_FLAG_ANSWERED: + return mailimap_token_send(fd, "\\Answered"); + case MAILIMAP_FLAG_FLAGGED: + return mailimap_token_send(fd, "\\Flagged"); + case MAILIMAP_FLAG_DELETED: + return mailimap_token_send(fd, "\\Deleted"); + case MAILIMAP_FLAG_SEEN: + return mailimap_token_send(fd, "\\Seen"); + case MAILIMAP_FLAG_DRAFT: + return mailimap_token_send(fd, "\\Draft"); + case MAILIMAP_FLAG_KEYWORD: + return mailimap_flag_keyword_send(fd, flag->fl_data.fl_keyword); + case MAILIMAP_FLAG_EXTENSION: + return mailimap_flag_extension_send(fd, flag->fl_data.fl_extension); + default: + /* should not happen */ + return MAILIMAP_ERROR_INVAL; + } +} + + +/* +=> flag-extension = "\" atom + ; Future expansion. Client implementations + ; MUST accept flag-extension flags. Server + ; implementations MUST NOT generate + ; flag-extension flags except as defined by + ; future standard or standards-track + ; revisions of this specification. +*/ + +static int mailimap_flag_extension_send(mailstream * fd, + const char * flag_extension) +{ + int r; + + r = mailimap_char_send(fd, '\\'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_atom_send(fd, flag_extension); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + flag-fetch = flag / "\Recent" +*/ + +/* +=> flag-keyword = atom +*/ + +static int mailimap_flag_keyword_send(mailstream * fd, + const char * flag_keyword) +{ + return mailimap_token_send(fd, flag_keyword); +} + +/* +=> flag-list = "(" [flag *(SP flag)] ")" +*/ + +static int mailimap_flag_list_send(mailstream * fd, + struct mailimap_flag_list * flag_list) +{ + int r; + + r = mailimap_oparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (flag_list->fl_list != NULL) { + r = mailimap_struct_spaced_list_send(fd, flag_list->fl_list, + (mailimap_struct_sender *) mailimap_flag_send); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_cparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + flag-perm = flag / "\*" + + greeting = "*" SP (resp-cond-auth / resp-cond-bye) CRLF +*/ + +/* +=> header-fld-name = astring +*/ + +static int mailimap_header_fld_name_send(mailstream * fd, const char * header) +{ + return mailimap_astring_send(fd, header); +} + +/* +=> header-list = "(" header-fld-name *(SP header-fld-name) ")" +*/ + +static int +mailimap_header_list_send(mailstream * fd, + struct mailimap_header_list * header_list) +{ + int r; + + r = mailimap_oparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_struct_spaced_list_send(fd, header_list->hdr_list, + (mailimap_struct_sender *) mailimap_header_fld_name_send); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_cparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> list = "LIST" SP mailbox SP list-mailbox +*/ + +int mailimap_list_send(mailstream * fd, + const char * mb, + const char * list_mb) +{ + int r; + + r = mailimap_token_send(fd, "LIST"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_list_mailbox_send(fd, list_mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> list-mailbox = 1*list-char / string +*/ + +int +mailimap_list_mailbox_send(mailstream * fd, const char * pattern) +{ + return mailimap_quoted_send(fd, pattern); +} + +/* + list-char = ATOM-CHAR / list-wildcards / resp-specials + + list-wildcards = "%" / "*" +*/ + +/* +=> literal = "{" number "}" CRLF *CHAR8 + ; Number represents the number of CHAR8s +*/ + +int +mailimap_literal_send(mailstream * fd, const char * literal, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t len; + size_t literal_len; + int r; + + len = strlen(literal); + literal_len = mailstream_get_data_crlf_size(literal, len); + + r = mailimap_literal_count_send(fd, literal_len); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_literal_data_send(fd, literal, len, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + "{" number "}" CRLF +*/ + +static int literal_count_send(mailstream * fd, size_t count, int literalplus_enabled) +{ + int r; + + r = mailimap_char_send(fd, '{'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_number_send(fd, (uint32_t) count); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (literalplus_enabled) { + r = mailimap_char_send(fd, '+'); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_char_send(fd, '}'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int +mailimap_literal_count_send(mailstream * fd, size_t count) +{ + return literal_count_send(fd, count, 0); +} + +static int +mailimap_literalplus_count_send(mailstream * fd, size_t count) +{ + return literal_count_send(fd, count, 1); +} + +/* + *CHAR8 +*/ + +int +mailimap_literal_data_send(mailstream * fd, const char * literal, size_t len, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_literal_data_send_with_context(fd, literal, len, NULL, NULL); +} + +int +mailimap_literal_data_send_with_context(mailstream * fd, const char * literal, size_t len, + mailprogress_function * progr_fun, + void * context) +{ + int r; + + r = mailimap_sized_token_send_with_context(fd, literal, len, progr_fun, context); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> login = "LOGIN" SP userid SP password +*/ + +int mailimap_login_send(mailstream * fd, + const char * userid, const char * password) +{ + int r; + + r = mailimap_token_send(fd, "LOGIN"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_userid_send(fd, userid); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_password_send(fd, password); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> lsub = "LSUB" SP mailbox SP list-mailbox +*/ + +int mailimap_lsub_send(mailstream * fd, + const char * mb, const char * list_mb) +{ + int r; + + r = mailimap_token_send(fd, "LSUB"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_list_mailbox_send(fd, list_mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + mailbox = "INBOX" / astring + ; INBOX is case-insensitive. All case variants of + ; INBOX (e.g. "iNbOx") MUST be interpreted as INBOX + ; not as an astring. An astring which consists of + ; the case-insensitive sequence "I" "N" "B" "O" "X" + ; is considered to be INBOX and not an astring. + ; Refer to section 5.1 for further + ; semantic details of mailbox names. +*/ + +int mailimap_mailbox_send(mailstream * fd, const char * mb) +{ + return mailimap_astring_send(fd, mb); +} + +/* + mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list / + "LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) / + "STATUS" SP mailbox SP "(" + [status-att SP number *(SP status-att SP number)] ")" / + number SP "EXISTS" / number SP "RECENT" + + mailbox-list = "(" [mbx-list-flags] ")" SP + (DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox + + mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag + *(SP mbx-list-oflag) / + mbx-list-oflag *(SP mbx-list-oflag) + + mbx-list-oflag = "\Noinferiors" / flag-extension + ; Other flags; multiple possible per LIST response + + mbx-list-sflag = "\Noselect" / "\Marked" / "\Unmarked" + ; Selectability flags; only one per LIST response + + media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" / + "VIDEO") DQUOTE) / string) SP media-subtype + ; Defined in [MIME-IMT] + + media-message = DQUOTE "MESSAGE" DQUOTE SP DQUOTE "RFC822" DQUOTE + ; Defined in [MIME-IMT] + + media-subtype = string + ; Defined in [MIME-IMT] + + media-text = DQUOTE "TEXT" DQUOTE SP media-subtype + ; Defined in [MIME-IMT] + + message-data = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att)) + + msg-att = "(" (msg-att-dynamic / msg-att-static) + *(SP (msg-att-dynamic / msg-att-static)) ")" + + msg-att-dynamic = "FLAGS" SP "(" [flag-fetch *(SP flag-fetch)] ")" + ; MAY change for a message + + msg-att-static = "ENVELOPE" SP envelope / "INTERNALDATE" SP date-time / + "RFC822" [".HEADER" / ".TEXT"] SP nstring / + "RFC822.SIZE" SP number / "BODY" ["STRUCTURE"] SP body / + "BODY" section ["<" number ">"] SP nstring / + "UID" SP uniqueid + ; MUST NOT change for a message + + nil = "NIL" + + nstring = string / nil +*/ + +/* +=> number = 1*DIGIT + ; Unsigned 32-bit integer + ; (0 <= n < 4,294,967,296) +*/ + +/* + nz-number = digit-nz *DIGIT + ; Non-zero unsigned 32-bit integer + ; (0 < n < 4,294,967,296) +*/ + +int mailimap_number_send(mailstream * fd, uint32_t number) +{ + int r; + + if (number / 10 != 0) { + r = mailimap_number_send(fd, number / 10); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_digit_send(fd, number % 10); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> password = astring +*/ + +static int mailimap_password_send(mailstream * fd, const char * pass) +{ + return mailimap_astring_send(fd, pass); +} + +/* +=> quoted = DQUOTE *QUOTED-CHAR DQUOTE + +=> QUOTED-CHAR = / + "\" quoted-specials + +=> quoted-specials = DQUOTE / "\" +*/ + +static int is_quoted_specials(char ch) +{ + return (ch == '\"') || (ch == '\\'); +} + +static int mailimap_quoted_char_send(mailstream * fd, char ch) +{ + int r; + + if (is_quoted_specials(ch)) { + r = mailimap_char_send(fd, '\\'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, ch); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; + } + else + return mailimap_char_send(fd, ch); +} + +int mailimap_quoted_send(mailstream * fd, const char * quoted) +{ + const char * pos; + int r; + + pos = quoted; + + r = mailimap_dquote_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + while (* pos != 0) { + r = mailimap_quoted_char_send(fd, * pos); + if (r != MAILIMAP_NO_ERROR) + return r; + pos ++; + } + + r = mailimap_dquote_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> rename = "RENAME" SP mailbox SP mailbox + ; Use of INBOX as a destination gives a NO error +*/ + +int mailimap_rename_send(mailstream * fd, const char * mb, + const char * new_name) +{ + int r; + + r = mailimap_token_send(fd, "RENAME"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_mailbox_send(fd, new_name); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +static int is_ascii(const char * str) +{ + const char * p = str; + while (* p != 0) { + if ((unsigned char) * p >= 128) { + return 0; + } + p ++; + } + return 1; +} + +/* +=> search-key = "ALL" / "ANSWERED" / "BCC" SP astring / + "BEFORE" SP date / "BODY" SP astring / + "CC" SP astring / "DELETED" / "FLAGGED" / + "FROM" SP astring / "KEYWORD" SP flag-keyword / "NEW" / + "OLD" / "ON" SP date / "RECENT" / "SEEN" / + "SINCE" SP date / "SUBJECT" SP astring / + "TEXT" SP astring / "TO" SP astring / + "UNANSWERED" / "UNDELETED" / "UNFLAGGED" / + "UNKEYWORD" SP flag-keyword / "UNSEEN" / + ; Above this line were in [IMAP2] + "DRAFT" / "HEADER" SP header-fld-name SP astring / + "LARGER" SP number / "NOT" SP search-key / + "OR" SP search-key SP search-key / + "SENTBEFORE" SP date / "SENTON" SP date / + "SENTSINCE" SP date / "SMALLER" SP number / + "UID" SP set / "UNDRAFT" / set / + "(" search-key *(SP search-key) ")" +*/ + +static int mailimap_search_key_need_to_send_charset(struct mailimap_search_key * key) +{ + clistiter * cur; + struct mailimap_search_key * elt; + int r; + + switch (key->sk_type) { + + case MAILIMAP_SEARCH_KEY_ALL: + return 0; + + case MAILIMAP_SEARCH_KEY_ANSWERED: + return 0; + + case MAILIMAP_SEARCH_KEY_BCC: + return !is_ascii(key->sk_data.sk_bcc); + + case MAILIMAP_SEARCH_KEY_BEFORE: + return 0; + + case MAILIMAP_SEARCH_KEY_BODY: + return !is_ascii(key->sk_data.sk_body); + + case MAILIMAP_SEARCH_KEY_CC: + return !is_ascii(key->sk_data.sk_cc); + + case MAILIMAP_SEARCH_KEY_DELETED: + return 0; + + case MAILIMAP_SEARCH_KEY_FLAGGED: + return 0; + + case MAILIMAP_SEARCH_KEY_FROM: + return !is_ascii(key->sk_data.sk_from); + + case MAILIMAP_SEARCH_KEY_KEYWORD: + return !is_ascii(key->sk_data.sk_keyword); + + case MAILIMAP_SEARCH_KEY_NEW: + return 0; + + case MAILIMAP_SEARCH_KEY_OLD: + return 0; + + case MAILIMAP_SEARCH_KEY_ON: + return 0; + + case MAILIMAP_SEARCH_KEY_RECENT: + return 0; + + case MAILIMAP_SEARCH_KEY_SEEN: + return 0; + + case MAILIMAP_SEARCH_KEY_SINCE: + return 0; + + case MAILIMAP_SEARCH_KEY_SUBJECT: + return !is_ascii(key->sk_data.sk_subject); + + case MAILIMAP_SEARCH_KEY_TEXT: + return !is_ascii(key->sk_data.sk_text); + + case MAILIMAP_SEARCH_KEY_TO: + return !is_ascii(key->sk_data.sk_to); + + case MAILIMAP_SEARCH_KEY_UNANSWERED: + return 0; + + case MAILIMAP_SEARCH_KEY_UNDELETED: + return 0; + + case MAILIMAP_SEARCH_KEY_UNFLAGGED: + return 0; + + case MAILIMAP_SEARCH_KEY_UNKEYWORD: + return !is_ascii(key->sk_data.sk_unkeyword); + + case MAILIMAP_SEARCH_KEY_UNSEEN: + return 0; + + case MAILIMAP_SEARCH_KEY_DRAFT: + return 0; + + case MAILIMAP_SEARCH_KEY_HEADER: + return !is_ascii(key->sk_data.sk_header.sk_header_name) || !is_ascii(key->sk_data.sk_header.sk_header_value); + + case MAILIMAP_SEARCH_KEY_LARGER: + return 0; + + case MAILIMAP_SEARCH_KEY_NOT: + return mailimap_search_key_need_to_send_charset(key->sk_data.sk_not); + + case MAILIMAP_SEARCH_KEY_OR: + return mailimap_search_key_need_to_send_charset(key->sk_data.sk_or.sk_or1) || + mailimap_search_key_need_to_send_charset(key->sk_data.sk_or.sk_or2); + + case MAILIMAP_SEARCH_KEY_SENTBEFORE: + return 0; + + case MAILIMAP_SEARCH_KEY_SENTON: + return 0; + + case MAILIMAP_SEARCH_KEY_SENTSINCE: + return 0; + + case MAILIMAP_SEARCH_KEY_SMALLER: + return 0; + + case MAILIMAP_SEARCH_KEY_UID: + return 0; + + case MAILIMAP_SEARCH_KEY_UNDRAFT: + return 0; + + case MAILIMAP_SEARCH_KEY_SET: + return 0; + + case MAILIMAP_SEARCH_KEY_XGMTHRID: + return 0; + + case MAILIMAP_SEARCH_KEY_MULTIPLE: + { + cur = clist_begin(key->sk_data.sk_multiple); + + if (cur == NULL) + return 0; + + elt = (struct mailimap_search_key *) clist_content(cur); + r = mailimap_search_key_need_to_send_charset(elt); + if (r != 0) + return r; + cur = clist_next(cur); + + while (cur != NULL) { + + elt = (struct mailimap_search_key *) clist_content(cur); + r = mailimap_search_key_need_to_send_charset(elt); + if (r != 0) + return r; + cur = clist_next(cur); + } + + return 0; + } + + case MAILIMAP_SEARCH_KEY_MODSEQ: + return 0; + + case MAILIMAP_SEARCH_KEY_XGMMSGID: + return 0; + + default: + /* don't know, better send */ + return 1; + } +} + +/* + response = *(continue-req / response-data) response-done + + response-data = "*" SP (resp-cond-state / resp-cond-bye / + mailbox-data / message-data / capability-data) CRLF + + response-done = response-tagged / response-fatal + + response-fatal = "*" SP resp-cond-bye CRLF + ; Server closes connection immediately + + response-tagged = tag SP resp-cond-state CRLF + + resp-cond-auth = ("OK" / "PREAUTH") SP resp-text + ; Authentication condition + + resp-cond-bye = "BYE" SP resp-text + + resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text + ; Status condition + + resp-specials = "]" + + resp-text = ["[" resp-text-code "]" SP] text + + resp-text-code = "ALERT" / + "BADCHARSET" [SP "(" astring *(SP astring) ")" ] / + capability-data / "PARSE" / + "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" / + "READ-ONLY" / "READ-WRITE" / "TRYCREATE" / + "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number / + "UNSEEN" SP nz-number / + atom [SP 1*] +*/ + +/* +=> search = "SEARCH" [SP "CHARSET" SP astring] 1*(SP search-key) + ; CHARSET argument to MUST be registered with IANA +*/ + +int +mailimap_search_send(mailstream * fd, const char * charset, + struct mailimap_search_key * key) +{ + int r; + int needToSendCharset = 1; + + r = mailimap_token_send(fd, "SEARCH"); + if (r != MAILIMAP_NO_ERROR) + return r; + + needToSendCharset = mailimap_search_key_need_to_send_charset(key); + + if (charset != NULL && needToSendCharset) { + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_send(fd, "CHARSET"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, charset); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_search_key_send(fd, key); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int +mailimap_uid_search_send(mailstream * fd, const char * charset, + struct mailimap_search_key * key) +{ + int r; + + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return mailimap_search_send(fd, charset, key); +} + +int mailimap_search_literalplus_send(mailstream * fd, const char * charset, + struct mailimap_search_key * key) +{ + int r; + int needToSendCharset = 1; + + r = mailimap_token_send(fd, "SEARCH"); + if (r != MAILIMAP_NO_ERROR) + return r; + + needToSendCharset = mailimap_search_key_need_to_send_charset(key); + + if (charset != NULL && needToSendCharset) { + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_send(fd, "CHARSET"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, charset); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_search_key_literalplus_send(fd, key); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_uid_search_literalplus_send(mailstream * fd, const char * charset, + struct mailimap_search_key * key) +{ + int r; + + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return mailimap_search_literalplus_send(fd, charset, key); +} + +/* +=> search-key = "ALL" / "ANSWERED" / "BCC" SP astring / + "BEFORE" SP date / "BODY" SP astring / + "CC" SP astring / "DELETED" / "FLAGGED" / + "FROM" SP astring / "KEYWORD" SP flag-keyword / "NEW" / + "OLD" / "ON" SP date / "RECENT" / "SEEN" / + "SINCE" SP date / "SUBJECT" SP astring / + "TEXT" SP astring / "TO" SP astring / + "UNANSWERED" / "UNDELETED" / "UNFLAGGED" / + "UNKEYWORD" SP flag-keyword / "UNSEEN" / + ; Above this line were in [IMAP2] + "DRAFT" / "HEADER" SP header-fld-name SP astring / + "LARGER" SP number / "NOT" SP search-key / + "OR" SP search-key SP search-key / + "SENTBEFORE" SP date / "SENTON" SP date / + "SENTSINCE" SP date / "SMALLER" SP number / + "UID" SP set / "UNDRAFT" / set / + "(" search-key *(SP search-key) ")" +*/ + + +static int search_key_send(mailstream * fd, + struct mailimap_search_key * key, + int literalplus_enabled, int toplevel) +{ + int r; + + switch (key->sk_type) { + + case MAILIMAP_SEARCH_KEY_ALL: + return mailimap_token_send(fd, "ALL"); + + case MAILIMAP_SEARCH_KEY_ANSWERED: + return mailimap_token_send(fd, "ANSWERED"); + + case MAILIMAP_SEARCH_KEY_BCC: + r = mailimap_token_send(fd, "BCC"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_literalplus_send(fd, key->sk_data.sk_bcc, literalplus_enabled); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_BEFORE: + r = mailimap_token_send(fd, "BEFORE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_send(fd, key->sk_data.sk_before); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_BODY: + r = mailimap_token_send(fd, "BODY"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_literalplus_send(fd, key->sk_data.sk_body, literalplus_enabled); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_CC: + r = mailimap_token_send(fd, "CC"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_literalplus_send(fd, key->sk_data.sk_cc, literalplus_enabled); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_DELETED: + return mailimap_token_send(fd, "DELETED"); + + case MAILIMAP_SEARCH_KEY_FLAGGED: + return mailimap_token_send(fd, "FLAGGED"); + + case MAILIMAP_SEARCH_KEY_FROM: + r = mailimap_token_send(fd, "FROM"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_literalplus_send(fd, key->sk_data.sk_from, literalplus_enabled); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_KEYWORD: + r = mailimap_token_send(fd, "KEYWORD"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_flag_keyword_send(fd, key->sk_data.sk_keyword); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_NEW: + return mailimap_token_send(fd, "NEW"); + + case MAILIMAP_SEARCH_KEY_OLD: + return mailimap_token_send(fd, "OLD"); + + case MAILIMAP_SEARCH_KEY_ON: + r = mailimap_token_send(fd, "ON"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_send(fd, key->sk_data.sk_on); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_RECENT: + return mailimap_token_send(fd, "RECENT"); + + case MAILIMAP_SEARCH_KEY_SEEN: + return mailimap_token_send(fd, "SEEN"); + + case MAILIMAP_SEARCH_KEY_SINCE: + r = mailimap_token_send(fd, "SINCE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_send(fd, key->sk_data.sk_since); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_SUBJECT: + r = mailimap_token_send(fd, "SUBJECT"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_literalplus_send(fd, key->sk_data.sk_subject, literalplus_enabled); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_TEXT: + r = mailimap_token_send(fd, "TEXT"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_literalplus_send(fd, key->sk_data.sk_text, literalplus_enabled); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_TO: + r = mailimap_token_send(fd, "TO"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_literalplus_send(fd, key->sk_data.sk_text, literalplus_enabled); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_UNANSWERED: + return mailimap_token_send(fd, "UNANSWERED"); + + case MAILIMAP_SEARCH_KEY_UNDELETED: + return mailimap_token_send(fd, "UNDELETED"); + + case MAILIMAP_SEARCH_KEY_UNFLAGGED: + return mailimap_token_send(fd, "UNFLAGGED"); + + case MAILIMAP_SEARCH_KEY_UNKEYWORD: + r = mailimap_token_send(fd, "UNKEYWORD"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_literalplus_send(fd, key->sk_data.sk_unkeyword, literalplus_enabled); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_UNSEEN: + return mailimap_token_send(fd, "UNSEEN"); + + case MAILIMAP_SEARCH_KEY_DRAFT: + return mailimap_token_send(fd, "DRAFT"); + + case MAILIMAP_SEARCH_KEY_HEADER: + r = mailimap_token_send(fd, "HEADER"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_header_fld_name_send(fd, key->sk_data.sk_header.sk_header_name); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_literalplus_send(fd, key->sk_data.sk_header.sk_header_value, + literalplus_enabled); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_LARGER: + r = mailimap_token_send(fd, "LARGER"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_number_send(fd, key->sk_data.sk_larger); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_NOT: + r = mailimap_token_send(fd, "NOT"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = search_key_send(fd, key->sk_data.sk_not, literalplus_enabled, 0); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_OR: + r = mailimap_token_send(fd, "OR"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = search_key_send(fd, key->sk_data.sk_or.sk_or1, literalplus_enabled, 0); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = search_key_send(fd, key->sk_data.sk_or.sk_or2, literalplus_enabled, 0); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_SENTBEFORE: + r = mailimap_token_send(fd, "SENTBEFORE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_send(fd, key->sk_data.sk_sentbefore); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_SENTON: + r = mailimap_token_send(fd, "SENTON"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_send(fd, key->sk_data.sk_senton); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_SENTSINCE: + r = mailimap_token_send(fd, "SENTSINCE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_send(fd, key->sk_data.sk_sentsince); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_SMALLER: + r = mailimap_token_send(fd, "SMALLER"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_number_send(fd, key->sk_data.sk_smaller); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_UID: + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_set_send(fd, key->sk_data.sk_set); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_UNDRAFT: + return mailimap_token_send(fd, "UNDRAFT"); + + case MAILIMAP_SEARCH_KEY_SET: + return mailimap_set_send(fd, key->sk_data.sk_set); + + case MAILIMAP_SEARCH_KEY_XGMTHRID: + r = mailimap_token_send(fd, "X-GM-THRID"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_uint64_send(fd, key->sk_data.sk_xgmthrid); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_XGMMSGID: + r = mailimap_token_send(fd, "X-GM-MSGID"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_uint64_send(fd, key->sk_data.sk_xgmmsgid); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_XGMRAW: + r = mailimap_token_send(fd, "X-GM-RAW"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_literalplus_send(fd, key->sk_data.sk_xgmraw, literalplus_enabled); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_MULTIPLE: + if (!toplevel) { + r = mailimap_oparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + if (literalplus_enabled) { + r = mailimap_struct_spaced_list_send(fd, key->sk_data.sk_multiple, + (mailimap_struct_sender *) search_key_literalplus_notoplevel_send); + } + else { + r = mailimap_struct_spaced_list_send(fd, key->sk_data.sk_multiple, + (mailimap_struct_sender *) search_key_notoplevel_send); + } + if (r != MAILIMAP_NO_ERROR) + return r; + + if (!toplevel) { + r = mailimap_cparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + return MAILIMAP_NO_ERROR; + case MAILIMAP_SEARCH_KEY_MODSEQ: + r = mailimap_token_send(fd, "MODSEQ"); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (key->sk_data.sk_modseq.sk_entry_name != NULL) { + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + mailimap_dquote_send(fd); + r = mailimap_token_send(fd, "/flags/"); + if (r != MAILIMAP_NO_ERROR) + return r; + if (key->sk_data.sk_modseq.sk_entry_name->fl_type != MAILIMAP_FLAG_KEYWORD) { + r = mailimap_token_send(fd, "\\"); + if (r != MAILIMAP_NO_ERROR) + return r; + } + r = mailimap_flag_send(fd, key->sk_data.sk_modseq.sk_entry_name); + if (r != MAILIMAP_NO_ERROR) + return r; + mailimap_dquote_send(fd); + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + switch (key->sk_data.sk_modseq.sk_entry_type_req) { + case MAILIMAP_SEARCH_KEY_MODSEQ_ENTRY_TYPE_REQ_PRIV: + r = mailimap_token_send(fd, "priv"); + if (r != MAILIMAP_NO_ERROR) + return r; + break; + case MAILIMAP_SEARCH_KEY_MODSEQ_ENTRY_TYPE_REQ_SHARED: + r = mailimap_token_send(fd, "shared"); + if (r != MAILIMAP_NO_ERROR) + return r; + break; + case MAILIMAP_SEARCH_KEY_MODSEQ_ENTRY_TYPE_REQ_ALL: + r = mailimap_token_send(fd, "all"); + if (r != MAILIMAP_NO_ERROR) + return r; + break; + } + } + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mod_sequence_value_send(fd, key->sk_data.sk_modseq.sk_modseq_valzer); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; + + default: + /* should not happend */ + return MAILIMAP_ERROR_INVAL; + } +} + +static int search_key_notoplevel_send(mailstream * fd, + struct mailimap_search_key * key) +{ + return search_key_send(fd, key, 0, 0); +} + +static int search_key_literalplus_notoplevel_send(mailstream * fd, + struct mailimap_search_key * key) +{ + return search_key_send(fd, key, 1, 0); +} + +int mailimap_search_key_send(mailstream * fd, + struct mailimap_search_key * key) +{ + return search_key_send(fd, key, 0, 1); +} + +int mailimap_search_key_literalplus_send(mailstream * fd, + struct mailimap_search_key * key) +{ + return search_key_send(fd, key, 1, 1); +} + +int mailimap_mod_sequence_value_send(mailstream * fd, uint64_t number) +{ + return mailimap_uint64_send(fd, number); +} + +int mailimap_uint64_send(mailstream * fd, uint64_t number) +{ + char numberval[30]; + snprintf(numberval, sizeof(numberval), "%llu", (long long unsigned) number); + return mailimap_token_send(fd, numberval); +} + + +/* +=> section = "[" [section-spec] "]" +*/ + +static int +mailimap_section_send(mailstream * fd, + struct mailimap_section * section) +{ + int r; + + r = mailimap_char_send(fd, '['); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (section != NULL) { + if (section->sec_spec != NULL) { + r = mailimap_section_spec_send(fd, section->sec_spec); + if (r != MAILIMAP_NO_ERROR) + return r; + } + } + + r = mailimap_char_send(fd, ']'); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> section-msgtext = "HEADER" / "HEADER.FIELDS" [".NOT"] SP header-list / + "TEXT" + ; top-level or MESSAGE/RFC822 part +*/ + +static int +mailimap_section_msgtext_send(mailstream * fd, + struct mailimap_section_msgtext * + section_msgtext) +{ + int r; + + switch (section_msgtext->sec_type) { + case MAILIMAP_SECTION_MSGTEXT_HEADER: + return mailimap_token_send(fd, "HEADER"); + + case MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS: + r = mailimap_token_send(fd, "HEADER.FIELDS"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_header_list_send(fd, section_msgtext->sec_header_list); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT: + r = mailimap_token_send(fd, "HEADER.FIELDS.NOT"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_header_list_send(fd, section_msgtext->sec_header_list); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SECTION_MSGTEXT_TEXT: + return mailimap_token_send(fd, "TEXT"); + + default: + /* should not happend */ + return MAILIMAP_ERROR_INVAL; + } +} + +/* +=> section-part = nz-number *("." nz-number) + ; body part nesting +*/ + +static int +mailimap_pnumber_send(mailstream * fd, uint32_t * pnumber) +{ + return mailimap_number_send(fd, * pnumber); +} + +static int +mailimap_section_part_send(mailstream * fd, + struct mailimap_section_part * section) +{ + int r; + + r = mailimap_struct_list_send(fd, section->sec_id, '.', + (mailimap_struct_sender *) mailimap_pnumber_send); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> section-spec = section-msgtext / (section-part ["." section-text]) +*/ + +static int +mailimap_section_spec_send(mailstream * fd, + struct mailimap_section_spec * section_spec) +{ + int r; + + switch (section_spec->sec_type) { + case MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT: + return mailimap_section_msgtext_send(fd, + section_spec->sec_data.sec_msgtext); + + case MAILIMAP_SECTION_SPEC_SECTION_PART: + r = mailimap_section_part_send(fd, section_spec->sec_data.sec_part); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (section_spec->sec_text != NULL) { + r = mailimap_char_send(fd, '.'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_section_text_send(fd, + section_spec->sec_text); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + return MAILIMAP_NO_ERROR; + + default: + /* should not happen */ + return MAILIMAP_ERROR_INVAL; + } +} + +/* +=> section-text = section-msgtext / "MIME" + ; text other than actual body part (headers, etc.) +*/ + +static int +mailimap_section_text_send(mailstream * fd, + struct mailimap_section_text * section_text) +{ + switch (section_text->sec_type) { + case MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT: + return mailimap_section_msgtext_send(fd, section_text->sec_msgtext); + + case MAILIMAP_SECTION_TEXT_MIME: + return mailimap_token_send(fd, "MIME"); + + default: + /* should not happen */ + return MAILIMAP_NO_ERROR; + } +} + +/* +=> select = "SELECT" SP mailbox +*/ + +int +mailimap_select_send(mailstream * fd, const char * mb, int condstore) +{ + int r; + + r = mailimap_token_send(fd, "SELECT"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (condstore) { + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_oparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_send(fd, "CONDSTORE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_cparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + return MAILIMAP_NO_ERROR; +} + +/* +=> sequence-num = nz-number / "*" + ; * is the largest number in use. For message + ; sequence numbers, it is the number of messages + ; in the mailbox. For unique identifiers, it is + ; the unique identifier of the last message in + ; the mailbox. +*/ + +/* if sequence_num == 0 then "*" */ + +static int +mailimap_sequence_num_send(mailstream * fd, uint32_t sequence_num) +{ + if (sequence_num == 0) + return mailimap_char_send(fd, '*'); + else + return mailimap_number_send(fd, sequence_num); +} + +/* +=> set = sequence-num / (sequence-num ":" sequence-num) / + (set "," set) + ; Identifies a set of messages. For message + ; sequence numbers, these are consecutive + ; numbers from 1 to the number of messages in + ; the mailbox + ; Comma delimits individual numbers, colon + ; delimits between two numbers inclusive. + ; Example: 2,4:7,9,12:* is 2,4,5,6,7,9,12,13, + ; 14,15 for a mailbox with 15 messages. +*/ + +static int mailimap_set_item_send(mailstream * fd, + struct mailimap_set_item * item) +{ + int r; + + if (item->set_first == item->set_last) + return mailimap_sequence_num_send(fd, item->set_first); + else { + r = mailimap_sequence_num_send(fd, item->set_first); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, ':'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_sequence_num_send(fd, item->set_last); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + } +} + +int mailimap_set_send(mailstream * fd, + struct mailimap_set * set) +{ + return mailimap_struct_list_send(fd, set->set_list, ',', + (mailimap_struct_sender *) mailimap_set_item_send); +} + +/* +=> status = "STATUS" SP mailbox SP "(" status-att *(SP status-att) ")" +*/ + +static int +mailimap_status_att_list_send(mailstream * fd, + struct mailimap_status_att_list * status_att_list) +{ + return mailimap_struct_spaced_list_send(fd, status_att_list->att_list, + (mailimap_struct_sender *) mailimap_status_att_send); +} + +int +mailimap_status_send(mailstream * fd, const char * mb, + struct mailimap_status_att_list * status_att_list) +{ + int r; + + r = mailimap_token_send(fd, "STATUS"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '('); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_status_att_list_send(fd, status_att_list); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, ')'); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> status-att = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" / + "UNSEEN" +*/ + + +static int mailimap_status_att_send(mailstream * fd, int * status_att) +{ + const char * token; + + token = mailimap_status_att_get_token_str(* status_att); + if (token == NULL) { + /* should not happen */ + return MAILIMAP_ERROR_INVAL; + } + + return mailimap_token_send(fd, token); +} + +/* +=> store = "STORE" SP set SP store-att-flags +*/ + +int +mailimap_store_send(mailstream * fd, + struct mailimap_set * set, int use_unchangedsince, uint64_t mod_sequence_valzer, + struct mailimap_store_att_flags * store_att_flags) +{ + int r; + + r = mailimap_token_send(fd, "STORE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_set_send(fd, set); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (use_unchangedsince) { + r = mailimap_oparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_send(fd, "UNCHANGEDSINCE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mod_sequence_value_send(fd, mod_sequence_valzer); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_cparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_store_att_flags_send(fd, store_att_flags); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int +mailimap_uid_store_send(mailstream * fd, + struct mailimap_set * set, int use_unchangedsince, uint64_t mod_sequence_valzer, + struct mailimap_store_att_flags * store_att_flags) +{ + int r; + + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return mailimap_store_send(fd, set, + use_unchangedsince, mod_sequence_valzer, store_att_flags); +} + +/* +=> store-att-flags = (["+" / "-"] "FLAGS" [".SILENT"]) SP + (flag-list / (flag *(SP flag))) +*/ + +static int +mailimap_store_att_flags_send(mailstream * fd, + struct mailimap_store_att_flags * store_flags) +{ + int r; + + switch (store_flags->fl_sign) { + case 1: + r = mailimap_char_send(fd, '+'); + if (r != MAILIMAP_NO_ERROR) + return r; + break; + case -1: + r = mailimap_char_send(fd, '-'); + if (r != MAILIMAP_NO_ERROR) + return r; + break; + } + + r = mailimap_token_send(fd, "FLAGS"); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (store_flags->fl_silent) { + r = mailimap_token_send(fd, ".SILENT"); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_flag_list_send(fd, store_flags->fl_flag_list); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + string = quoted / literal +*/ + +/* +=> subscribe = "SUBSCRIBE" SP mailbox +*/ + +int mailimap_subscribe_send(mailstream * fd, const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "SUBSCRIBE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> tag = 1* +*/ + +int mailimap_tag_send(mailstream * fd, const char * tag) +{ + return mailimap_token_send(fd, tag); +} + +/* + text = 1*TEXT-CHAR + + TEXT-CHAR = + + time = 2DIGIT ":" 2DIGIT ":" 2DIGIT + ; Hours minutes seconds +*/ + +/* +=> uid = "UID" SP (copy / fetch / search / store) + ; Unique identifiers used instead of message + ; sequence numbers + +functions uid_copy, uid_fetch ... +*/ + + +/* + uniqueid = nz-number + ; Strictly ascending +*/ + +/* +=> unsubscribe = "UNSUBSCRIBE" SP mailbox +*/ + +int mailimap_unsubscribe_send(mailstream * fd, + const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "UNSUBSCRIBE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_starttls_send(mailstream * fd) +{ + return mailimap_token_send(fd, "STARTTLS"); +} + +int +mailimap_send_custom_command(mailstream *fd, const char * command) +{ + int r; + + r = mailimap_token_send(fd, command); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> userid = astring +*/ + +static int mailimap_userid_send(mailstream * fd, const char * user) +{ + return mailimap_astring_send(fd, user); +} + +/* + x-command = "X" atom + + zone = ("+" / "-") 4DIGIT + ; Signed four-digit value of hhmm representing + ; hours and minutes east of Greenwich (that is, + ; the amount that the given time differs from + ; Universal Time). Subtracting the timezone + ; from the given time will give the UT form. + ; The Universal Time zone is "+0000". +*/ diff --git a/Sources/libetpan/low-level/imap/mailimap_sender.h b/Sources/libetpan/low-level/imap/mailimap_sender.h new file mode 100644 index 00000000..4f44f32f --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_sender.h @@ -0,0 +1,223 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_sender.h,v 1.15 2010/11/28 17:01:26 hoa Exp $ + */ + +#ifndef MAILIMAP_SENDER_H + +#define MAILIMAP_SENDER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_types.h" + +int mailimap_append_send(mailstream * fd, + const char * mailbox, + struct mailimap_flag_list * flag_list, + struct mailimap_date_time * date_time, + size_t literal_size); + +int mailimap_authenticate_send(mailstream * fd, + const char * auth_type); + +int mailimap_authenticate_resp_send(mailstream * fd, + const char * base64); + +int mailimap_noop_send(mailstream * fd); + +int mailimap_logout_send(mailstream * fd); + +int mailimap_capability_send(mailstream * fd); + +int mailimap_check_send(mailstream * fd); + +int mailimap_close_send(mailstream * fd); + +int mailimap_expunge_send(mailstream * fd); + +int mailimap_copy_send(mailstream * fd, + struct mailimap_set * set, + const char * mb); + +int mailimap_uid_copy_send(mailstream * fd, + struct mailimap_set * set, + const char * mb); + +int mailimap_move_send(mailstream * fd, + struct mailimap_set * set, + const char * mb); + +int mailimap_uid_move_send(mailstream * fd, + struct mailimap_set * set, + const char * mb); + +int mailimap_create_send(mailstream * fd, + const char * mb); + + +int mailimap_delete_send(mailstream * fd, const char * mb); + +int mailimap_examine_send(mailstream * fd, const char * mb, int condstore); + +int +mailimap_fetch_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type); + +int +mailimap_uid_fetch_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type); + +int mailimap_list_send(mailstream * fd, + const char * mb, const char * list_mb); + +int mailimap_login_send(mailstream * fd, + const char * userid, const char * password); + +int mailimap_lsub_send(mailstream * fd, + const char * mb, const char * list_mb); + +int mailimap_rename_send(mailstream * fd, const char * mb, + const char * new_name); + +int +mailimap_search_send(mailstream * fd, const char * charset, + struct mailimap_search_key * key); + +int +mailimap_uid_search_send(mailstream * fd, const char * charset, + struct mailimap_search_key * key); + +int mailimap_search_literalplus_send(mailstream * fd, const char * charset, + struct mailimap_search_key * key); + +int mailimap_uid_search_literalplus_send(mailstream * fd, const char * charset, + struct mailimap_search_key * key); + +int mailimap_search_key_send(mailstream * fd, + struct mailimap_search_key * key); + +int mailimap_search_key_literalplus_send(mailstream * fd, + struct mailimap_search_key * key); + +int +mailimap_select_send(mailstream * fd, const char * mb, int condstore); + +int +mailimap_status_send(mailstream * fd, const char * mb, + struct mailimap_status_att_list * status_att_list); + +int + mailimap_store_send(mailstream * fd, + struct mailimap_set * set, int use_unchangedsince, uint64_t mod_sequence_valzer, + struct mailimap_store_att_flags * store_att_flags); + +int + mailimap_uid_store_send(mailstream * fd, + struct mailimap_set * set, int use_unchangedsince, uint64_t mod_sequence_valzer, + struct mailimap_store_att_flags * store_att_flags); + +int mailimap_subscribe_send(mailstream * fd, const char * mb); + + +int mailimap_tag_send(mailstream * fd, const char * tag); + +int mailimap_unsubscribe_send(mailstream * fd, + const char * mb); + +int mailimap_crlf_send(mailstream * fd); + +int mailimap_space_send(mailstream * fd); + +int +mailimap_literal_send(mailstream * fd, const char * literal, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_literal_count_send(mailstream * fd, size_t count); + +int +mailimap_literal_data_send(mailstream * fd, const char * literal, size_t len, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_literal_data_send_with_context(mailstream * fd, const char * literal, size_t len, + mailprogress_function * progr_fun, + void * context); + +int mailimap_starttls_send(mailstream * fd); + +int mailimap_token_send(mailstream * fd, const char * atom); + +int mailimap_quoted_send(mailstream * fd, const char * quoted); + +typedef int mailimap_struct_sender(mailstream * fd, void * data); + +int +mailimap_struct_spaced_list_send(mailstream * fd, clist * list, + mailimap_struct_sender * sender); + +int +mailimap_list_mailbox_send(mailstream * fd, const char * pattern); + +int mailimap_char_send(mailstream * fd, char ch); + +int mailimap_mailbox_send(mailstream * fd, const char * mb); + +int mailimap_astring_send(mailstream * fd, const char * astring); + +int mailimap_set_send(mailstream * fd, + struct mailimap_set * set); + +int mailimap_oparenth_send(mailstream * fd); + +int mailimap_cparenth_send(mailstream * fd); + +int mailimap_mod_sequence_value_send(mailstream * fd, uint64_t modseq); + +int mailimap_uint64_send(mailstream * fd, uint64_t number); + +int mailimap_number_send(mailstream * fd, uint32_t number); + +int mailimap_send_custom_command(mailstream *fd, const char * command); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/mailimap_socket.c b/Sources/libetpan/low-level/imap/mailimap_socket.c new file mode 100644 index 00000000..a6f578b0 --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_socket.c @@ -0,0 +1,187 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_socket.c,v 1.18 2009/12/19 00:57:31 hoa Exp $ + */ +#define HAVE_CONFIG_H 1 + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailimap_socket.h" + +#include "mailimap.h" + +#include "connect.h" + +#include +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif + +#include "mailstream_cfstream.h" + +#define DEFAULT_IMAP_PORT 143 +#define SERVICE_NAME_IMAP "imap2" +#define SERVICE_TYPE_TCP "tcp" + +#if HAVE_CFNETWORK +static int mailimap_cfsocket_connect_voip(mailimap * f, const char * server, uint16_t port, int voip_enabled); +#endif + +LIBETPAN_EXPORT +int mailimap_socket_connect_voip(mailimap * f, const char * server, uint16_t port, int voip_enabled) +{ + int s; + mailstream * stream; + + #if HAVE_CFNETWORK + if (mailstream_cfstream_enabled) { + return mailimap_cfsocket_connect_voip(f, server, port, voip_enabled); + } + #endif + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_IMAP, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_IMAP_PORT; + } + + /* Connection */ + + s = mail_tcp_connect_timeout(server, port, f->imap_timeout); + if (s == -1) + return MAILIMAP_ERROR_CONNECTION_REFUSED; + + stream = mailstream_socket_open_timeout(s, f->imap_timeout); + if (stream == NULL) { + #ifdef WIN32 + closesocket(s); + #else + close(s); + #endif + return MAILIMAP_ERROR_MEMORY; + } + + return mailimap_connect(f, stream); +} + +LIBETPAN_EXPORT +int mailimap_socket_connect(mailimap * f, const char * server, uint16_t port) +{ + return mailimap_socket_connect_voip(f, server, port, mailstream_cfstream_voip_enabled); +} + + +int mailimap_socket_starttls(mailimap * f) +{ + return mailimap_socket_starttls_with_callback(f, NULL, NULL); +} + +static int mailimap_cfsocket_starttls(mailimap * f); + +int mailimap_socket_starttls_with_callback(mailimap * f, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data) +{ + mailstream_low * low; + mailstream_low * new_low; + int r; + int fd; + + low = mailstream_get_low(f->imap_stream); + if (low->driver == mailstream_cfstream_driver) { + // won't use callback + return mailimap_cfsocket_starttls(f); + } + + r = mailimap_starttls(f); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return r; + } + + fd = mailstream_low_get_fd(low); + if (fd == -1) + return MAILIMAP_ERROR_STREAM; + + new_low = mailstream_low_tls_open_with_callback_timeout(fd, f->imap_timeout, + callback, data); + if (new_low == NULL) + return MAILIMAP_ERROR_STREAM; + + mailstream_low_free(low); + mailstream_set_low(f->imap_stream, new_low); + + return MAILIMAP_NO_ERROR; +} + +#if HAVE_CFNETWORK +static int mailimap_cfsocket_connect_voip(mailimap * f, const char * server, uint16_t port, int voip_enabled) +{ + mailstream * stream; + + stream = mailstream_cfstream_open_voip_timeout(server, port, voip_enabled, f->imap_timeout); + if (stream == NULL) { + return MAILIMAP_ERROR_CONNECTION_REFUSED; + } + + return mailimap_connect(f, stream); +} +#endif + +static int mailimap_cfsocket_starttls(mailimap * f) +{ + int r; + + r = mailimap_starttls(f); + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return r; + } + + mailstream_cfstream_set_ssl_verification_mask(f->imap_stream, MAILSTREAM_CFSTREAM_SSL_NO_VERIFICATION); + r = mailstream_cfstream_set_ssl_enabled(f->imap_stream, 1); + if (r < 0) { + return MAILIMAP_ERROR_SSL; + } + + return MAILIMAP_NO_ERROR; +} diff --git a/Sources/libetpan/low-level/imap/mailimap_socket.h b/Sources/libetpan/low-level/imap/mailimap_socket.h new file mode 100644 index 00000000..c6b18e56 --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_socket.h @@ -0,0 +1,67 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_socket.h,v 1.16 2006/12/26 13:13:24 hoa Exp $ + */ + +#ifndef MAILIMAP_SOCKET_H + +#define MAILIMAP_SOCKET_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_INTTYPES_H +# include +#endif + +#include + +LIBETPAN_EXPORT +int mailimap_socket_connect_voip(mailimap * f, const char * server, uint16_t port, int voip_enabled); + +LIBETPAN_EXPORT +int mailimap_socket_connect(mailimap * f, const char * server, uint16_t port); + +LIBETPAN_EXPORT +int mailimap_socket_starttls(mailimap * f); + +LIBETPAN_EXPORT +int mailimap_socket_starttls_with_callback(mailimap * f, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/mailimap_sort.c b/Sources/libetpan/low-level/imap/mailimap_sort.c new file mode 100644 index 00000000..aea119c2 --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_sort.c @@ -0,0 +1,455 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +// +// Created by Pitiphong Phongpattranont on 28/3/56 BE. +// +#include "mailimap_sort.h" + +#include +#include "mailimap.h" +#include "mailimap_extension.h" +#include "mailimap_extension_types.h" +#include "mailimap_sender.h" +#include "mailimap_parser.h" +#include "mailimap_keywords.h" +#include "mailimap_sender.h" + +enum { + MAILIMAP_SORT_TYPE_SORT +}; + + +int +mailimap_sort_send(mailstream * fd, const char * charset, + struct mailimap_sort_key * key, struct mailimap_search_key * searchkey); + +int +mailimap_uid_sort_send(mailstream * fd, const char * charset, + struct mailimap_sort_key * key, struct mailimap_search_key * searchkey); + +int mailimap_sort_key_send(mailstream * fd, + struct mailimap_sort_key * key); + +static int +mailimap_sort_extension_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, progress_function * progr_fun); + + +static void +mailimap_sort_extension_data_free(struct mailimap_extension_data * ext_data); + +LIBETPAN_EXPORT +struct mailimap_extension_api mailimap_extension_sort = { + /* name */ "SORT", + /* extension_id */ MAILIMAP_EXTENSION_SORT, + /* parser */ mailimap_sort_extension_parse, + /* free */ mailimap_sort_extension_data_free +}; + + +LIBETPAN_EXPORT +int +mailimap_sort(mailimap * session, const char * charset, + struct mailimap_sort_key * key, struct mailimap_search_key * searchkey, + clist ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + clist * sort_result = NULL; + clistiter * cur = NULL; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_sort_send(session->imap_stream, charset, key, searchkey); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + + for (cur = clist_begin(session->imap_response_info->rsp_extension_list); + cur != NULL; cur = clist_next(cur)) { + struct mailimap_extension_data * ext_data; + + ext_data = (struct mailimap_extension_data *) clist_content(cur); + if (ext_data->ext_extension->ext_id == MAILIMAP_EXTENSION_SORT) { + if (sort_result == NULL) { + sort_result = ext_data->ext_data; + ext_data->ext_data = NULL; + ext_data->ext_type = -1; + } + } + } + + clist_foreach(session->imap_response_info->rsp_extension_list, + (clist_func) mailimap_extension_data_free, NULL); + clist_free(session->imap_response_info->rsp_extension_list); + session->imap_response_info->rsp_extension_list = NULL; + + if (sort_result == NULL) { + sort_result = clist_new(); + } + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + break; + + default: + mailimap_search_result_free(sort_result); + return MAILIMAP_ERROR_EXTENSION; + } + + mailimap_response_free(response); + + * result = sort_result; + + return MAILIMAP_NO_ERROR; +} + +LIBETPAN_EXPORT +int +mailimap_uid_sort(mailimap * session, const char * charset, + struct mailimap_sort_key * key, struct mailimap_search_key * searchkey, + clist ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + clistiter * cur = NULL; + clist * sort_result = NULL; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uid_sort_send(session->imap_stream, charset, key, searchkey); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + + for (cur = clist_begin(session->imap_response_info->rsp_extension_list); + cur != NULL; cur = clist_next(cur)) { + struct mailimap_extension_data * ext_data; + + ext_data = (struct mailimap_extension_data *) clist_content(cur); + if (ext_data->ext_extension->ext_id == MAILIMAP_EXTENSION_SORT) { + if (sort_result == NULL) { + sort_result = ext_data->ext_data; + ext_data->ext_data = NULL; + ext_data->ext_type = -1; + } + } + } + + clist_foreach(session->imap_response_info->rsp_extension_list, + (clist_func) mailimap_extension_data_free, NULL); + clist_free(session->imap_response_info->rsp_extension_list); + session->imap_response_info->rsp_extension_list = NULL; + + if (sort_result == NULL) { + sort_result = clist_new(); + } + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + break; + + default: + mailimap_search_result_free(sort_result); + return MAILIMAP_ERROR_EXTENSION; + } + + mailimap_response_free(response); + + * result = sort_result; + + return MAILIMAP_NO_ERROR; +} + +LIBETPAN_EXPORT +void mailimap_sort_result_free(clist * search_result) +{ + clist_foreach(search_result, (clist_func) free, NULL); + clist_free(search_result); +} + + +int +mailimap_sort_send(mailstream * fd, const char * charset, + struct mailimap_sort_key * key, struct mailimap_search_key * searchkey) +{ + int r; + + r = mailimap_token_send(fd, "SORT"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_oparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_sort_key_send(fd, key); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_cparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (charset != NULL) { + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, charset); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (searchkey != NULL) { + r = mailimap_search_key_send(fd, searchkey); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + + return MAILIMAP_NO_ERROR; +} + +int +mailimap_uid_sort_send(mailstream * fd, const char * charset, + struct mailimap_sort_key * key, struct mailimap_search_key * searchkey) + +{ + int r; + + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return mailimap_sort_send(fd, charset, key, searchkey); +} + +int mailimap_sort_key_send(mailstream * fd, + struct mailimap_sort_key * key) +{ + int r; + + if (key->sortk_is_reverse) { + r = mailimap_token_send(fd, "REVERSE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + switch (key->sortk_type) { + + case MAILIMAP_SORT_KEY_ARRIVAL: + return mailimap_token_send(fd, "ARRIVAL"); + case MAILIMAP_SORT_KEY_CC: + return mailimap_token_send(fd, "CC"); + case MAILIMAP_SORT_KEY_DATE: + return mailimap_token_send(fd, "DATE"); + case MAILIMAP_SORT_KEY_FROM: + return mailimap_token_send(fd, "FROM"); + case MAILIMAP_SORT_KEY_SIZE: + return mailimap_token_send(fd, "SIZE"); + case MAILIMAP_SORT_KEY_SUBJECT: + return mailimap_token_send(fd, "SUBJECT"); + case MAILIMAP_SORT_KEY_TO: + return mailimap_token_send(fd, "TO"); + + case MAILIMAP_SORT_KEY_MULTIPLE: + return mailimap_struct_spaced_list_send(fd, key->sortk_multiple, + (mailimap_struct_sender *) + mailimap_sort_key_send); + + default: + /* should not happend */ + return MAILIMAP_ERROR_INVAL; + } +} + +static int +mailimap_number_list_data_sort_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + clist ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * number_list; + int r; + size_t final_token; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "SORT"); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + final_token = cur_token; + number_list = NULL; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, &cur_token, &number_list, + (mailimap_struct_parser *) + mailimap_nz_number_alloc_parse, + (mailimap_struct_destructor *) + mailimap_number_alloc_free, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) { + final_token = cur_token; + } + } + + * result = number_list; + * indx = final_token; + + return MAILIMAP_NO_ERROR; +} + +static int +mailimap_sort_extension_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, progress_function * progr_fun) +{ + int r; + clist * number_list = NULL; + struct mailimap_extension_data * ext_data; + void * data = NULL; + size_t cur_token; + + cur_token = * indx; + + switch (calling_parser) + { + case MAILIMAP_EXTENDED_PARSER_RESPONSE_DATA: + case MAILIMAP_EXTENDED_PARSER_MAILBOX_DATA: + r = mailimap_number_list_data_sort_parse(fd, buffer, NULL, &cur_token, + &number_list, progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) { + data = number_list; + } + + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + ext_data = mailimap_extension_data_new(&mailimap_extension_sort, + MAILIMAP_SORT_TYPE_SORT, data); + if (ext_data == NULL) { + if (number_list != NULL) + mailimap_mailbox_data_search_free(number_list); + return MAILIMAP_ERROR_MEMORY; + } + + * result = ext_data; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + default: + /* return a MAILIMAP_ERROR_PARSE if the extension + doesn't extend calling_parser. */ + return MAILIMAP_ERROR_PARSE; + } +} + +static void +mailimap_sort_extension_data_free(struct mailimap_extension_data * ext_data) +{ + if (ext_data->ext_data != NULL) { + mailimap_mailbox_data_search_free((clist *) ext_data->ext_data); + } + free(ext_data); +} + +LIBETPAN_EXPORT +int mailimap_has_sort(mailimap * session) +{ + return mailimap_has_extension(session, "SORT"); +} diff --git a/Sources/libetpan/low-level/imap/mailimap_sort.h b/Sources/libetpan/low-level/imap/mailimap_sort.h new file mode 100644 index 00000000..ed5f5857 --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_sort.h @@ -0,0 +1,105 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2011 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef libetpan_mailimap_sort_h +#define libetpan_mailimap_sort_h + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + + LIBETPAN_EXPORT + extern struct mailimap_extension_api mailimap_extension_sort; + + + /* + mailimap_sort() + + All mails that match the given criteria will be returned + their numbers sorted by the given sorting criteria in the result list. + + @param session IMAP session + @param charset This indicates the charset of the strings that appears + in the searching criteria + @param key This is the searching criteria + @param result The result is a clist of (uint32_t *) and will be + stored in (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + + LIBETPAN_EXPORT + int + mailimap_sort(mailimap * session, const char * charset, + struct mailimap_sort_key * key, struct mailimap_search_key * searchkey, + clist ** result); + + /* + mailimap_uid_sort() + + + All mails that match the given criteria will be returned + their unique identifiers sorted by the given sorting criteria in the result list. + + @param session IMAP session + @param charset This indicates the charset of the strings that appears + in the searching criteria + @param key This is the sorting criteria + @param searchkey This is the searching criteria + @param result The result is a clist of (uint32_t *) and will be + stored in (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + + LIBETPAN_EXPORT + int + mailimap_uid_sort(mailimap * session, const char * charset, + struct mailimap_sort_key * key, struct mailimap_search_key * searchkey, + clist ** result); + + LIBETPAN_EXPORT + void mailimap_sort_result_free(clist * search_result); + + LIBETPAN_EXPORT + int mailimap_has_sort(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/mailimap_sort_types.c b/Sources/libetpan/low-level/imap/mailimap_sort_types.c new file mode 100644 index 00000000..7d2f753f --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_sort_types.c @@ -0,0 +1,147 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +// +// Created by Pitiphong Phongpattranont on 28/3/56 BE. +// + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailimap_sort_types.h" +#include "mmapstring.h" +#include "mail.h" +#include "mailimap_extension.h" + +#include +#include +#include + + +struct mailimap_sort_key * +mailimap_sort_key_new(int sortk_type, + int is_reverse, + clist * sortk_multiple) { + struct mailimap_sort_key * key; + + key = malloc(sizeof(* key)); + if (key == NULL) + return NULL; + + key->sortk_type = sortk_type; + key->sortk_is_reverse = is_reverse; + + if (sortk_type == MAILIMAP_SORT_KEY_MULTIPLE) { + key->sortk_multiple = sortk_multiple; + } + + return key; +} + + +void mailimap_sort_key_free(struct mailimap_sort_key * key) { + if (key->sortk_type == MAILIMAP_SORT_KEY_MULTIPLE) { + clist_foreach(key->sortk_multiple, + (clist_func) mailimap_sort_key_free, NULL); + clist_free(key->sortk_multiple); + } + + free(key); +} + + +struct mailimap_sort_key * +mailimap_sort_key_new_arrival(int is_reverse) { + return mailimap_sort_key_new(MAILIMAP_SORT_KEY_ARRIVAL, is_reverse, NULL); +} + +struct mailimap_sort_key * +mailimap_sort_key_new_cc(int is_reverse) { + return mailimap_sort_key_new(MAILIMAP_SORT_KEY_CC, is_reverse, NULL); +} + +struct mailimap_sort_key * +mailimap_sort_key_new_date(int is_reverse) { + return mailimap_sort_key_new(MAILIMAP_SORT_KEY_DATE, is_reverse, NULL); +} + +struct mailimap_sort_key * +mailimap_sort_key_new_from(int is_reverse) { + return mailimap_sort_key_new(MAILIMAP_SORT_KEY_FROM, is_reverse, NULL); +} + +struct mailimap_sort_key * +mailimap_sort_key_new_size(int is_reverse) { + return mailimap_sort_key_new(MAILIMAP_SORT_KEY_SIZE, is_reverse, NULL); +} + +struct mailimap_sort_key * +mailimap_sort_key_new_subject(int is_reverse) { + return mailimap_sort_key_new(MAILIMAP_SORT_KEY_SUBJECT, is_reverse, NULL); +} + +struct mailimap_sort_key * +mailimap_sort_key_new_to(int is_reverse) { + return mailimap_sort_key_new(MAILIMAP_SORT_KEY_TO, is_reverse, NULL); +} + +struct mailimap_sort_key * +mailimap_sort_key_new_multiple(clist * keys) { + return mailimap_sort_key_new(MAILIMAP_SORT_KEY_MULTIPLE, false, keys); +} + + +struct mailimap_sort_key * +mailimap_sort_key_new_multiple_empty(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_sort_key_new_multiple(list); +} + +int +mailimap_sort_key_multiple_add(struct mailimap_sort_key * keys, + struct mailimap_sort_key * key_item) +{ + int r; + + r = clist_append(keys->sortk_multiple, key_item); + if (r < 0) + return MAILIMAP_ERROR_MEMORY; + + return MAILIMAP_NO_ERROR; +} + + diff --git a/Sources/libetpan/low-level/imap/mailimap_sort_types.h b/Sources/libetpan/low-level/imap/mailimap_sort_types.h new file mode 100644 index 00000000..7b8fa32a --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_sort_types.h @@ -0,0 +1,121 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2011 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef MAILIMAP_SORT_TYPES_H + +#define MAILIMAP_SORT_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef WIN32 +#include +#endif + +#include "mailimap_types.h" + + /* this is the condition of the SORT operation */ + + enum { + MAILIMAP_SORT_KEY_ARRIVAL, + MAILIMAP_SORT_KEY_CC, + MAILIMAP_SORT_KEY_DATE, + MAILIMAP_SORT_KEY_FROM, + MAILIMAP_SORT_KEY_SIZE, + MAILIMAP_SORT_KEY_SUBJECT, + MAILIMAP_SORT_KEY_TO, + MAILIMAP_SORT_KEY_MULTIPLE + }; + + struct mailimap_sort_key { + int sortk_type; + int sortk_is_reverse; + clist * sortk_multiple; /* list of (struct mailimap_sort_key *) */ + }; + + + LIBETPAN_EXPORT + struct mailimap_sort_key * + mailimap_sort_key_new(int sortk_type, + int is_reverse, + clist * sortk_multiple); + + LIBETPAN_EXPORT + void mailimap_sort_key_free(struct mailimap_sort_key * key); + + LIBETPAN_EXPORT + struct mailimap_sort_key * + mailimap_sort_key_new_arrival(int is_reverse); + + LIBETPAN_EXPORT + struct mailimap_sort_key * + mailimap_sort_key_new_cc(int is_reverse); + + LIBETPAN_EXPORT + struct mailimap_sort_key * + mailimap_sort_key_new_date(int is_reverse); + + LIBETPAN_EXPORT + struct mailimap_sort_key * + mailimap_sort_key_new_from(int is_reverse); + + LIBETPAN_EXPORT + struct mailimap_sort_key * + mailimap_sort_key_new_size(int is_reverse); + + LIBETPAN_EXPORT + struct mailimap_sort_key * + mailimap_sort_key_new_subject(int is_reverse); + + LIBETPAN_EXPORT + struct mailimap_sort_key * + mailimap_sort_key_new_to(int is_reverse); + + LIBETPAN_EXPORT + struct mailimap_sort_key * + mailimap_sort_key_new_multiple(clist * keys); + + LIBETPAN_EXPORT + struct mailimap_sort_key * + mailimap_sort_key_new_multiple_empty(void); + + LIBETPAN_EXPORT + int + mailimap_sort_key_multiple_add(struct mailimap_sort_key * keys, + struct mailimap_sort_key * key_item); + + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/Sources/libetpan/low-level/imap/mailimap_ssl.c b/Sources/libetpan/low-level/imap/mailimap_ssl.c new file mode 100644 index 00000000..8a59f50a --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_ssl.c @@ -0,0 +1,147 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_ssl.c,v 1.17 2009/12/19 00:57:31 hoa Exp $ + */ +#define HAVE_CONFIG_H 1 +#define HAVE_CFNETWORK 1 + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailimap_ssl.h" + +#include "mailimap.h" + +#include "connect.h" + +#include +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif + +#include "mailstream_cfstream.h" + +#define DEFAULT_IMAPS_PORT 993 +#define SERVICE_NAME_IMAPS "imaps" +#define SERVICE_TYPE_TCP "tcp" + +#if HAVE_CFNETWORK +static int mailimap_cfssl_connect_voip(mailimap * f, const char * server, uint16_t port, int voip_enabled); +#endif + +int mailimap_ssl_connect_with_callback(mailimap * f, const char * server, uint16_t port, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data) +{ + return mailimap_ssl_connect_voip_with_callback(f, server, port, mailstream_cfstream_voip_enabled, callback, data); +} + +int mailimap_ssl_connect_voip_with_callback(mailimap * f, const char * server, uint16_t port, int voip_enabled, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data) +{ + int s; + mailstream * stream; + +#if HAVE_CFNETWORK + if (mailstream_cfstream_enabled) { + if (callback == NULL) { + return mailimap_cfssl_connect_voip(f, server, port, voip_enabled); + } + } +#endif + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_IMAPS, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_IMAPS_PORT; + } + + /* Connection */ + + s = mail_tcp_connect_timeout(server, port, f->imap_timeout); + if (s == -1) + return MAILIMAP_ERROR_CONNECTION_REFUSED; + + stream = mailstream_ssl_open_with_callback_timeout(s, f->imap_timeout, callback, data); + if (stream == NULL) { +#ifdef WIN32 + closesocket(s); +#else + close(s); +#endif + return MAILIMAP_ERROR_SSL; + } + + return mailimap_connect(f, stream); +} + +int mailimap_ssl_connect(mailimap * f, const char * server, uint16_t port) +{ + return mailimap_ssl_connect_voip(f, server, port, mailstream_cfstream_voip_enabled); +} + +int mailimap_ssl_connect_voip(mailimap * f, const char * server, uint16_t port, int voip_enabled) +{ + return mailimap_ssl_connect_voip_with_callback(f, server, port, voip_enabled, + NULL, NULL); +} + +#if HAVE_CFNETWORK +static int mailimap_cfssl_connect_voip_ssl_level(mailimap * f, const char * server, uint16_t port, int voip_enabled, int ssl_level) +{ + mailstream * stream; + int r; + + stream = mailstream_cfstream_open_voip_timeout(server, port, voip_enabled, f->imap_timeout); + if (stream == NULL) { + return MAILIMAP_ERROR_CONNECTION_REFUSED; + } + mailstream_cfstream_set_ssl_level(stream, ssl_level); + mailstream_cfstream_set_ssl_verification_mask(stream, MAILSTREAM_CFSTREAM_SSL_NO_VERIFICATION); + r = mailstream_cfstream_set_ssl_enabled(stream, 1); + if (r < 0) { + mailstream_close(stream); + return MAILIMAP_ERROR_SSL; + } + + return mailimap_connect(f, stream); +} + +static int mailimap_cfssl_connect_voip(mailimap * f, const char * server, uint16_t port, int voip_enabled) +{ + return mailimap_cfssl_connect_voip_ssl_level(f, server, port, voip_enabled, MAILSTREAM_CFSTREAM_SSL_LEVEL_NEGOCIATED_SSL); +} +#endif diff --git a/Sources/libetpan/low-level/imap/mailimap_ssl.h b/Sources/libetpan/low-level/imap/mailimap_ssl.h new file mode 100644 index 00000000..499a7856 --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_ssl.h @@ -0,0 +1,68 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_ssl.h,v 1.16 2006/12/26 13:13:24 hoa Exp $ + */ + +#ifndef MAILIMAP_SSL_H + +#define MAILIMAP_SSL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_INTTYPES_H +# include +#endif + +#include + +LIBETPAN_EXPORT +int mailimap_ssl_connect(mailimap * f, const char * server, uint16_t port); + +LIBETPAN_EXPORT +int mailimap_ssl_connect_voip(mailimap * f, const char * server, uint16_t port, int voip_enabled); + +LIBETPAN_EXPORT +int mailimap_ssl_connect_with_callback(mailimap * f, const char * server, uint16_t port, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +LIBETPAN_EXPORT +int mailimap_ssl_connect_voip_with_callback(mailimap * f, const char * server, uint16_t port, int voip_enabled, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/mailimap_types.c b/Sources/libetpan/low-level/imap/mailimap_types.c new file mode 100644 index 00000000..9923125c --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_types.c @@ -0,0 +1,3287 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_types.c,v 1.31 2011/03/16 22:40:04 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailimap_types.h" +#include "mmapstring.h" +#include "mail.h" +#include "mailimap_extension.h" +#include "mailimap.h" + +#include +#include +#include + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + + + + + + +/* from parser */ + + +LIBETPAN_EXPORT +uint32_t * mailimap_number_alloc_new(uint32_t number) +{ + uint32_t * pnumber; + + pnumber = malloc(sizeof(* pnumber)); + if (pnumber == NULL) + return NULL; + + * pnumber = number; + + return pnumber; +} + +LIBETPAN_EXPORT +void mailimap_number_alloc_free(uint32_t * pnumber) +{ + free(pnumber); +} + + +/* ************************************************************************* */ + + +LIBETPAN_EXPORT +struct mailimap_address * +mailimap_address_new(char * ad_personal_name, char * ad_source_route, + char * ad_mailbox_name, char * ad_host_name) +{ + struct mailimap_address * addr; + + addr = malloc(sizeof(* addr)); + if (addr == NULL) + return NULL; + + addr->ad_personal_name = ad_personal_name; + addr->ad_source_route = ad_source_route; + addr->ad_mailbox_name = ad_mailbox_name; + addr->ad_host_name = ad_host_name; + + return addr; +} + +LIBETPAN_EXPORT +void mailimap_address_free(struct mailimap_address * addr) +{ + mailimap_addr_host_free(addr->ad_host_name); + mailimap_addr_mailbox_free(addr->ad_mailbox_name); + mailimap_addr_adl_free(addr->ad_source_route); + mailimap_addr_name_free(addr->ad_personal_name); + free(addr); +} + +LIBETPAN_EXPORT +void mailimap_addr_host_free(char * addr_host) +{ + mailimap_nstring_free(addr_host); +} + +LIBETPAN_EXPORT +void mailimap_addr_mailbox_free(char * addr_mailbox) +{ + mailimap_nstring_free(addr_mailbox); +} + +LIBETPAN_EXPORT +void mailimap_addr_adl_free(char * addr_adl) +{ + mailimap_nstring_free(addr_adl); +} + +LIBETPAN_EXPORT +void mailimap_addr_name_free(char * addr_name) +{ + mailimap_nstring_free(addr_name); +} + + + + + +LIBETPAN_EXPORT +void mailimap_astring_free(char * astring) +{ + if (mmap_string_unref(astring) != 0) + free(astring); +} + +static void mailimap_custom_string_free(char * str) +{ + free(str); +} + + +LIBETPAN_EXPORT +void mailimap_atom_free(char * atom) +{ + free(atom); +} + + + + +LIBETPAN_EXPORT +void mailimap_auth_type_free(char * auth_type) +{ + mailimap_atom_free(auth_type); +} + + + + + +LIBETPAN_EXPORT +void mailimap_base64_free(char * base64) +{ + free(base64); +} + + + + +LIBETPAN_EXPORT +struct mailimap_body * +mailimap_body_new(int bd_type, + struct mailimap_body_type_1part * bd_body_1part, + struct mailimap_body_type_mpart * bd_body_mpart) +{ + struct mailimap_body * body; + + body = malloc(sizeof(* body)); + if (body == NULL) + return NULL; + + body->bd_type = bd_type; + switch (bd_type) { + case MAILIMAP_BODY_1PART: + body->bd_data.bd_body_1part = bd_body_1part; + break; + case MAILIMAP_BODY_MPART: + body->bd_data.bd_body_mpart = bd_body_mpart; + break; + } + + return body; +} + +LIBETPAN_EXPORT +void mailimap_body_free(struct mailimap_body * body) +{ + switch (body->bd_type) { + case MAILIMAP_BODY_1PART: + mailimap_body_type_1part_free(body->bd_data.bd_body_1part); + break; + case MAILIMAP_BODY_MPART: + mailimap_body_type_mpart_free(body->bd_data.bd_body_mpart); + break; + } + free(body); +} + + +LIBETPAN_EXPORT +struct mailimap_body_extension * +mailimap_body_extension_new(int ext_type, char * ext_nstring, + uint32_t ext_number, + clist * ext_body_extension_list) +{ + struct mailimap_body_extension * body_extension; + + body_extension = malloc(sizeof(* body_extension)); + if (body_extension == NULL) + return NULL; + + body_extension->ext_type = ext_type; + switch (ext_type) { + case MAILIMAP_BODY_EXTENSION_NSTRING: + body_extension->ext_data.ext_nstring = ext_nstring; + break; + case MAILIMAP_BODY_EXTENSION_NUMBER: + body_extension->ext_data.ext_number = ext_number; + break; + case MAILIMAP_BODY_EXTENSION_LIST: + body_extension->ext_data.ext_body_extension_list = ext_body_extension_list; + break; + } + + return body_extension; +} + +static void +mailimap_body_ext_list_free(clist * body_ext_list); + +LIBETPAN_EXPORT +void mailimap_body_extension_free(struct mailimap_body_extension * be) +{ + switch (be->ext_type) { + case MAILIMAP_BODY_EXTENSION_NSTRING: + mailimap_nstring_free(be->ext_data.ext_nstring); + break; + case MAILIMAP_BODY_EXTENSION_LIST: + mailimap_body_ext_list_free(be->ext_data.ext_body_extension_list); + break; + } + + free(be); +} + + +static void +mailimap_body_ext_list_free(clist * body_ext_list) +{ + clist_foreach(body_ext_list, (clist_func) mailimap_body_extension_free, + NULL); + clist_free(body_ext_list); +} + + +LIBETPAN_EXPORT +struct mailimap_body_ext_1part * +mailimap_body_ext_1part_new(char * bd_md5, + struct mailimap_body_fld_dsp * bd_disposition, + struct mailimap_body_fld_lang * bd_language, + char * bd_loc, + clist * bd_extension_list) +{ + struct mailimap_body_ext_1part * body_ext_1part; + + body_ext_1part = malloc(sizeof(* body_ext_1part)); + if (body_ext_1part == NULL) + return NULL; + + body_ext_1part->bd_md5 = bd_md5; + body_ext_1part->bd_disposition = bd_disposition; + body_ext_1part->bd_language = bd_language; + body_ext_1part->bd_loc = bd_loc; + body_ext_1part->bd_extension_list = bd_extension_list; + + return body_ext_1part; +} + +LIBETPAN_EXPORT +void +mailimap_body_ext_1part_free(struct mailimap_body_ext_1part * body_ext_1part) +{ + mailimap_body_fld_md5_free(body_ext_1part->bd_md5); + if (body_ext_1part->bd_disposition) + mailimap_body_fld_dsp_free(body_ext_1part->bd_disposition); + if (body_ext_1part->bd_language) + mailimap_body_fld_lang_free(body_ext_1part->bd_language); + if (body_ext_1part->bd_extension_list) + mailimap_body_ext_list_free(body_ext_1part->bd_extension_list); + mailimap_body_fld_loc_free(body_ext_1part->bd_loc); + + free(body_ext_1part); +} + +LIBETPAN_EXPORT +struct mailimap_body_ext_mpart * +mailimap_body_ext_mpart_new(struct mailimap_body_fld_param * bd_parameter, + struct mailimap_body_fld_dsp * bd_disposition, + struct mailimap_body_fld_lang * bd_language, + char * bd_loc, + clist * bd_extension_list) +{ + struct mailimap_body_ext_mpart * body_ext_mpart; + + body_ext_mpart = malloc(sizeof(* body_ext_mpart)); + if (body_ext_mpart == NULL) + return NULL; + + body_ext_mpart->bd_parameter = bd_parameter; + body_ext_mpart->bd_disposition = bd_disposition; + body_ext_mpart->bd_language = bd_language; + body_ext_mpart->bd_extension_list = bd_extension_list; + body_ext_mpart->bd_loc = bd_loc; + + return body_ext_mpart; +} + +LIBETPAN_EXPORT +void +mailimap_body_ext_mpart_free(struct mailimap_body_ext_mpart * body_ext_mpart) +{ + if (body_ext_mpart->bd_parameter != NULL) + mailimap_body_fld_param_free(body_ext_mpart->bd_parameter); + if (body_ext_mpart->bd_disposition) + mailimap_body_fld_dsp_free(body_ext_mpart->bd_disposition); + if (body_ext_mpart->bd_language) + mailimap_body_fld_lang_free(body_ext_mpart->bd_language); + if (body_ext_mpart->bd_extension_list) + mailimap_body_ext_list_free(body_ext_mpart->bd_extension_list); + mailimap_body_fld_loc_free(body_ext_mpart->bd_loc); + free(body_ext_mpart); +} + + +LIBETPAN_EXPORT +struct mailimap_body_fields * +mailimap_body_fields_new(struct mailimap_body_fld_param * bd_parameter, + char * bd_id, + char * bd_description, + struct mailimap_body_fld_enc * bd_encoding, + uint32_t bd_size) +{ + struct mailimap_body_fields * body_fields; + + body_fields = malloc(sizeof(* body_fields)); + if (body_fields == NULL) + return NULL; + body_fields->bd_parameter = bd_parameter; + body_fields->bd_id = bd_id; + body_fields->bd_description = bd_description; + body_fields->bd_encoding = bd_encoding; + body_fields->bd_size = bd_size; + + return body_fields; +} + +LIBETPAN_EXPORT +void +mailimap_body_fields_free(struct mailimap_body_fields * body_fields) +{ + if (body_fields->bd_parameter != NULL) + mailimap_body_fld_param_free(body_fields->bd_parameter); + mailimap_body_fld_id_free(body_fields->bd_id); + mailimap_body_fld_desc_free(body_fields->bd_description); + mailimap_body_fld_enc_free(body_fields->bd_encoding); + free(body_fields); +} + + + + + + +LIBETPAN_EXPORT +void mailimap_body_fld_desc_free(char * body_fld_desc) +{ + mailimap_nstring_free(body_fld_desc); +} + + + + +LIBETPAN_EXPORT +struct mailimap_body_fld_dsp * +mailimap_body_fld_dsp_new(char * dsp_type, + struct mailimap_body_fld_param * dsp_attributes) +{ + struct mailimap_body_fld_dsp * body_fld_dsp; + + body_fld_dsp = malloc(sizeof(* body_fld_dsp)); + if (body_fld_dsp == NULL) + return NULL; + + body_fld_dsp->dsp_type = dsp_type; + body_fld_dsp->dsp_attributes = dsp_attributes; + + return body_fld_dsp; +} + +LIBETPAN_EXPORT +void mailimap_body_fld_dsp_free(struct mailimap_body_fld_dsp * bfd) +{ + if (bfd->dsp_type != NULL) + mailimap_string_free(bfd->dsp_type); + if (bfd->dsp_attributes != NULL) + mailimap_body_fld_param_free(bfd->dsp_attributes); + free(bfd); +} + + + +LIBETPAN_EXPORT +struct mailimap_body_fld_enc * +mailimap_body_fld_enc_new(int enc_type, char * enc_value) +{ + struct mailimap_body_fld_enc * body_fld_enc; + + body_fld_enc = malloc(sizeof(* body_fld_enc)); + if (body_fld_enc == NULL) + return NULL; + + body_fld_enc->enc_type = enc_type; + body_fld_enc->enc_value = enc_value; + + return body_fld_enc; +} + +LIBETPAN_EXPORT +void mailimap_body_fld_enc_free(struct mailimap_body_fld_enc * bfe) +{ + if (bfe->enc_value) + mailimap_string_free(bfe->enc_value); + free(bfe); +} + + + +LIBETPAN_EXPORT +void mailimap_body_fld_id_free(char * body_fld_id) +{ + mailimap_nstring_free(body_fld_id); +} + + + +LIBETPAN_EXPORT +struct mailimap_body_fld_lang * +mailimap_body_fld_lang_new(int lg_type, char * lg_single, clist * lg_list) +{ + struct mailimap_body_fld_lang * fld_lang; + + fld_lang = malloc(sizeof(* fld_lang)); + if (fld_lang == NULL) + return NULL; + + fld_lang->lg_type = lg_type; + switch (lg_type) { + case MAILIMAP_BODY_FLD_LANG_SINGLE: + fld_lang->lg_data.lg_single = lg_single; + break; + case MAILIMAP_BODY_FLD_LANG_LIST: + fld_lang->lg_data.lg_list = lg_list; + break; + } + + return fld_lang; +} + +LIBETPAN_EXPORT +void +mailimap_body_fld_lang_free(struct mailimap_body_fld_lang * fld_lang) +{ + switch (fld_lang->lg_type) { + case MAILIMAP_BODY_FLD_LANG_SINGLE: + mailimap_nstring_free(fld_lang->lg_data.lg_single); + break; + case MAILIMAP_BODY_FLD_LANG_LIST: + clist_foreach(fld_lang->lg_data.lg_list, + (clist_func) mailimap_string_free, NULL); + clist_free(fld_lang->lg_data.lg_list); + break; + } + free(fld_lang); +} + + + +LIBETPAN_EXPORT +void mailimap_body_fld_md5_free(char * body_fld_md5) +{ + mailimap_nstring_free(body_fld_md5); +} + +LIBETPAN_EXPORT +void mailimap_body_fld_loc_free(char * body_fld_loc) +{ + mailimap_nstring_free(body_fld_loc); +} + + +LIBETPAN_EXPORT +struct mailimap_single_body_fld_param * +mailimap_single_body_fld_param_new(char * pa_name, char * pa_value) +{ + struct mailimap_single_body_fld_param * param; + + param = malloc(sizeof(* param)); + if (param == NULL) + return NULL; + param->pa_name = pa_name; + param->pa_value = pa_value; + + return param; +} + +LIBETPAN_EXPORT +void +mailimap_single_body_fld_param_free(struct mailimap_single_body_fld_param * p) +{ + mailimap_string_free(p->pa_name); + mailimap_string_free(p->pa_value); + free(p); +} + + +LIBETPAN_EXPORT +struct mailimap_body_fld_param * +mailimap_body_fld_param_new(clist * pa_list) +{ + struct mailimap_body_fld_param * fld_param; + + fld_param = malloc(sizeof(* fld_param)); + if (fld_param == NULL) + return NULL; + fld_param->pa_list = pa_list; + + return fld_param; +} + +LIBETPAN_EXPORT +void +mailimap_body_fld_param_free(struct mailimap_body_fld_param * fld_param) +{ + clist_foreach(fld_param->pa_list, + (clist_func) mailimap_single_body_fld_param_free, NULL); + clist_free(fld_param->pa_list); + free(fld_param); +} + + +LIBETPAN_EXPORT +struct mailimap_body_type_1part * +mailimap_body_type_1part_new(int bd_type, + struct mailimap_body_type_basic * bd_type_basic, + struct mailimap_body_type_msg * bd_type_msg, + struct mailimap_body_type_text * bd_type_text, + struct mailimap_body_ext_1part * bd_ext_1part) +{ + struct mailimap_body_type_1part * body_type_1part; + + body_type_1part = malloc(sizeof(* body_type_1part)); + if (body_type_1part == NULL) + return NULL; + + body_type_1part->bd_type = bd_type; + switch (bd_type) { + case MAILIMAP_BODY_TYPE_1PART_BASIC: + body_type_1part->bd_data.bd_type_basic = bd_type_basic; + break; + case MAILIMAP_BODY_TYPE_1PART_MSG: + body_type_1part->bd_data.bd_type_msg = bd_type_msg; + break; + case MAILIMAP_BODY_TYPE_1PART_TEXT: + body_type_1part->bd_data.bd_type_text = bd_type_text; + break; + } + body_type_1part->bd_ext_1part = bd_ext_1part; + + return body_type_1part; +} + +LIBETPAN_EXPORT +void +mailimap_body_type_1part_free(struct mailimap_body_type_1part * bt1p) +{ + switch (bt1p->bd_type) { + case MAILIMAP_BODY_TYPE_1PART_BASIC: + mailimap_body_type_basic_free(bt1p->bd_data.bd_type_basic); + break; + case MAILIMAP_BODY_TYPE_1PART_MSG: + mailimap_body_type_msg_free(bt1p->bd_data.bd_type_msg); + break; + case MAILIMAP_BODY_TYPE_1PART_TEXT: + mailimap_body_type_text_free(bt1p->bd_data.bd_type_text); + break; + } + if (bt1p->bd_ext_1part) + mailimap_body_ext_1part_free(bt1p->bd_ext_1part); + + free(bt1p); +} + + + +LIBETPAN_EXPORT +struct mailimap_body_type_basic * +mailimap_body_type_basic_new(struct mailimap_media_basic * bd_media_basic, + struct mailimap_body_fields * bd_fields) +{ + struct mailimap_body_type_basic * body_type_basic; + + body_type_basic = malloc(sizeof(* body_type_basic)); + if (body_type_basic == NULL) + return NULL; + + body_type_basic->bd_media_basic = bd_media_basic; + body_type_basic->bd_fields = bd_fields; + + return body_type_basic; +} + +LIBETPAN_EXPORT +void mailimap_body_type_basic_free(struct mailimap_body_type_basic * + body_type_basic) +{ + mailimap_media_basic_free(body_type_basic->bd_media_basic); + mailimap_body_fields_free(body_type_basic->bd_fields); + free(body_type_basic); +} + + +LIBETPAN_EXPORT +struct mailimap_body_type_mpart * +mailimap_body_type_mpart_new(clist * bd_list, char * bd_media_subtype, + struct mailimap_body_ext_mpart * bd_ext_mpart) +{ + struct mailimap_body_type_mpart * body_type_mpart; + + body_type_mpart = malloc(sizeof(* body_type_mpart)); + if (body_type_mpart == NULL) + return NULL; + + body_type_mpart->bd_list = bd_list; + body_type_mpart->bd_media_subtype = bd_media_subtype; + body_type_mpart->bd_ext_mpart = bd_ext_mpart; + + return body_type_mpart; +} + +LIBETPAN_EXPORT +void mailimap_body_type_mpart_free(struct mailimap_body_type_mpart * + body_type_mpart) +{ + clist_foreach(body_type_mpart->bd_list, + (clist_func) mailimap_body_free, NULL); + clist_free(body_type_mpart->bd_list); + mailimap_media_subtype_free(body_type_mpart->bd_media_subtype); + if (body_type_mpart->bd_ext_mpart) + mailimap_body_ext_mpart_free(body_type_mpart->bd_ext_mpart); + + free(body_type_mpart); +} + + +LIBETPAN_EXPORT +struct mailimap_body_type_msg * +mailimap_body_type_msg_new(struct mailimap_body_fields * bd_fields, + struct mailimap_envelope * bd_envelope, + struct mailimap_body * bd_body, + uint32_t bd_lines) +{ + struct mailimap_body_type_msg * body_type_msg; + + body_type_msg = malloc(sizeof(* body_type_msg)); + if (body_type_msg == NULL) + return NULL; + + body_type_msg->bd_fields = bd_fields; + body_type_msg->bd_envelope = bd_envelope; + body_type_msg->bd_body = bd_body; + body_type_msg->bd_lines = bd_lines; + + return body_type_msg; +} + +LIBETPAN_EXPORT +void +mailimap_body_type_msg_free(struct mailimap_body_type_msg * body_type_msg) +{ + mailimap_body_fields_free(body_type_msg->bd_fields); + mailimap_envelope_free(body_type_msg->bd_envelope); + mailimap_body_free(body_type_msg->bd_body); + free(body_type_msg); +} + + + +LIBETPAN_EXPORT +struct mailimap_body_type_text * +mailimap_body_type_text_new(char * bd_media_text, + struct mailimap_body_fields * bd_fields, + uint32_t bd_lines) +{ + struct mailimap_body_type_text * body_type_text; + + body_type_text = malloc(sizeof(* body_type_text)); + if (body_type_text == NULL) + return NULL; + + body_type_text->bd_media_text = bd_media_text; + body_type_text->bd_fields = bd_fields; + body_type_text->bd_lines = bd_lines; + + return body_type_text; +} + +LIBETPAN_EXPORT +void +mailimap_body_type_text_free(struct mailimap_body_type_text * body_type_text) +{ + mailimap_media_text_free(body_type_text->bd_media_text); + mailimap_body_fields_free(body_type_text->bd_fields); + free(body_type_text); +} + + + +LIBETPAN_EXPORT +struct mailimap_capability * +mailimap_capability_new(int cap_type, char * cap_auth_type, char * cap_name) +{ + struct mailimap_capability * cap; + + cap = malloc(sizeof(* cap)); + if (cap == NULL) + return NULL; + cap->cap_type = cap_type; + switch (cap_type) { + case MAILIMAP_CAPABILITY_AUTH_TYPE: + cap->cap_data.cap_auth_type = cap_auth_type; + break; + case MAILIMAP_CAPABILITY_NAME: + cap->cap_data.cap_name = cap_name; + break; + } + + return cap; +} + +LIBETPAN_EXPORT +void mailimap_capability_free(struct mailimap_capability * c) +{ + switch (c->cap_type) { + case MAILIMAP_CAPABILITY_AUTH_TYPE: + free(c->cap_data.cap_auth_type); + break; + case MAILIMAP_CAPABILITY_NAME: + free(c->cap_data.cap_name); + break; + } + free(c); +} + + +LIBETPAN_EXPORT +struct mailimap_capability_data * +mailimap_capability_data_new(clist * cap_list) +{ + struct mailimap_capability_data * cap_data; + + cap_data = malloc(sizeof(* cap_data)); + if (cap_data == NULL) + return NULL; + + cap_data->cap_list = cap_list; + + return cap_data; +} + +LIBETPAN_EXPORT +void +mailimap_capability_data_free(struct mailimap_capability_data * cap_data) +{ + if (cap_data->cap_list) { + clist_foreach(cap_data->cap_list, + (clist_func) mailimap_capability_free, NULL); + clist_free(cap_data->cap_list); + } + free(cap_data); +} + + + + +LIBETPAN_EXPORT +struct mailimap_continue_req * +mailimap_continue_req_new(int cr_type, struct mailimap_resp_text * cr_text, + char * cr_base64) +{ + struct mailimap_continue_req * cont_req; + + cont_req = malloc(sizeof(* cont_req)); + if (cont_req == NULL) + return NULL; + cont_req->cr_type = cr_type; + switch (cr_type) { + case MAILIMAP_CONTINUE_REQ_TEXT: + cont_req->cr_data.cr_text = cr_text; + break; + case MAILIMAP_CONTINUE_REQ_BASE64: + cont_req->cr_data.cr_base64 = cr_base64; + break; + } + + return cont_req; +} + +LIBETPAN_EXPORT +void mailimap_continue_req_free(struct mailimap_continue_req * cont_req) +{ + switch (cont_req->cr_type) { + case MAILIMAP_CONTINUE_REQ_TEXT: + mailimap_resp_text_free(cont_req->cr_data.cr_text); + break; + case MAILIMAP_CONTINUE_REQ_BASE64: + mailimap_base64_free(cont_req->cr_data.cr_base64); + break; + } + free(cont_req); +} + +LIBETPAN_EXPORT +struct mailimap_date_time * +mailimap_date_time_new(int dt_day, int dt_month, int dt_year, int dt_hour, + int dt_min, int dt_sec, int dt_zone) +{ + struct mailimap_date_time * date_time; + + date_time = malloc(sizeof(* date_time)); + if (date_time == NULL) + return NULL; + + date_time->dt_day = dt_day; + date_time->dt_month = dt_month; + date_time->dt_year = dt_year; + date_time->dt_hour = dt_hour; + date_time->dt_min = dt_min; + date_time->dt_sec = dt_sec; + date_time->dt_zone = dt_zone; + + return date_time; +} + +LIBETPAN_EXPORT +void mailimap_date_time_free(struct mailimap_date_time * date_time) +{ + free(date_time); +} + + + +LIBETPAN_EXPORT +struct mailimap_envelope * +mailimap_envelope_new(char * env_date, char * env_subject, + struct mailimap_env_from * env_from, + struct mailimap_env_sender * env_sender, + struct mailimap_env_reply_to * env_reply_to, + struct mailimap_env_to * env_to, + struct mailimap_env_cc* env_cc, + struct mailimap_env_bcc * env_bcc, + char * env_in_reply_to, char * env_message_id) +{ + struct mailimap_envelope * env; + + env = malloc(sizeof(* env)); + if (env == NULL) + return NULL; + + env->env_date = env_date; + env->env_subject = env_subject; + env->env_from = env_from; + env->env_sender = env_sender; + env->env_reply_to = env_reply_to; + env->env_to = env_to; + env->env_cc = env_cc; + env->env_bcc = env_bcc; + env->env_in_reply_to = env_in_reply_to; + env->env_message_id = env_message_id; + + return env; +} + + +LIBETPAN_EXPORT +void mailimap_envelope_free(struct mailimap_envelope * env) +{ + if (env->env_date) + mailimap_env_date_free(env->env_date); + if (env->env_subject) + mailimap_env_subject_free(env->env_subject); + if (env->env_from) + mailimap_env_from_free(env->env_from); + if (env->env_sender) + mailimap_env_sender_free(env->env_sender); + if (env->env_reply_to) + mailimap_env_reply_to_free(env->env_reply_to); + if (env->env_to) + mailimap_env_to_free(env->env_to); + if (env->env_cc) + mailimap_env_cc_free(env->env_cc); + if (env->env_bcc) + mailimap_env_bcc_free(env->env_bcc); + if (env->env_in_reply_to) + mailimap_env_in_reply_to_free(env->env_in_reply_to); + if (env->env_message_id) + mailimap_env_message_id_free(env->env_message_id); + + free(env); +} + + +static void mailimap_address_list_free(clist * addr_list) +{ + if (addr_list != NULL) { + clist_foreach(addr_list, (clist_func) mailimap_address_free, NULL); + clist_free(addr_list); + } +} + + +LIBETPAN_EXPORT +struct mailimap_env_bcc * mailimap_env_bcc_new(clist * bcc_list) +{ + struct mailimap_env_bcc * env_bcc; + + env_bcc = malloc(sizeof(* env_bcc)); + if (env_bcc == NULL) + return NULL; + env_bcc->bcc_list = bcc_list; + + return env_bcc; +} + +LIBETPAN_EXPORT +void mailimap_env_bcc_free(struct mailimap_env_bcc * env_bcc) +{ + mailimap_address_list_free(env_bcc->bcc_list); + free(env_bcc); +} + + +LIBETPAN_EXPORT +struct mailimap_env_cc * mailimap_env_cc_new(clist * cc_list) +{ + struct mailimap_env_cc * env_cc; + + env_cc = malloc(sizeof(* env_cc)); + if (env_cc == NULL) + return NULL; + env_cc->cc_list = cc_list; + + return env_cc; +} + +LIBETPAN_EXPORT +void mailimap_env_cc_free(struct mailimap_env_cc * env_cc) +{ + mailimap_address_list_free(env_cc->cc_list); + free(env_cc); +} + + +LIBETPAN_EXPORT +void mailimap_env_date_free(char * date) +{ + mailimap_nstring_free(date); +} + + +LIBETPAN_EXPORT +struct mailimap_env_from * mailimap_env_from_new(clist * frm_list) +{ + struct mailimap_env_from * env_from; + + env_from = malloc(sizeof(* env_from)); + if (env_from == NULL) + return NULL; + env_from->frm_list = frm_list; + + return env_from; +} + +LIBETPAN_EXPORT +void mailimap_env_from_free(struct mailimap_env_from * env_from) +{ + mailimap_address_list_free(env_from->frm_list); + free(env_from); +} + + +void mailimap_env_in_reply_to_free(char * in_reply_to) +{ + mailimap_nstring_free(in_reply_to); +} + +void mailimap_env_message_id_free(char * message_id) +{ + mailimap_nstring_free(message_id); +} + +LIBETPAN_EXPORT +struct mailimap_env_reply_to * mailimap_env_reply_to_new(clist * rt_list) +{ + struct mailimap_env_reply_to * env_reply_to; + + env_reply_to = malloc(sizeof(* env_reply_to)); + if (env_reply_to == NULL) + return NULL; + env_reply_to->rt_list = rt_list; + + return env_reply_to; +} + +LIBETPAN_EXPORT +void +mailimap_env_reply_to_free(struct mailimap_env_reply_to * env_reply_to) +{ + mailimap_address_list_free(env_reply_to->rt_list); + free(env_reply_to); +} + +LIBETPAN_EXPORT +struct mailimap_env_sender * mailimap_env_sender_new(clist * snd_list) +{ + struct mailimap_env_sender * env_sender; + + env_sender = malloc(sizeof(* env_sender)); + if (env_sender == NULL) + return NULL; + env_sender->snd_list = snd_list; + + return env_sender; +} + +LIBETPAN_EXPORT +void mailimap_env_sender_free(struct mailimap_env_sender * env_sender) +{ + mailimap_address_list_free(env_sender->snd_list); + free(env_sender); +} + +void mailimap_env_subject_free(char * subject) +{ + mailimap_nstring_free(subject); +} + +LIBETPAN_EXPORT +struct mailimap_env_to * mailimap_env_to_new(clist * to_list) +{ + struct mailimap_env_to * env_to; + + env_to = malloc(sizeof(* env_to)); + if (env_to == NULL) + return NULL; + env_to->to_list = to_list; + + return env_to; +} + +LIBETPAN_EXPORT +void mailimap_env_to_free(struct mailimap_env_to * env_to) +{ + mailimap_address_list_free(env_to->to_list); + free(env_to); +} + + + +LIBETPAN_EXPORT +struct mailimap_flag * mailimap_flag_new(int fl_type, + char * fl_keyword, char * fl_extension) +{ + struct mailimap_flag * f; + + f = malloc(sizeof(* f)); + if (f == NULL) + return NULL; + f->fl_type = fl_type; + switch (fl_type) { + case MAILIMAP_FLAG_KEYWORD: + f->fl_data.fl_keyword = fl_keyword; + break; + case MAILIMAP_FLAG_EXTENSION: + f->fl_data.fl_extension = fl_extension; + break; + } + + return f; +} + +LIBETPAN_EXPORT +void mailimap_flag_free(struct mailimap_flag * f) +{ + switch (f->fl_type) { + case MAILIMAP_FLAG_KEYWORD: + mailimap_flag_keyword_free(f->fl_data.fl_keyword); + break; + case MAILIMAP_FLAG_EXTENSION: + mailimap_flag_extension_free(f->fl_data.fl_extension); + break; + } + free(f); +} + + + +LIBETPAN_EXPORT +void mailimap_flag_extension_free(char * flag_extension) +{ + mailimap_atom_free(flag_extension); +} + + + +LIBETPAN_EXPORT +struct mailimap_flag_fetch * +mailimap_flag_fetch_new(int fl_type, struct mailimap_flag * fl_flag) +{ + struct mailimap_flag_fetch * flag_fetch; + + flag_fetch = malloc(sizeof(* flag_fetch)); + if (flag_fetch == NULL) + return NULL; + + flag_fetch->fl_type = fl_type; + flag_fetch->fl_flag = fl_flag; + + return flag_fetch; +} + +LIBETPAN_EXPORT +void mailimap_flag_fetch_free(struct mailimap_flag_fetch * flag_fetch) +{ + if (flag_fetch->fl_flag) + mailimap_flag_free(flag_fetch->fl_flag); + free(flag_fetch); +} + + + +LIBETPAN_EXPORT +void mailimap_flag_keyword_free(char * flag_keyword) +{ + mailimap_atom_free(flag_keyword); +} + + + + +LIBETPAN_EXPORT +struct mailimap_flag_list * +mailimap_flag_list_new(clist * fl_list) +{ + struct mailimap_flag_list * flag_list; + + flag_list = malloc(sizeof(* flag_list)); + if (flag_list == NULL) + return NULL; + flag_list->fl_list = fl_list; + + return flag_list; +} + +LIBETPAN_EXPORT +void mailimap_flag_list_free(struct mailimap_flag_list * flag_list) +{ + if (flag_list->fl_list) { + clist_foreach(flag_list->fl_list, (clist_func) mailimap_flag_free, NULL); + clist_free(flag_list->fl_list); + } + free(flag_list); +} + + + + + +LIBETPAN_EXPORT +struct mailimap_flag_perm * +mailimap_flag_perm_new(int fl_type, struct mailimap_flag * fl_flag) +{ + struct mailimap_flag_perm * flag_perm; + + flag_perm = malloc(sizeof(* flag_perm)); + if (flag_perm == NULL) + return NULL; + + flag_perm->fl_type = fl_type; + flag_perm->fl_flag = fl_flag; + + return flag_perm; +} + +LIBETPAN_EXPORT +void mailimap_flag_perm_free(struct mailimap_flag_perm * flag_perm) +{ + if (flag_perm->fl_flag != NULL) + mailimap_flag_free(flag_perm->fl_flag); + free(flag_perm); +} + + + + +LIBETPAN_EXPORT +struct mailimap_greeting * +mailimap_greeting_new(int gr_type, + struct mailimap_resp_cond_auth * gr_auth, + struct mailimap_resp_cond_bye * gr_bye) +{ + struct mailimap_greeting * greeting; + + greeting = malloc(sizeof(* greeting)); + if (greeting == NULL) + return NULL; + greeting->gr_type = gr_type; + switch (gr_type) { + case MAILIMAP_GREETING_RESP_COND_AUTH: + greeting->gr_data.gr_auth = gr_auth; + break; + case MAILIMAP_GREETING_RESP_COND_BYE: + greeting->gr_data.gr_bye = gr_bye; + break; + } + + return greeting; +} + +LIBETPAN_EXPORT +void mailimap_greeting_free(struct mailimap_greeting * greeting) +{ + switch (greeting->gr_type) { + case MAILIMAP_GREETING_RESP_COND_AUTH: + mailimap_resp_cond_auth_free(greeting->gr_data.gr_auth); + break; + case MAILIMAP_GREETING_RESP_COND_BYE: + mailimap_resp_cond_bye_free(greeting->gr_data.gr_bye); + break; + } + free(greeting); +} + + + +LIBETPAN_EXPORT +void +mailimap_header_fld_name_free(char * header_fld_name) +{ + mailimap_astring_free(header_fld_name); +} + + + +LIBETPAN_EXPORT +struct mailimap_header_list * +mailimap_header_list_new(clist * hdr_list) +{ + struct mailimap_header_list * header_list; + + header_list = malloc(sizeof(* header_list)); + if (header_list == NULL) + return NULL; + + header_list->hdr_list = hdr_list; + + return header_list; +} + +LIBETPAN_EXPORT +void +mailimap_header_list_free(struct mailimap_header_list * header_list) +{ + clist_foreach(header_list->hdr_list, + (clist_func) mailimap_header_fld_name_free, + NULL); + clist_free(header_list->hdr_list); + free(header_list); +} + + + +LIBETPAN_EXPORT +void mailimap_literal_free(char * literal) +{ + /* free(literal); */ + mmap_string_unref(literal); +} + +LIBETPAN_EXPORT +void mailimap_mailbox_free(char * mb) +{ + mailimap_astring_free(mb); +} + + + + +LIBETPAN_EXPORT +struct mailimap_status_info * +mailimap_status_info_new(int st_att, uint32_t st_value, + struct mailimap_extension_data * st_ext_data) +{ + struct mailimap_status_info * info; + + info = malloc(sizeof(* info)); + if (info == NULL) + return NULL; + info->st_att = st_att; + info->st_value = st_value; + info->st_ext_data = st_ext_data; + + return info; +} + +LIBETPAN_EXPORT +void mailimap_status_info_free(struct mailimap_status_info * info) +{ + if (info->st_ext_data != NULL) { + mailimap_extension_data_free(info->st_ext_data); + } + free(info); +} + + + +LIBETPAN_EXPORT +struct mailimap_mailbox_data_status * +mailimap_mailbox_data_status_new(char * st_mailbox, + clist * st_info_list) +{ + struct mailimap_mailbox_data_status * mb_data_status; + + mb_data_status = malloc(sizeof(* mb_data_status)); + if (mb_data_status == NULL) + return NULL; + mb_data_status->st_mailbox = st_mailbox; + mb_data_status->st_info_list = st_info_list; + + return mb_data_status; +} + +LIBETPAN_EXPORT +void +mailimap_mailbox_data_search_free(clist * data_search) +{ + clist_foreach(data_search, (clist_func) mailimap_number_alloc_free, NULL); + clist_free(data_search); +} + +LIBETPAN_EXPORT +void +mailimap_mailbox_data_status_free(struct mailimap_mailbox_data_status * info) +{ + mailimap_mailbox_free(info->st_mailbox); + clist_foreach(info->st_info_list, (clist_func) mailimap_status_info_free, + NULL); + clist_free(info->st_info_list); + free(info); +} + + +static void +mailimap_mailbox_data_flags_free(struct mailimap_flag_list * flag_list) +{ + mailimap_flag_list_free(flag_list); +} + +static void +mailimap_mailbox_data_list_free(struct mailimap_mailbox_list * mb_list) +{ + mailimap_mailbox_list_free(mb_list); +} + +static void +mailimap_mailbox_data_lsub_free(struct mailimap_mailbox_list * mb_lsub) +{ + mailimap_mailbox_list_free(mb_lsub); +} + + + + + + +LIBETPAN_EXPORT +struct mailimap_mailbox_data * +mailimap_mailbox_data_new(int mbd_type, struct mailimap_flag_list * mbd_flags, + struct mailimap_mailbox_list * mbd_list, + struct mailimap_mailbox_list * mbd_lsub, + clist * mbd_search, + struct mailimap_mailbox_data_status * mbd_status, + uint32_t mbd_exists, + uint32_t mbd_recent, + struct mailimap_extension_data * mbd_extension) +{ + struct mailimap_mailbox_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + return NULL; + + data->mbd_type = mbd_type; + switch (mbd_type) { + case MAILIMAP_MAILBOX_DATA_FLAGS: + data->mbd_data.mbd_flags = mbd_flags; + break; + case MAILIMAP_MAILBOX_DATA_LIST: + data->mbd_data.mbd_list = mbd_list; + break; + case MAILIMAP_MAILBOX_DATA_LSUB: + data->mbd_data.mbd_lsub = mbd_lsub; + break; + case MAILIMAP_MAILBOX_DATA_SEARCH: + data->mbd_data.mbd_search = mbd_search; + break; + case MAILIMAP_MAILBOX_DATA_STATUS: + data->mbd_data.mbd_status = mbd_status; + break; + case MAILIMAP_MAILBOX_DATA_EXISTS: + data->mbd_data.mbd_exists = mbd_exists; + break; + case MAILIMAP_MAILBOX_DATA_RECENT: + data->mbd_data.mbd_recent = mbd_recent; + break; + case MAILIMAP_MAILBOX_DATA_EXTENSION_DATA: + data->mbd_data.mbd_extension = mbd_extension; + break; + } + + return data; +} + +LIBETPAN_EXPORT +void +mailimap_mailbox_data_free(struct mailimap_mailbox_data * mb_data) +{ + switch (mb_data->mbd_type) { + case MAILIMAP_MAILBOX_DATA_FLAGS: + if (mb_data->mbd_data.mbd_flags != NULL) + mailimap_mailbox_data_flags_free(mb_data->mbd_data.mbd_flags); + break; + case MAILIMAP_MAILBOX_DATA_LIST: + if (mb_data->mbd_data.mbd_list != NULL) + mailimap_mailbox_data_list_free(mb_data->mbd_data.mbd_list); + break; + case MAILIMAP_MAILBOX_DATA_LSUB: + if (mb_data->mbd_data.mbd_lsub != NULL) + mailimap_mailbox_data_lsub_free(mb_data->mbd_data.mbd_lsub); + break; + case MAILIMAP_MAILBOX_DATA_SEARCH: + if (mb_data->mbd_data.mbd_search != NULL) + mailimap_mailbox_data_search_free(mb_data->mbd_data.mbd_search); + break; + case MAILIMAP_MAILBOX_DATA_STATUS: + if (mb_data->mbd_data.mbd_status != NULL) + mailimap_mailbox_data_status_free(mb_data->mbd_data.mbd_status); + break; + case MAILIMAP_MAILBOX_DATA_EXTENSION_DATA: + if (mb_data->mbd_data.mbd_extension != NULL) + mailimap_extension_data_free(mb_data->mbd_data.mbd_extension); + break; + } + free(mb_data); +} + + + + + +LIBETPAN_EXPORT +struct mailimap_mbx_list_flags * +mailimap_mbx_list_flags_new(int mbf_type, clist * mbf_oflags, + int mbf_sflag) +{ + struct mailimap_mbx_list_flags * mbx_list_flags; + + mbx_list_flags = malloc(sizeof(* mbx_list_flags)); + if (mbx_list_flags == NULL) + return NULL; + + mbx_list_flags->mbf_type = mbf_type; + mbx_list_flags->mbf_oflags = mbf_oflags; + mbx_list_flags->mbf_sflag = mbf_sflag; + + return mbx_list_flags; +} + +LIBETPAN_EXPORT +void +mailimap_mbx_list_flags_free(struct mailimap_mbx_list_flags * mbx_list_flags) +{ + clist_foreach(mbx_list_flags->mbf_oflags, + (clist_func) mailimap_mbx_list_oflag_free, + NULL); + clist_free(mbx_list_flags->mbf_oflags); + + free(mbx_list_flags); +} + + +LIBETPAN_EXPORT +struct mailimap_mbx_list_oflag * +mailimap_mbx_list_oflag_new(int of_type, char * of_flag_ext) +{ + struct mailimap_mbx_list_oflag * oflag; + + oflag = malloc(sizeof(* oflag)); + if (oflag == NULL) + return NULL; + + oflag->of_type = of_type; + oflag->of_flag_ext = of_flag_ext; + + return oflag; +} + +LIBETPAN_EXPORT +void +mailimap_mbx_list_oflag_free(struct mailimap_mbx_list_oflag * oflag) +{ + if (oflag->of_flag_ext != NULL) + mailimap_flag_extension_free(oflag->of_flag_ext); + free(oflag); +} + + + +LIBETPAN_EXPORT +struct mailimap_mailbox_list * +mailimap_mailbox_list_new(struct mailimap_mbx_list_flags * mbx_flags, + char mb_delimiter, char * mb_name) +{ + struct mailimap_mailbox_list * mb_list; + + mb_list = malloc(sizeof(* mb_list)); + if (mb_list == NULL) + return NULL; + + mb_list->mb_flag = mbx_flags; + mb_list->mb_delimiter = mb_delimiter; + mb_list->mb_name = mb_name; + + return mb_list; +} + +LIBETPAN_EXPORT +void +mailimap_mailbox_list_free(struct mailimap_mailbox_list * mb_list) +{ + if (mb_list->mb_flag != NULL) + mailimap_mbx_list_flags_free(mb_list->mb_flag); + if (mb_list->mb_name != NULL) + mailimap_mailbox_free(mb_list->mb_name); + free(mb_list); +} + + + +LIBETPAN_EXPORT +struct mailimap_media_basic * +mailimap_media_basic_new(int med_type, + char * med_basic_type, char * med_subtype) +{ + struct mailimap_media_basic * media_basic; + + media_basic = malloc(sizeof(* media_basic)); + if (media_basic == NULL) + return NULL; + media_basic->med_type = med_type; + media_basic->med_basic_type = med_basic_type; + media_basic->med_subtype = med_subtype; + + return media_basic; +} + +LIBETPAN_EXPORT +void +mailimap_media_basic_free(struct mailimap_media_basic * media_basic) +{ + mailimap_string_free(media_basic->med_basic_type); + mailimap_media_subtype_free(media_basic->med_subtype); + free(media_basic); +} + + + +LIBETPAN_EXPORT +void mailimap_media_subtype_free(char * media_subtype) +{ + mmap_string_unref(media_subtype); +} + + +LIBETPAN_EXPORT +void mailimap_media_text_free(char * media_text) +{ + mailimap_media_subtype_free(media_text); +} + + + +LIBETPAN_EXPORT +struct mailimap_message_data * +mailimap_message_data_new(uint32_t mdt_number, int mdt_type, + struct mailimap_msg_att * mdt_msg_att) +{ + struct mailimap_message_data * msg_data; + + msg_data = malloc(sizeof(* msg_data)); + if (msg_data == NULL) { + return NULL; + } + + msg_data->mdt_number = mdt_number; + msg_data->mdt_type = mdt_type; + msg_data->mdt_msg_att = mdt_msg_att; + + return msg_data; +} + +LIBETPAN_EXPORT +void +mailimap_message_data_free(struct mailimap_message_data * msg_data) +{ + if (msg_data->mdt_msg_att != NULL) + mailimap_msg_att_free(msg_data->mdt_msg_att); + free(msg_data); +} + + + + +LIBETPAN_EXPORT +struct mailimap_msg_att_item * +mailimap_msg_att_item_new(int att_type, + struct mailimap_msg_att_dynamic * att_dyn, + struct mailimap_msg_att_static * att_static, + struct mailimap_extension_data * att_extension_data) +{ + struct mailimap_msg_att_item * item; + + item = malloc(sizeof(* item)); + if (item == NULL) + return item; + + item->att_type = att_type; + switch (att_type) { + case MAILIMAP_MSG_ATT_ITEM_DYNAMIC: + item->att_data.att_dyn = att_dyn; + break; + case MAILIMAP_MSG_ATT_ITEM_STATIC: + item->att_data.att_static = att_static; + break; + case MAILIMAP_MSG_ATT_ITEM_EXTENSION: + item->att_data.att_extension_data = att_extension_data; + break; + } + + return item; +} + +LIBETPAN_EXPORT +void +mailimap_msg_att_item_free(struct mailimap_msg_att_item * item) +{ + switch (item->att_type) { + case MAILIMAP_MSG_ATT_ITEM_DYNAMIC: + mailimap_msg_att_dynamic_free(item->att_data.att_dyn); + break; + case MAILIMAP_MSG_ATT_ITEM_STATIC: + mailimap_msg_att_static_free(item->att_data.att_static); + break; + case MAILIMAP_MSG_ATT_ITEM_EXTENSION: + mailimap_extension_data_free(item->att_data.att_extension_data); + break; + } + free(item); +} + + +LIBETPAN_EXPORT +struct mailimap_msg_att * +mailimap_msg_att_new(clist * att_list) +{ + struct mailimap_msg_att * msg_att; + + msg_att = malloc(sizeof(* msg_att)); + if (msg_att == NULL) + return NULL; + + msg_att->att_list = att_list; + msg_att->att_number = 0; + + return msg_att; +} + +LIBETPAN_EXPORT +void mailimap_msg_att_free(struct mailimap_msg_att * msg_att) +{ + clist_foreach(msg_att->att_list, + (clist_func) mailimap_msg_att_item_free, NULL); + clist_free(msg_att->att_list); + free(msg_att); +} + + + +LIBETPAN_EXPORT +struct mailimap_msg_att_dynamic * +mailimap_msg_att_dynamic_new(clist * att_list) +{ + struct mailimap_msg_att_dynamic * msg_att_dyn; + + msg_att_dyn = malloc(sizeof(* msg_att_dyn)); + if (msg_att_dyn == NULL) + return NULL; + + msg_att_dyn->att_list = att_list; + + return msg_att_dyn; +} + +LIBETPAN_EXPORT +void +mailimap_msg_att_dynamic_free(struct mailimap_msg_att_dynamic * msg_att_dyn) +{ + if (msg_att_dyn->att_list != NULL) { + clist_foreach(msg_att_dyn->att_list, + (clist_func) mailimap_flag_fetch_free, + NULL); + clist_free(msg_att_dyn->att_list); + } + free(msg_att_dyn); +} + + +LIBETPAN_EXPORT +struct mailimap_msg_att_body_section * +mailimap_msg_att_body_section_new(struct mailimap_section * sec_section, + uint32_t sec_origin_octet, + char * sec_body_part, + size_t sec_length) +{ + struct mailimap_msg_att_body_section * msg_att_body_section; + + msg_att_body_section = malloc(sizeof(* msg_att_body_section)); + if (msg_att_body_section == NULL) + return NULL; + + msg_att_body_section->sec_section = sec_section; + msg_att_body_section->sec_origin_octet = sec_origin_octet; + msg_att_body_section->sec_body_part = sec_body_part; + msg_att_body_section->sec_length = sec_length; + + return msg_att_body_section; +} + +LIBETPAN_EXPORT +void +mailimap_msg_att_body_section_free(struct mailimap_msg_att_body_section * + msg_att_body_section) +{ + if (msg_att_body_section->sec_section != NULL) + mailimap_section_free(msg_att_body_section->sec_section); + if (msg_att_body_section->sec_body_part != NULL) + mailimap_nstring_free(msg_att_body_section->sec_body_part); + free(msg_att_body_section); +} + + + + + + +LIBETPAN_EXPORT +void mailimap_msg_att_envelope_free(struct mailimap_envelope * env) +{ + mailimap_envelope_free(env); +} + +LIBETPAN_EXPORT +void +mailimap_msg_att_internaldate_free(struct mailimap_date_time * date_time) +{ + mailimap_date_time_free(date_time); +} + +LIBETPAN_EXPORT +void +mailimap_msg_att_rfc822_free(char * str) +{ + mailimap_nstring_free(str); +} + + +LIBETPAN_EXPORT +void +mailimap_msg_att_rfc822_header_free(char * str) +{ + mailimap_nstring_free(str); +} + +LIBETPAN_EXPORT +void +mailimap_msg_att_rfc822_text_free(char * str) +{ + mailimap_nstring_free(str); +} + +LIBETPAN_EXPORT +void +mailimap_msg_att_body_free(struct mailimap_body * body) +{ + mailimap_body_free(body); +} + +LIBETPAN_EXPORT +void +mailimap_msg_att_bodystructure_free(struct mailimap_body * body) +{ + mailimap_body_free(body); +} + + + +LIBETPAN_EXPORT +struct mailimap_msg_att_static * +mailimap_msg_att_static_new(int att_type, struct mailimap_envelope * att_env, + struct mailimap_date_time * att_internal_date, + char * att_rfc822, + char * att_rfc822_header, + char * att_rfc822_text, + size_t att_length, + uint32_t att_rfc822_size, + struct mailimap_body * att_bodystructure, + struct mailimap_body * att_body, + struct mailimap_msg_att_body_section * att_body_section, + uint32_t att_uid) +{ + struct mailimap_msg_att_static * item; + + item = malloc(sizeof(* item)); + if (item == NULL) + return FALSE; + + item->att_type = att_type; + switch (att_type) { + case MAILIMAP_MSG_ATT_ENVELOPE: + item->att_data.att_env = att_env; + break; + case MAILIMAP_MSG_ATT_INTERNALDATE: + item->att_data.att_internal_date = att_internal_date; + break; + case MAILIMAP_MSG_ATT_RFC822: + item->att_data.att_rfc822.att_content = att_rfc822; + item->att_data.att_rfc822.att_length = att_length; + break; + case MAILIMAP_MSG_ATT_RFC822_HEADER: + item->att_data.att_rfc822_header.att_content = att_rfc822_header; + item->att_data.att_rfc822_header.att_length = att_length; + break; + case MAILIMAP_MSG_ATT_RFC822_TEXT: + item->att_data.att_rfc822_text.att_content = att_rfc822_text; + item->att_data.att_rfc822_text.att_length = att_length; + break; + case MAILIMAP_MSG_ATT_RFC822_SIZE: + item->att_data.att_rfc822_size = att_rfc822_size; + break; + case MAILIMAP_MSG_ATT_BODY: + item->att_data.att_body = att_body; + break; + case MAILIMAP_MSG_ATT_BODYSTRUCTURE: + item->att_data.att_bodystructure = att_bodystructure; + break; + case MAILIMAP_MSG_ATT_BODY_SECTION: + item->att_data.att_body_section = att_body_section; + break; + case MAILIMAP_MSG_ATT_UID: + item->att_data.att_uid = att_uid; + break; + } + + return item; +} + +LIBETPAN_EXPORT +void +mailimap_msg_att_static_free(struct mailimap_msg_att_static * item) +{ + switch (item->att_type) { + case MAILIMAP_MSG_ATT_ENVELOPE: + if (item->att_data.att_env != NULL) + mailimap_msg_att_envelope_free(item->att_data.att_env); + break; + case MAILIMAP_MSG_ATT_INTERNALDATE: + if (item->att_data.att_internal_date != NULL) + mailimap_msg_att_internaldate_free(item->att_data.att_internal_date); + break; + case MAILIMAP_MSG_ATT_RFC822: + if (item->att_data.att_rfc822.att_content != NULL) + mailimap_msg_att_rfc822_free(item->att_data.att_rfc822.att_content); + break; + case MAILIMAP_MSG_ATT_RFC822_HEADER: + if (item->att_data.att_rfc822_header.att_content != NULL) + mailimap_msg_att_rfc822_header_free(item->att_data.att_rfc822_header.att_content); + break; + case MAILIMAP_MSG_ATT_RFC822_TEXT: + if (item->att_data.att_rfc822_text.att_content != NULL) + mailimap_msg_att_rfc822_text_free(item->att_data.att_rfc822_text.att_content); + break; + case MAILIMAP_MSG_ATT_BODYSTRUCTURE: + if (item->att_data.att_bodystructure != NULL) + mailimap_msg_att_bodystructure_free(item->att_data.att_bodystructure); + break; + case MAILIMAP_MSG_ATT_BODY: + if (item->att_data.att_body != NULL) + mailimap_msg_att_body_free(item->att_data.att_body); + break; + case MAILIMAP_MSG_ATT_BODY_SECTION: + if (item->att_data.att_body_section != NULL) + mailimap_msg_att_body_section_free(item->att_data.att_body_section); + break; + } + free(item); +} + + + + +LIBETPAN_EXPORT +void mailimap_nstring_free(char * str) +{ + if (str != NULL) + mailimap_string_free(str); +} + + + + + + + +LIBETPAN_EXPORT +struct mailimap_cont_req_or_resp_data * +mailimap_cont_req_or_resp_data_new(int rsp_type, + struct mailimap_continue_req * rsp_cont_req, + struct mailimap_response_data * rsp_resp_data) +{ + struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data; + + cont_req_or_resp_data = malloc(sizeof(* cont_req_or_resp_data)); + if (cont_req_or_resp_data == NULL) + return NULL; + + cont_req_or_resp_data->rsp_type = rsp_type; + switch (rsp_type) { + case MAILIMAP_RESP_CONT_REQ: + cont_req_or_resp_data->rsp_data.rsp_cont_req = rsp_cont_req; + break; + case MAILIMAP_RESP_RESP_DATA: + cont_req_or_resp_data->rsp_data.rsp_resp_data = rsp_resp_data; + break; + } + + return cont_req_or_resp_data; +} + +LIBETPAN_EXPORT +void +mailimap_cont_req_or_resp_data_free(struct mailimap_cont_req_or_resp_data * + cont_req_or_resp_data) +{ + switch (cont_req_or_resp_data->rsp_type) { + case MAILIMAP_RESP_CONT_REQ: + if (cont_req_or_resp_data->rsp_data.rsp_cont_req != NULL) + mailimap_continue_req_free(cont_req_or_resp_data->rsp_data.rsp_cont_req); + break; + case MAILIMAP_RESP_RESP_DATA: + if (cont_req_or_resp_data->rsp_data.rsp_resp_data != NULL) + mailimap_response_data_free(cont_req_or_resp_data->rsp_data.rsp_resp_data); + break; + } + free(cont_req_or_resp_data); +} + + + + +LIBETPAN_EXPORT +struct mailimap_response * +mailimap_response_new(clist * rsp_cont_req_or_resp_data_list, + struct mailimap_response_done * rsp_resp_done) +{ + struct mailimap_response * resp; + + resp = malloc(sizeof(* resp)); + if (resp == NULL) + return NULL; + + resp->rsp_cont_req_or_resp_data_list = rsp_cont_req_or_resp_data_list; + resp->rsp_resp_done = rsp_resp_done; + + return resp; +} + +LIBETPAN_EXPORT +void +mailimap_response_free(struct mailimap_response * resp) +{ + if (resp->rsp_cont_req_or_resp_data_list != NULL) { + clist_foreach(resp->rsp_cont_req_or_resp_data_list, + (clist_func) mailimap_cont_req_or_resp_data_free, NULL); + clist_free(resp->rsp_cont_req_or_resp_data_list); + } + mailimap_response_done_free(resp->rsp_resp_done); + free(resp); +} + + + +LIBETPAN_EXPORT +struct mailimap_response_data * +mailimap_response_data_new(int rsp_type, + struct mailimap_resp_cond_state * rsp_cond_state, + struct mailimap_resp_cond_bye * rsp_bye, + struct mailimap_mailbox_data * rsp_mailbox_data, + struct mailimap_message_data * rsp_message_data, + struct mailimap_capability_data * rsp_capability_data, + struct mailimap_extension_data * rsp_extension_data) +{ + struct mailimap_response_data * resp_data; + + resp_data = malloc(sizeof(* resp_data)); + if (resp_data == NULL) + return NULL; + resp_data->rsp_type = rsp_type; + + switch (rsp_type) { + case MAILIMAP_RESP_DATA_TYPE_COND_STATE: + resp_data->rsp_data.rsp_cond_state = rsp_cond_state; + break; + case MAILIMAP_RESP_DATA_TYPE_COND_BYE: + resp_data->rsp_data.rsp_bye = rsp_bye; + break; + case MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA: + resp_data->rsp_data.rsp_mailbox_data = rsp_mailbox_data; + break; + case MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA: + resp_data->rsp_data.rsp_message_data = rsp_message_data; + break; + case MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA: + resp_data->rsp_data.rsp_capability_data = rsp_capability_data; + break; + case MAILIMAP_RESP_DATA_TYPE_EXTENSION_DATA: + resp_data->rsp_data.rsp_extension_data = rsp_extension_data; + break; + } + + return resp_data; +} + +LIBETPAN_EXPORT +void +mailimap_response_data_free(struct mailimap_response_data * resp_data) +{ + switch (resp_data->rsp_type) { + case MAILIMAP_RESP_DATA_TYPE_COND_STATE: + if (resp_data->rsp_data.rsp_cond_state != NULL) + mailimap_resp_cond_state_free(resp_data->rsp_data.rsp_cond_state); + break; + case MAILIMAP_RESP_DATA_TYPE_COND_BYE: + if (resp_data->rsp_data.rsp_bye != NULL) + mailimap_resp_cond_bye_free(resp_data->rsp_data.rsp_bye); + break; + case MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA: + if (resp_data->rsp_data.rsp_mailbox_data != NULL) + mailimap_mailbox_data_free(resp_data->rsp_data.rsp_mailbox_data); + break; + case MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA: + if (resp_data->rsp_data.rsp_message_data != NULL) + mailimap_message_data_free(resp_data->rsp_data.rsp_message_data); + break; + case MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA: + if (resp_data->rsp_data.rsp_capability_data != NULL) + mailimap_capability_data_free(resp_data->rsp_data.rsp_capability_data); + break; + case MAILIMAP_RESP_DATA_TYPE_EXTENSION_DATA: + if (resp_data->rsp_data.rsp_extension_data != NULL) + mailimap_extension_data_free(resp_data->rsp_data.rsp_extension_data); + break; + } + free(resp_data); +} + + + +LIBETPAN_EXPORT +struct mailimap_response_done * +mailimap_response_done_new(int rsp_type, + struct mailimap_response_tagged * rsp_tagged, + struct mailimap_response_fatal * rsp_fatal) +{ + struct mailimap_response_done * resp_done; + + resp_done = malloc(sizeof(* resp_done)); + if (resp_done == NULL) + return NULL; + + resp_done->rsp_type = rsp_type; + switch (rsp_type) { + case MAILIMAP_RESP_DONE_TYPE_TAGGED: + resp_done->rsp_data.rsp_tagged = rsp_tagged; + break; + case MAILIMAP_RESP_DONE_TYPE_FATAL: + resp_done->rsp_data.rsp_fatal = rsp_fatal; + break; + } + + return resp_done; +} + +LIBETPAN_EXPORT +void mailimap_response_done_free(struct mailimap_response_done * + resp_done) +{ + switch (resp_done->rsp_type) { + case MAILIMAP_RESP_DONE_TYPE_TAGGED: + mailimap_response_tagged_free(resp_done->rsp_data.rsp_tagged); + break; + case MAILIMAP_RESP_DONE_TYPE_FATAL: + mailimap_response_fatal_free(resp_done->rsp_data.rsp_fatal); + break; + } + free(resp_done); +} + +LIBETPAN_EXPORT +struct mailimap_response_fatal * +mailimap_response_fatal_new(struct mailimap_resp_cond_bye * rsp_bye) +{ + struct mailimap_response_fatal * resp_fatal; + + resp_fatal = malloc(sizeof(* resp_fatal)); + if (resp_fatal == NULL) + return NULL; + + resp_fatal->rsp_bye = rsp_bye; + + return resp_fatal; +} + +LIBETPAN_EXPORT +void mailimap_response_fatal_free(struct mailimap_response_fatal * resp_fatal) +{ + mailimap_resp_cond_bye_free(resp_fatal->rsp_bye); + free(resp_fatal); +} + +LIBETPAN_EXPORT +struct mailimap_response_tagged * +mailimap_response_tagged_new(char * rsp_tag, + struct mailimap_resp_cond_state * rsp_cond_state) +{ + struct mailimap_response_tagged * resp_tagged; + + resp_tagged = malloc(sizeof(* resp_tagged)); + if (resp_tagged == NULL) + return NULL; + + resp_tagged->rsp_tag = rsp_tag; + resp_tagged->rsp_cond_state = rsp_cond_state; + + return resp_tagged; +} + +LIBETPAN_EXPORT +void +mailimap_response_tagged_free(struct mailimap_response_tagged * tagged) +{ + mailimap_tag_free(tagged->rsp_tag); + mailimap_resp_cond_state_free(tagged->rsp_cond_state); + free(tagged); +} + + + +LIBETPAN_EXPORT +struct mailimap_resp_cond_auth * +mailimap_resp_cond_auth_new(int rsp_type, + struct mailimap_resp_text * rsp_text) +{ + struct mailimap_resp_cond_auth * cond_auth; + + cond_auth = malloc(sizeof(* cond_auth)); + if (cond_auth == NULL) + return NULL; + + cond_auth->rsp_type = rsp_type; + cond_auth->rsp_text = rsp_text; + + return cond_auth; +} + +LIBETPAN_EXPORT +void +mailimap_resp_cond_auth_free(struct mailimap_resp_cond_auth * cond_auth) +{ + mailimap_resp_text_free(cond_auth->rsp_text); + free(cond_auth); +} + + + +LIBETPAN_EXPORT +struct mailimap_resp_cond_bye * +mailimap_resp_cond_bye_new(struct mailimap_resp_text * rsp_text) +{ + struct mailimap_resp_cond_bye * cond_bye; + + cond_bye = malloc(sizeof(* cond_bye)); + if (cond_bye == NULL) + return NULL; + + cond_bye->rsp_text = rsp_text; + + return cond_bye; +} + + +LIBETPAN_EXPORT +void +mailimap_resp_cond_bye_free(struct mailimap_resp_cond_bye * cond_bye) +{ + mailimap_resp_text_free(cond_bye->rsp_text); + free(cond_bye); +} + + +LIBETPAN_EXPORT +struct mailimap_resp_cond_state * +mailimap_resp_cond_state_new(int rsp_type, + struct mailimap_resp_text * rsp_text) +{ + struct mailimap_resp_cond_state * cond_state; + + cond_state = malloc(sizeof(* cond_state)); + if (cond_state == NULL) + return NULL; + + cond_state->rsp_type = rsp_type; + cond_state->rsp_text = rsp_text; + + return cond_state; +} + +LIBETPAN_EXPORT +void +mailimap_resp_cond_state_free(struct mailimap_resp_cond_state * cond_state) +{ + mailimap_resp_text_free(cond_state->rsp_text); + free(cond_state); +} + + +LIBETPAN_EXPORT +struct mailimap_resp_text * +mailimap_resp_text_new(struct mailimap_resp_text_code * rsp_code, + char * rsp_text) +{ + struct mailimap_resp_text * resp_text; + + resp_text = malloc(sizeof(* resp_text)); + if (resp_text == NULL) + return NULL; + + resp_text->rsp_code = rsp_code; + resp_text->rsp_text = rsp_text; + + return resp_text; +} + +LIBETPAN_EXPORT +void mailimap_resp_text_free(struct mailimap_resp_text * resp_text) +{ + if (resp_text->rsp_code) + mailimap_resp_text_code_free(resp_text->rsp_code); + if (resp_text->rsp_text) + mailimap_text_free(resp_text->rsp_text); + free(resp_text); +} + + + + +LIBETPAN_EXPORT +struct mailimap_resp_text_code * +mailimap_resp_text_code_new(int rc_type, clist * rc_badcharset, + struct mailimap_capability_data * rc_cap_data, + clist * rc_perm_flags, + uint32_t rc_uidnext, uint32_t rc_uidvalidity, + uint32_t rc_first_unseen, char * rc_atom, char * rc_atom_value, + struct mailimap_extension_data * rc_ext_data) +{ + struct mailimap_resp_text_code * resp_text_code; + + resp_text_code = malloc(sizeof(* resp_text_code)); + if (resp_text_code == NULL) + return NULL; + + resp_text_code->rc_type = rc_type; + switch (rc_type) { + case MAILIMAP_RESP_TEXT_CODE_BADCHARSET: + resp_text_code->rc_data.rc_badcharset = rc_badcharset; + break; + case MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA: + resp_text_code->rc_data.rc_cap_data = rc_cap_data; + break; + case MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS: + resp_text_code->rc_data.rc_perm_flags = rc_perm_flags; + break; + case MAILIMAP_RESP_TEXT_CODE_UIDNEXT: + resp_text_code->rc_data.rc_uidnext = rc_uidnext; + break; + case MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY: + resp_text_code->rc_data.rc_uidvalidity = rc_uidvalidity; + break; + case MAILIMAP_RESP_TEXT_CODE_UNSEEN: + resp_text_code->rc_data.rc_first_unseen = rc_first_unseen; + break; + case MAILIMAP_RESP_TEXT_CODE_OTHER: + resp_text_code->rc_data.rc_atom.atom_name = rc_atom; + resp_text_code->rc_data.rc_atom.atom_value = rc_atom_value; + break; + case MAILIMAP_RESP_TEXT_CODE_EXTENSION: + resp_text_code->rc_data.rc_ext_data = rc_ext_data; + break; + } + + return resp_text_code; +} + +LIBETPAN_EXPORT +void +mailimap_resp_text_code_free(struct mailimap_resp_text_code * resp_text_code) +{ + switch (resp_text_code->rc_type) { + case MAILIMAP_RESP_TEXT_CODE_BADCHARSET: + if (resp_text_code->rc_data.rc_badcharset != NULL) { + clist_foreach(resp_text_code->rc_data.rc_badcharset, + (clist_func) mailimap_astring_free, + NULL); + clist_free(resp_text_code->rc_data.rc_badcharset); + } + break; + case MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA: + if (resp_text_code->rc_data.rc_cap_data != NULL) + mailimap_capability_data_free(resp_text_code->rc_data.rc_cap_data); + break; + case MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS: + if (resp_text_code->rc_data.rc_perm_flags != NULL) { + clist_foreach(resp_text_code->rc_data.rc_perm_flags, + (clist_func) mailimap_flag_perm_free, NULL); + clist_free(resp_text_code->rc_data.rc_perm_flags); + } + break; + case MAILIMAP_RESP_TEXT_CODE_OTHER: + if (resp_text_code->rc_data.rc_atom.atom_name != NULL) + mailimap_atom_free(resp_text_code->rc_data.rc_atom.atom_name); + if (resp_text_code->rc_data.rc_atom.atom_value != NULL) + mailimap_custom_string_free(resp_text_code->rc_data.rc_atom.atom_value); + break; + case MAILIMAP_RESP_TEXT_CODE_EXTENSION: + if (resp_text_code->rc_data.rc_ext_data != NULL) + mailimap_extension_data_free(resp_text_code->rc_data.rc_ext_data); + break; + } + free(resp_text_code); +} + + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new(struct mailimap_section_spec * sec_spec) +{ + struct mailimap_section * section; + + section = malloc(sizeof(* section)); + if (section == NULL) + return NULL; + + section->sec_spec = sec_spec; + + return section; +} + +LIBETPAN_EXPORT +void mailimap_section_free(struct mailimap_section * section) +{ + if (section->sec_spec != NULL) + mailimap_section_spec_free(section->sec_spec); + free(section); +} + + + +LIBETPAN_EXPORT +struct mailimap_section_msgtext * +mailimap_section_msgtext_new(int sec_type, + struct mailimap_header_list * sec_header_list) +{ + struct mailimap_section_msgtext * msgtext; + + msgtext = malloc(sizeof(* msgtext)); + if (msgtext == NULL) + return FALSE; + + msgtext->sec_type = sec_type; + msgtext->sec_header_list = sec_header_list; + + return msgtext; +} + +LIBETPAN_EXPORT +void +mailimap_section_msgtext_free(struct mailimap_section_msgtext * msgtext) +{ + if (msgtext->sec_header_list != NULL) + mailimap_header_list_free(msgtext->sec_header_list); + free(msgtext); +} + + +LIBETPAN_EXPORT +struct mailimap_section_part * +mailimap_section_part_new(clist * sec_id) +{ + struct mailimap_section_part * section_part; + + section_part = malloc(sizeof(* section_part)); + if (section_part == NULL) + return NULL; + + section_part->sec_id = sec_id; + + return section_part; +} + +LIBETPAN_EXPORT +void +mailimap_section_part_free(struct mailimap_section_part * section_part) +{ + clist_foreach(section_part->sec_id, + (clist_func) mailimap_number_alloc_free, NULL); + clist_free(section_part->sec_id); + free(section_part); +} + + +LIBETPAN_EXPORT +struct mailimap_section_spec * +mailimap_section_spec_new(int sec_type, + struct mailimap_section_msgtext * sec_msgtext, + struct mailimap_section_part * sec_part, + struct mailimap_section_text * sec_text) +{ + struct mailimap_section_spec * section_spec; + + section_spec = malloc(sizeof(* section_spec)); + if (section_spec == NULL) + return NULL; + + section_spec->sec_type = sec_type; + switch (sec_type) { + case MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT: + section_spec->sec_data.sec_msgtext = sec_msgtext; + break; + case MAILIMAP_SECTION_SPEC_SECTION_PART: + section_spec->sec_data.sec_part = sec_part; + break; + } + section_spec->sec_text = sec_text; + + return section_spec; +} + +LIBETPAN_EXPORT +void +mailimap_section_spec_free(struct mailimap_section_spec * section_spec) +{ + if (section_spec->sec_text) + mailimap_section_text_free(section_spec->sec_text); + + switch (section_spec->sec_type) { + case MAILIMAP_SECTION_SPEC_SECTION_PART: + if (section_spec->sec_data.sec_part != NULL) + mailimap_section_part_free(section_spec->sec_data.sec_part); + break; + case MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT: + /* handle case where it can be detached */ + if (section_spec->sec_data.sec_msgtext != NULL) + mailimap_section_msgtext_free(section_spec->sec_data.sec_msgtext); + break; + } + free(section_spec); +} + + +LIBETPAN_EXPORT +struct mailimap_section_text * +mailimap_section_text_new(int sec_type, + struct mailimap_section_msgtext * sec_msgtext) +{ + struct mailimap_section_text * section_text; + + section_text = malloc(sizeof(* section_text)); + if (section_text == NULL) + return NULL; + + section_text->sec_type = sec_type; + section_text->sec_msgtext = sec_msgtext; + + return section_text; +} + +LIBETPAN_EXPORT +void +mailimap_section_text_free(struct mailimap_section_text * section_text) +{ + if (section_text->sec_msgtext != NULL) + mailimap_section_msgtext_free(section_text->sec_msgtext); + free(section_text); +} + + + + +LIBETPAN_EXPORT +void +mailimap_string_free(char * str) +{ + mmap_string_unref(str); +} + + + + + +LIBETPAN_EXPORT +void mailimap_tag_free(char * tag) +{ + mailimap_custom_string_free(tag); +} + + +LIBETPAN_EXPORT +void mailimap_text_free(char * text) +{ + mailimap_custom_string_free(text); +} + + + + + + + + + + + + + + + + + + + + + + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + + + + + + +/* sender only */ + + +/* COPY FETCH SEARCH STORE */ +/* set */ + +LIBETPAN_EXPORT +struct mailimap_set_item * +mailimap_set_item_new(uint32_t set_first, uint32_t set_last) +{ + struct mailimap_set_item * item; + + item = malloc(sizeof(* item)); + if (item == NULL) + return NULL; + + item->set_first = set_first; + item->set_last = set_last; + + return item; +} + +LIBETPAN_EXPORT +void mailimap_set_item_free(struct mailimap_set_item * set_item) +{ + free(set_item); +} + +LIBETPAN_EXPORT +struct mailimap_set * mailimap_set_new(clist * set_list) +{ + struct mailimap_set * set; + + set = malloc(sizeof(* set)); + if (set == NULL) + return NULL; + + set->set_list = set_list; + + return set; +} + +LIBETPAN_EXPORT +void mailimap_set_free(struct mailimap_set * set) +{ + clist_foreach(set->set_list, (clist_func) mailimap_set_item_free, NULL); + clist_free(set->set_list); + free(set); +} + +/* SEARCH with date key */ +/* date */ + +LIBETPAN_EXPORT +struct mailimap_date * +mailimap_date_new(int dt_day, int dt_month, int dt_year) +{ + struct mailimap_date * date; + + date = malloc(sizeof(* date)); + if (date == NULL) + return NULL; + + date->dt_day = dt_day; + date->dt_month = dt_month; + date->dt_year = dt_year; + + return date; +} + +LIBETPAN_EXPORT +void mailimap_date_free(struct mailimap_date * date) +{ + free(date); +} + + + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new(int att_type, struct mailimap_section * att_section, + uint32_t att_offset, uint32_t att_size, char * att_extension) +{ + struct mailimap_fetch_att * fetch_att; + + fetch_att = malloc(sizeof(* fetch_att)); + if (fetch_att == NULL) + return NULL; + fetch_att->att_type = att_type; + fetch_att->att_section = att_section; + fetch_att->att_offset = att_offset; + fetch_att->att_size = att_size; + fetch_att->att_extension = att_extension; + + return fetch_att; +} + +LIBETPAN_EXPORT +void mailimap_fetch_att_free(struct mailimap_fetch_att * fetch_att) +{ + if (fetch_att->att_extension != NULL) + free(fetch_att->att_extension); + if (fetch_att->att_section != NULL) + mailimap_section_free(fetch_att->att_section); + free(fetch_att); +} + + + +LIBETPAN_EXPORT +struct mailimap_fetch_type * +mailimap_fetch_type_new(int ft_type, + struct mailimap_fetch_att * ft_fetch_att, + clist * ft_fetch_att_list) +{ + struct mailimap_fetch_type * fetch_type; + + fetch_type = malloc(sizeof(* fetch_type)); + if (fetch_type == NULL) + return NULL; + fetch_type->ft_type = ft_type; + switch (ft_type) { + case MAILIMAP_FETCH_TYPE_FETCH_ATT: + fetch_type->ft_data.ft_fetch_att = ft_fetch_att; + break; + case MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST: + fetch_type->ft_data.ft_fetch_att_list = ft_fetch_att_list; + break; + } + + return fetch_type; +} + +LIBETPAN_EXPORT +void mailimap_fetch_type_free(struct mailimap_fetch_type * fetch_type) +{ + switch (fetch_type->ft_type) { + case MAILIMAP_FETCH_TYPE_FETCH_ATT: + mailimap_fetch_att_free(fetch_type->ft_data.ft_fetch_att); + break; + case MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST: + clist_foreach(fetch_type->ft_data.ft_fetch_att_list, + (clist_func) mailimap_fetch_att_free, NULL); + clist_free(fetch_type->ft_data.ft_fetch_att_list); + break; + } + free(fetch_type); +} + + + + +LIBETPAN_EXPORT +struct mailimap_store_att_flags * +mailimap_store_att_flags_new(int fl_sign, int fl_silent, + struct mailimap_flag_list * fl_flag_list) +{ + struct mailimap_store_att_flags * store_att_flags; + + store_att_flags = malloc(sizeof(* store_att_flags)); + if (store_att_flags == NULL) + return NULL; + + store_att_flags->fl_sign = fl_sign; + store_att_flags->fl_silent = fl_silent; + store_att_flags->fl_flag_list = fl_flag_list; + + return store_att_flags; +} + +LIBETPAN_EXPORT +void mailimap_store_att_flags_free(struct mailimap_store_att_flags * + store_att_flags) +{ + mailimap_flag_list_free(store_att_flags->fl_flag_list); + free(store_att_flags); +} + + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new(int sk_type, + char * sk_bcc, struct mailimap_date * sk_before, char * sk_body, + char * sk_cc, char * sk_from, char * sk_keyword, + struct mailimap_date * sk_on, struct mailimap_date * sk_since, + char * sk_subject, char * sk_text, char * sk_to, + char * sk_unkeyword, char * sk_header_name, + char * sk_header_value, uint32_t sk_larger, + struct mailimap_search_key * sk_not, + struct mailimap_search_key * sk_or1, + struct mailimap_search_key * sk_or2, + struct mailimap_date * sk_sentbefore, + struct mailimap_date * sk_senton, + struct mailimap_date * sk_sentsince, + uint32_t sk_smaller, struct mailimap_set * sk_uid, + struct mailimap_set * sk_set, clist * sk_multiple) +{ + struct mailimap_search_key * key; + + key = malloc(sizeof(* key)); + if (key == NULL) + return NULL; + + key->sk_type = sk_type; + switch (sk_type) { + case MAILIMAP_SEARCH_KEY_BCC: + key->sk_data.sk_bcc = sk_bcc; + break; + case MAILIMAP_SEARCH_KEY_BEFORE: + key->sk_data.sk_before = sk_before; + break; + case MAILIMAP_SEARCH_KEY_BODY: + key->sk_data.sk_body = sk_body; + break; + case MAILIMAP_SEARCH_KEY_CC: + key->sk_data.sk_cc = sk_cc; + break; + case MAILIMAP_SEARCH_KEY_FROM: + key->sk_data.sk_from = sk_from; + break; + case MAILIMAP_SEARCH_KEY_KEYWORD: + key->sk_data.sk_keyword = sk_keyword; + break; + case MAILIMAP_SEARCH_KEY_ON: + key->sk_data.sk_on = sk_on; + break; + case MAILIMAP_SEARCH_KEY_SINCE: + key->sk_data.sk_since = sk_since; + break; + case MAILIMAP_SEARCH_KEY_SUBJECT: + key->sk_data.sk_subject = sk_subject; + break; + case MAILIMAP_SEARCH_KEY_TEXT: + key->sk_data.sk_text = sk_text; + break; + case MAILIMAP_SEARCH_KEY_TO: + key->sk_data.sk_to = sk_to; + break; + case MAILIMAP_SEARCH_KEY_UNKEYWORD: + key->sk_data.sk_unkeyword = sk_unkeyword; + break; + case MAILIMAP_SEARCH_KEY_HEADER: + key->sk_data.sk_header.sk_header_name = sk_header_name; + key->sk_data.sk_header.sk_header_value = sk_header_value; + break; + case MAILIMAP_SEARCH_KEY_LARGER: + key->sk_data.sk_larger = sk_larger; + break; + case MAILIMAP_SEARCH_KEY_NOT: + key->sk_data.sk_not = sk_not; + break; + case MAILIMAP_SEARCH_KEY_OR: + key->sk_data.sk_or.sk_or1 = sk_or1; + key->sk_data.sk_or.sk_or2 = sk_or2; + break; + case MAILIMAP_SEARCH_KEY_SENTBEFORE: + key->sk_data.sk_sentbefore = sk_sentbefore; + break; + case MAILIMAP_SEARCH_KEY_SENTON: + key->sk_data.sk_senton = sk_senton; + break; + case MAILIMAP_SEARCH_KEY_SENTSINCE: + key->sk_data.sk_sentsince = sk_sentsince; + break; + case MAILIMAP_SEARCH_KEY_SMALLER: + key->sk_data.sk_smaller = sk_smaller; + break; + case MAILIMAP_SEARCH_KEY_UID: + key->sk_data.sk_uid = sk_uid; + break; + case MAILIMAP_SEARCH_KEY_SET: + key->sk_data.sk_set = sk_set; + break; + case MAILIMAP_SEARCH_KEY_MULTIPLE: + key->sk_data.sk_multiple = sk_multiple; + break; + } + return key; +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_xgmthrid(uint64_t sk_xgmthrid) +{ + struct mailimap_search_key * key; + + key = malloc(sizeof(* key)); + if (key == NULL) + return NULL; + + key->sk_type = MAILIMAP_SEARCH_KEY_XGMTHRID; + key->sk_data.sk_xgmthrid = sk_xgmthrid; + + return key; +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_xgmmsgid(uint64_t sk_xgmmsgid) +{ + struct mailimap_search_key * key; + + key = malloc(sizeof(* key)); + if (key == NULL) + return NULL; + + key->sk_type = MAILIMAP_SEARCH_KEY_XGMMSGID; + key->sk_data.sk_xgmmsgid = sk_xgmmsgid; + + return key; +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_xgmraw(char * sk_xgmraw) +{ + struct mailimap_search_key * key; + + key = malloc(sizeof(* key)); + if (key == NULL) + return NULL; + + key->sk_type = MAILIMAP_SEARCH_KEY_XGMRAW; + key->sk_data.sk_xgmraw = sk_xgmraw; + + return key; +} + +LIBETPAN_EXPORT +void mailimap_search_key_free(struct mailimap_search_key * key) +{ + switch (key->sk_type) { + case MAILIMAP_SEARCH_KEY_BCC: + mailimap_astring_free(key->sk_data.sk_bcc); + break; + case MAILIMAP_SEARCH_KEY_BEFORE: + mailimap_date_free(key->sk_data.sk_before); + break; + case MAILIMAP_SEARCH_KEY_BODY: + mailimap_astring_free(key->sk_data.sk_body); + break; + case MAILIMAP_SEARCH_KEY_CC: + mailimap_astring_free(key->sk_data.sk_cc); + break; + case MAILIMAP_SEARCH_KEY_FROM: + mailimap_astring_free(key->sk_data.sk_from); + break; + case MAILIMAP_SEARCH_KEY_KEYWORD: + mailimap_flag_keyword_free(key->sk_data.sk_keyword); + break; + case MAILIMAP_SEARCH_KEY_ON: + mailimap_date_free(key->sk_data.sk_on); + break; + case MAILIMAP_SEARCH_KEY_SINCE: + mailimap_date_free(key->sk_data.sk_since); + break; + case MAILIMAP_SEARCH_KEY_SUBJECT: + mailimap_astring_free(key->sk_data.sk_subject); + break; + case MAILIMAP_SEARCH_KEY_TEXT: + mailimap_astring_free(key->sk_data.sk_text); + break; + case MAILIMAP_SEARCH_KEY_TO: + mailimap_astring_free(key->sk_data.sk_to); + break; + case MAILIMAP_SEARCH_KEY_UNKEYWORD: + mailimap_flag_keyword_free(key->sk_data.sk_unkeyword); + break; + case MAILIMAP_SEARCH_KEY_HEADER: + mailimap_header_fld_name_free(key->sk_data.sk_header.sk_header_name); + mailimap_astring_free(key->sk_data.sk_header.sk_header_value); + break; + case MAILIMAP_SEARCH_KEY_NOT: + mailimap_search_key_free(key->sk_data.sk_not); + break; + case MAILIMAP_SEARCH_KEY_OR: + mailimap_search_key_free(key->sk_data.sk_or.sk_or1); + mailimap_search_key_free(key->sk_data.sk_or.sk_or2); + break; + case MAILIMAP_SEARCH_KEY_SENTBEFORE: + mailimap_date_free(key->sk_data.sk_sentbefore); + break; + case MAILIMAP_SEARCH_KEY_SENTON: + mailimap_date_free(key->sk_data.sk_senton); + break; + case MAILIMAP_SEARCH_KEY_SENTSINCE: + mailimap_date_free(key->sk_data.sk_sentsince); + break; + case MAILIMAP_SEARCH_KEY_UID: + mailimap_set_free(key->sk_data.sk_uid); + break; + case MAILIMAP_SEARCH_KEY_SET: + mailimap_set_free(key->sk_data.sk_set); + break; + case MAILIMAP_SEARCH_KEY_MULTIPLE: + clist_foreach(key->sk_data.sk_multiple, + (clist_func) mailimap_search_key_free, NULL); + clist_free(key->sk_data.sk_multiple); + break; + case MAILIMAP_SEARCH_KEY_MODSEQ: + if (key->sk_data.sk_modseq.sk_entry_name != NULL) { + mailimap_flag_free(key->sk_data.sk_modseq.sk_entry_name); + } + break; + case MAILIMAP_SEARCH_KEY_XGMRAW: + mailimap_astring_free(key->sk_data.sk_xgmraw); + break; + } + + free(key); +} + + + + + +LIBETPAN_EXPORT +struct mailimap_status_att_list * +mailimap_status_att_list_new(clist * att_list) +{ + struct mailimap_status_att_list * status_att_list; + + status_att_list = malloc(sizeof(* status_att_list)); + if (status_att_list == NULL) + return NULL; + status_att_list->att_list = att_list; + + return status_att_list; +} + +LIBETPAN_EXPORT +void mailimap_status_att_list_free(struct mailimap_status_att_list * + status_att_list) +{ + clist_foreach(status_att_list->att_list, (clist_func) free, NULL); + clist_free(status_att_list->att_list); + free(status_att_list); +} + + + + +/* main */ + + +LIBETPAN_EXPORT +struct mailimap_selection_info * +mailimap_selection_info_new(void) +{ + struct mailimap_selection_info * sel_info; + + sel_info = malloc(sizeof(* sel_info)); + if (sel_info == NULL) + return NULL; + + sel_info->sel_perm_flags = NULL; + sel_info->sel_perm = MAILIMAP_MAILBOX_READWRITE; + sel_info->sel_uidnext = 0; + sel_info->sel_uidvalidity = 0; + sel_info->sel_first_unseen = 0; + sel_info->sel_flags = NULL; + sel_info->sel_exists = 0; + sel_info->sel_recent = 0; + sel_info->sel_unseen = 0; + sel_info->sel_has_exists = 0; + sel_info->sel_has_recent = 0 ; + + return sel_info; +} + +LIBETPAN_EXPORT +void +mailimap_selection_info_free(struct mailimap_selection_info * sel_info) +{ + if (sel_info->sel_perm_flags != NULL) { + clist_foreach(sel_info->sel_perm_flags, + (clist_func) mailimap_flag_perm_free, NULL); + clist_free(sel_info->sel_perm_flags); + } + if (sel_info->sel_flags) + mailimap_flag_list_free(sel_info->sel_flags); + + free(sel_info); +} + +LIBETPAN_EXPORT +struct mailimap_connection_info * +mailimap_connection_info_new(void) +{ + struct mailimap_connection_info * conn_info; + + conn_info = malloc(sizeof(* conn_info)); + if (conn_info == NULL) + return NULL; + + conn_info->imap_capability = NULL; + + return conn_info; +} + +LIBETPAN_EXPORT +void +mailimap_connection_info_free(struct mailimap_connection_info * conn_info) +{ + if (conn_info->imap_capability != NULL) + mailimap_capability_data_free(conn_info->imap_capability); + free(conn_info); +} + +LIBETPAN_EXPORT +struct mailimap_response_info * +mailimap_response_info_new(void) +{ + struct mailimap_response_info * resp_info; + + resp_info = malloc(sizeof(* resp_info)); + if (resp_info == NULL) + goto err; + + resp_info->rsp_alert = NULL; + resp_info->rsp_parse = NULL; + resp_info->rsp_badcharset = NULL; + resp_info->rsp_trycreate = FALSE; + resp_info->rsp_mailbox_list = clist_new(); + if (resp_info->rsp_mailbox_list == NULL) + goto free; + resp_info->rsp_extension_list = clist_new(); + if (resp_info->rsp_extension_list == NULL) + goto free_mb_list; + resp_info->rsp_mailbox_lsub = clist_new(); + if (resp_info->rsp_mailbox_lsub == NULL) + goto free_extension_list; + resp_info->rsp_search_result = clist_new(); + if (resp_info->rsp_search_result == NULL) + goto free_mb_lsub; + resp_info->rsp_status = NULL; + resp_info->rsp_expunged = clist_new(); + if (resp_info->rsp_expunged == NULL) + goto free_search_result; + resp_info->rsp_fetch_list = clist_new(); + if (resp_info->rsp_fetch_list == NULL) + goto free_expunged; + resp_info->rsp_atom = NULL; + resp_info->rsp_value = NULL; + + return resp_info; + + free_expunged: + clist_free(resp_info->rsp_expunged); + free_search_result: + clist_free(resp_info->rsp_search_result); + free_mb_lsub: + clist_free(resp_info->rsp_mailbox_lsub); + free_extension_list: + clist_free(resp_info->rsp_extension_list); + free_mb_list: + clist_free(resp_info->rsp_mailbox_list); + free: + free(resp_info); + err: + return NULL; +} + +LIBETPAN_EXPORT +void +mailimap_response_info_free(struct mailimap_response_info * resp_info) +{ + free(resp_info->rsp_value); + free(resp_info->rsp_atom); + if (resp_info->rsp_alert != NULL) + free(resp_info->rsp_alert); + if (resp_info->rsp_parse != NULL) + free(resp_info->rsp_parse); + if (resp_info->rsp_badcharset != NULL) { + clist_foreach(resp_info->rsp_badcharset, + (clist_func) mailimap_astring_free, NULL); + clist_free(resp_info->rsp_badcharset); + } + if (resp_info->rsp_mailbox_list != NULL) { + clist_foreach(resp_info->rsp_mailbox_list, + (clist_func) mailimap_mailbox_list_free, NULL); + clist_free(resp_info->rsp_mailbox_list); + } + if (resp_info->rsp_extension_list != NULL) { + clist_foreach(resp_info->rsp_extension_list, + (clist_func) mailimap_extension_data_free, NULL); + clist_free(resp_info->rsp_extension_list); + } + if (resp_info->rsp_mailbox_lsub != NULL) { + clist_foreach(resp_info->rsp_mailbox_lsub, + (clist_func) mailimap_mailbox_list_free, NULL); + clist_free(resp_info->rsp_mailbox_lsub); + } + if (resp_info->rsp_search_result != NULL) + mailimap_mailbox_data_search_free(resp_info->rsp_search_result); + if (resp_info->rsp_status != NULL) + mailimap_mailbox_data_status_free(resp_info->rsp_status); + if (resp_info->rsp_expunged != NULL) { + clist_foreach(resp_info->rsp_expunged, + (clist_func) mailimap_number_alloc_free, NULL); + clist_free(resp_info->rsp_expunged); + } + if (resp_info->rsp_fetch_list != NULL) { + clist_foreach(resp_info->rsp_fetch_list, + (clist_func) mailimap_msg_att_free, NULL); + clist_free(resp_info->rsp_fetch_list); + } + + free(resp_info); +} + + +LIBETPAN_EXPORT +int +mailimap_parser_context_is_rambler_workaround_enabled(struct mailimap_parser_context * parser_ctx) +{ + return parser_ctx != NULL && parser_ctx->is_rambler_workaround_enabled; +} + +LIBETPAN_EXPORT +int +mailimap_parser_context_is_qip_workaround_enabled(struct mailimap_parser_context * parser_ctx) +{ + return parser_ctx != NULL && parser_ctx->is_qip_workaround_enabled; +} + +LIBETPAN_EXPORT +struct mailimap_parser_context * +mailimap_parser_context_new(mailimap * session) +{ + struct mailimap_parser_context * ctx; + + ctx = malloc(sizeof(* ctx)); + if (ctx == NULL) + goto err; + + ctx->is_rambler_workaround_enabled = mailimap_is_rambler_workaround_enabled(session); + ctx->is_qip_workaround_enabled = mailimap_is_qip_workaround_enabled(session); + + ctx->msg_body_handler = session->imap_msg_body_handler; + ctx->msg_body_handler_context = session->imap_msg_body_handler_context; + ctx->msg_body_parse_in_progress = false; + ctx->msg_body_section = NULL; + ctx->msg_body_att_type = 0; + + return ctx; + +err: + return NULL; +} + +LIBETPAN_EXPORT +void +mailimap_parser_context_free(struct mailimap_parser_context * ctx) +{ + free(ctx); +} diff --git a/Sources/libetpan/low-level/imap/mailimap_types.h b/Sources/libetpan/low-level/imap/mailimap_types.h new file mode 100644 index 00000000..a2b0e2a0 --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_types.h @@ -0,0 +1,3611 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_types.h,v 1.34 2011/01/06 00:09:52 hoa Exp $ + */ + +/* + IMAP4rev1 grammar + + address = "(" addr-name SP addr-adl SP addr-mailbox SP + addr-host ")" + + addr-adl = nstring + ; Holds route from [RFC-822] route-addr if + ; non-NIL + + addr-host = nstring + ; NIL indicates [RFC-822] group syntax. + ; Otherwise, holds [RFC-822] domain name + + addr-mailbox = nstring + ; NIL indicates end of [RFC-822] group; if + ; non-NIL and addr-host is NIL, holds + ; [RFC-822] group name. + ; Otherwise, holds [RFC-822] local-part + ; after removing [RFC-822] quoting + + + + addr-name = nstring + ; If non-NIL, holds phrase from [RFC-822] + ; mailbox after removing [RFC-822] quoting + + append = "APPEND" SP mailbox [SP flag-list] [SP date-time] SP + literal + + astring = 1*ASTRING-CHAR / string + + ASTRING-CHAR = ATOM-CHAR / resp-specials + + atom = 1*ATOM-CHAR + + ATOM-CHAR = + + atom-specials = "(" / ")" / "{" / SP / CTL / list-wildcards / + quoted-specials / resp-specials + + authenticate = "AUTHENTICATE" SP auth-type *(CRLF base64) + + auth-type = atom + ; Defined by [SASL] + + base64 = *(4base64-char) [base64-terminal] + + base64-char = ALPHA / DIGIT / "+" / "/" + ; Case-sensitive + + base64-terminal = (2base64-char "==") / (3base64-char "=") + + body = "(" (body-type-1part / body-type-mpart) ")" + + body-extension = nstring / number / + "(" body-extension *(SP body-extension) ")" + ; Future expansion. Client implementations + ; MUST accept body-extension fields. Server + ; implementations MUST NOT generate + ; body-extension fields except as defined by + ; future standard or standards-track + ; revisions of this specification. + + body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] + ; MUST NOT be returned on non-extensible + ; "BODY" fetch + + + body-ext-mpart = body-fld-param [SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] + ; MUST NOT be returned on non-extensible + ; "BODY" fetch + + body-fields = body-fld-param SP body-fld-id SP body-fld-desc SP + body-fld-enc SP body-fld-octets + + body-fld-desc = nstring + + body-fld-dsp = "(" string SP body-fld-param ")" / nil + + body-fld-enc = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/ + "QUOTED-PRINTABLE") DQUOTE) / string + + body-fld-id = nstring + + body-fld-lang = nstring / "(" string *(SP string) ")" + + body-fld-lines = number + + body-fld-md5 = nstring + + body-fld-octets = number + + body-fld-param = "(" string SP string *(SP string SP string) ")" / nil + + body-type-1part = (body-type-basic / body-type-msg / body-type-text) + [SP body-ext-1part] + + body-type-basic = media-basic SP body-fields + ; MESSAGE subtype MUST NOT be "RFC822" + + body-type-mpart = 1*body SP media-subtype + [SP body-ext-mpart] + + body-type-msg = media-message SP body-fields SP envelope + SP body SP body-fld-lines + + body-type-text = media-text SP body-fields SP body-fld-lines + + capability = ("AUTH=" auth-type) / atom + ; New capabilities MUST begin with "X" or be + ; registered with IANA as standard or + ; standards-track + + + capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev1" + *(SP capability) + ; IMAP4rev1 servers which offer RFC 1730 + ; compatibility MUST list "IMAP4" as the first + ; capability. + + CHAR8 = %x01-ff + ; any OCTET except NUL, %x00 + + command = tag SP (command-any / command-auth / command-nonauth / + command-select) CRLF + ; Modal based on state + + command-any = "CAPABILITY" / "LOGOUT" / "NOOP" / x-command + ; Valid in all states + + command-auth = append / create / delete / examine / list / lsub / + rename / select / status / subscribe / unsubscribe + ; Valid only in Authenticated or Selected state + + command-nonauth = login / authenticate + ; Valid only when in Not Authenticated state + + command-select = "CHECK" / "CLOSE" / "EXPUNGE" / copy / fetch / store / + uid / search + ; Valid only when in Selected state + + continue-req = "+" SP (resp-text / base64) CRLF + + copy = "COPY" SP set SP mailbox + + create = "CREATE" SP mailbox + ; Use of INBOX gives a NO error + + date = date-text / DQUOTE date-text DQUOTE + + date-day = 1*2DIGIT + ; Day of month + + date-day-fixed = (SP DIGIT) / 2DIGIT + ; Fixed-format version of date-day + + date-month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / + "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" + + date-text = date-day "-" date-month "-" date-year + + date-year = 4DIGIT + + date-time = DQUOTE date-day-fixed "-" date-month "-" date-year + SP time SP zone DQUOTE + + delete = "DELETE" SP mailbox + ; Use of INBOX gives a NO error + + digit-nz = %x31-39 + ; 1-9 + + envelope = "(" env-date SP env-subject SP env-from SP env-sender SP + env-reply-to SP env-to SP env-cc SP env-bcc SP + env-in-reply-to SP env-message-id ")" + + env-bcc = "(" 1*address ")" / nil + + env-cc = "(" 1*address ")" / nil + + env-date = nstring + + env-from = "(" 1*address ")" / nil + + env-in-reply-to = nstring + + env-message-id = nstring + + env-reply-to = "(" 1*address ")" / nil + + env-sender = "(" 1*address ")" / nil + + env-subject = nstring + + env-to = "(" 1*address ")" / nil + + examine = "EXAMINE" SP mailbox + + fetch = "FETCH" SP set SP ("ALL" / "FULL" / "FAST" / fetch-att / + "(" fetch-att *(SP fetch-att) ")") + + fetch-att = "ENVELOPE" / "FLAGS" / "INTERNALDATE" / + "RFC822" [".HEADER" / ".SIZE" / ".TEXT"] / + "BODY" ["STRUCTURE"] / "UID" / + "BODY" [".PEEK"] section ["<" number "." nz-number ">"] + + flag = "\Answered" / "\Flagged" / "\Deleted" / + "\Seen" / "\Draft" / flag-keyword / flag-extension + ; Does not include "\Recent" + + flag-extension = "\" atom + ; Future expansion. Client implementations + ; MUST accept flag-extension flags. Server + ; implementations MUST NOT generate + ; flag-extension flags except as defined by + ; future standard or standards-track + ; revisions of this specification. + + flag-fetch = flag / "\Recent" + + flag-keyword = atom + + flag-list = "(" [flag *(SP flag)] ")" + + flag-perm = flag / "\*" + + greeting = "*" SP (resp-cond-auth / resp-cond-bye) CRLF + + header-fld-name = astring + + header-list = "(" header-fld-name *(SP header-fld-name) ")" + + list = "LIST" SP mailbox SP list-mailbox + + list-mailbox = 1*list-char / string + + list-char = ATOM-CHAR / list-wildcards / resp-specials + + list-wildcards = "%" / "*" + + literal = "{" number "}" CRLF *CHAR8 + ; Number represents the number of CHAR8s + + login = "LOGIN" SP userid SP password + + lsub = "LSUB" SP mailbox SP list-mailbox + + mailbox = "INBOX" / astring + ; INBOX is case-insensitive. All case variants of + ; INBOX (e.g. "iNbOx") MUST be interpreted as INBOX + ; not as an astring. An astring which consists of + ; the case-insensitive sequence "I" "N" "B" "O" "X" + ; is considered to be INBOX and not an astring. + ; Refer to section 5.1 for further + ; semantic details of mailbox names. + + mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list / + "LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) / + "STATUS" SP mailbox SP "(" + [status-att SP number *(SP status-att SP number)] ")" / + number SP "EXISTS" / number SP "RECENT" + + mailbox-list = "(" [mbx-list-flags] ")" SP + (DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox + + mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag + *(SP mbx-list-oflag) / + mbx-list-oflag *(SP mbx-list-oflag) + + mbx-list-oflag = "\Noinferiors" / flag-extension + ; Other flags; multiple possible per LIST response + + mbx-list-sflag = "\Noselect" / "\Marked" / "\Unmarked" + ; Selectability flags; only one per LIST response + + media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" / + "VIDEO") DQUOTE) / string) SP media-subtype + ; Defined in [MIME-IMT] + + media-message = DQUOTE "MESSAGE" DQUOTE SP DQUOTE "RFC822" DQUOTE + ; Defined in [MIME-IMT] + + media-subtype = string + ; Defined in [MIME-IMT] + + media-text = DQUOTE "TEXT" DQUOTE SP media-subtype + ; Defined in [MIME-IMT] + + message-data = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att)) + + msg-att = "(" (msg-att-dynamic / msg-att-static) + *(SP (msg-att-dynamic / msg-att-static)) ")" + + msg-att-dynamic = "FLAGS" SP "(" [flag-fetch *(SP flag-fetch)] ")" + ; MAY change for a message + + msg-att-static = "ENVELOPE" SP envelope / "INTERNALDATE" SP date-time / + "RFC822" [".HEADER" / ".TEXT"] SP nstring / + "RFC822.SIZE" SP number / "BODY" ["STRUCTURE"] SP body / + "BODY" section ["<" number ">"] SP nstring / + "UID" SP uniqueid + ; MUST NOT change for a message + + nil = "NIL" + + nstring = string / nil + + number = 1*DIGIT + ; Unsigned 32-bit integer + ; (0 <= n < 4,294,967,296) + + nz-number = digit-nz *DIGIT + ; Non-zero unsigned 32-bit integer + ; (0 < n < 4,294,967,296) + + password = astring + + quoted = DQUOTE *QUOTED-CHAR DQUOTE + + QUOTED-CHAR = / + "\" quoted-specials + + quoted-specials = DQUOTE / "\" + + rename = "RENAME" SP mailbox SP mailbox + ; Use of INBOX as a destination gives a NO error + + response = *(continue-req / response-data) response-done + + response-data = "*" SP (resp-cond-state / resp-cond-bye / + mailbox-data / message-data / capability-data) CRLF + + response-done = response-tagged / response-fatal + + response-fatal = "*" SP resp-cond-bye CRLF + ; Server closes connection immediately + + response-tagged = tag SP resp-cond-state CRLF + + resp-cond-auth = ("OK" / "PREAUTH") SP resp-text + ; Authentication condition + + resp-cond-bye = "BYE" SP resp-text + + resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text + ; Status condition + + resp-specials = "]" + + resp-text = ["[" resp-text-code "]" SP] text + + resp-text-code = "ALERT" / + "BADCHARSET" [SP "(" astring *(SP astring) ")" ] / + capability-data / "PARSE" / + "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" / + "READ-ONLY" / "READ-WRITE" / "TRYCREATE" / + "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number / + "UNSEEN" SP nz-number / + atom [SP 1*] + + search = "SEARCH" [SP "CHARSET" SP astring] 1*(SP search-key) + ; CHARSET argument to MUST be registered with IANA + + search-key = "ALL" / "ANSWERED" / "BCC" SP astring / + "BEFORE" SP date / "BODY" SP astring / + "CC" SP astring / "DELETED" / "FLAGGED" / + "FROM" SP astring / "KEYWORD" SP flag-keyword / "NEW" / + "OLD" / "ON" SP date / "RECENT" / "SEEN" / + "SINCE" SP date / "SUBJECT" SP astring / + "TEXT" SP astring / "TO" SP astring / + "UNANSWERED" / "UNDELETED" / "UNFLAGGED" / + "UNKEYWORD" SP flag-keyword / "UNSEEN" / + ; Above this line were in [IMAP2] + "DRAFT" / "HEADER" SP header-fld-name SP astring / + "LARGER" SP number / "NOT" SP search-key / + "OR" SP search-key SP search-key / + "SENTBEFORE" SP date / "SENTON" SP date / + "SENTSINCE" SP date / "SMALLER" SP number / + "UID" SP set / "UNDRAFT" / set / + "(" search-key *(SP search-key) ")" + + section = "[" [section-spec] "]" + + section-msgtext = "HEADER" / "HEADER.FIELDS" [".NOT"] SP header-list / + "TEXT" + ; top-level or MESSAGE/RFC822 part + + section-part = nz-number *("." nz-number) + ; body part nesting + + section-spec = section-msgtext / (section-part ["." section-text]) + + section-text = section-msgtext / "MIME" + ; text other than actual body part (headers, etc.) + + select = "SELECT" SP mailbox + + sequence-num = nz-number / "*" + ; * is the largest number in use. For message + ; sequence numbers, it is the number of messages + ; in the mailbox. For unique identifiers, it is + ; the unique identifier of the last message in + ; the mailbox. + + set = sequence-num / (sequence-num ":" sequence-num) / + (set "," set) + ; Identifies a set of messages. For message + ; sequence numbers, these are consecutive + ; numbers from 1 to the number of messages in + ; the mailbox + ; Comma delimits individual numbers, colon + ; delimits between two numbers inclusive. + ; Example: 2,4:7,9,12:* is 2,4,5,6,7,9,12,13, + ; 14,15 for a mailbox with 15 messages. + + + status = "STATUS" SP mailbox SP "(" status-att *(SP status-att) ")" + + status-att = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" / + "UNSEEN" + + store = "STORE" SP set SP store-att-flags + + store-att-flags = (["+" / "-"] "FLAGS" [".SILENT"]) SP + (flag-list / (flag *(SP flag))) + + string = quoted / literal + + subscribe = "SUBSCRIBE" SP mailbox + + tag = 1* + + text = 1*TEXT-CHAR + + TEXT-CHAR = + + time = 2DIGIT ":" 2DIGIT ":" 2DIGIT + ; Hours minutes seconds + + uid = "UID" SP (copy / fetch / search / store) + ; Unique identifiers used instead of message + ; sequence numbers + + uniqueid = nz-number + ; Strictly ascending + + unsubscribe = "UNSUBSCRIBE" SP mailbox + + userid = astring + + x-command = "X" atom + + zone = ("+" / "-") 4DIGIT + ; Signed four-digit value of hhmm representing + ; hours and minutes east of Greenwich (that is, + ; the amount that the given time differs from + ; Universal Time). Subtracting the timezone + ; from the given time will give the UT form. + ; The Universal Time zone is "+0000". +*/ + + +#ifndef MAILIMAP_TYPES_H + +#define MAILIMAP_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + + +/* + IMPORTANT NOTE: + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + allocation functions will return NULL on failure +*/ + + +/* + mailimap_address represents a mail address + + - personal_name is the name to display in an address + '"name"' in '"name" ', should be allocated + with a malloc() + + - source_route is the source-route information in the + mail address (RFC 822), should be allocated with a malloc() + + - mailbox_name is the name of the mailbox 'address' in + '"name" ', should be allocated with a malloc() + + - host_name is the name of the host 'domain' in + '"name" ', should be allocated with a malloc() + + if mailbox_name is not NULL and host_name is NULL, this is the name + of a group, the next addresses in the list are elements of the group + until we reach an address with a NULL mailbox_name. +*/ + +struct mailimap_address { + char * ad_personal_name; /* can be NULL */ + char * ad_source_route; /* can be NULL */ + char * ad_mailbox_name; /* can be NULL */ + char * ad_host_name; /* can be NULL */ +}; + + +LIBETPAN_EXPORT +struct mailimap_address * +mailimap_address_new(char * ad_personal_name, char * ad_source_route, + char * ad_mailbox_name, char * ad_host_name); + +LIBETPAN_EXPORT +void mailimap_address_free(struct mailimap_address * addr); + + +/* this is the type of MIME body parsed by IMAP server */ + +enum { + MAILIMAP_BODY_ERROR, + MAILIMAP_BODY_1PART, /* single part */ + MAILIMAP_BODY_MPART /* multi-part */ +}; + +/* + mailimap_body represent a MIME body parsed by IMAP server + + - type is the type of the MIME part (single part or multipart) + + - body_1part is defined if this is a single part + + - body_mpart is defined if this is a multipart +*/ + +struct mailimap_body { + int bd_type; + /* can be MAILIMAP_BODY_1PART or MAILIMAP_BODY_MPART */ + union { + struct mailimap_body_type_1part * bd_body_1part; /* can be NULL */ + struct mailimap_body_type_mpart * bd_body_mpart; /* can be NULL */ + } bd_data; +}; + + +LIBETPAN_EXPORT +struct mailimap_body * +mailimap_body_new(int bd_type, + struct mailimap_body_type_1part * bd_body_1part, + struct mailimap_body_type_mpart * bd_body_mpart); + +LIBETPAN_EXPORT +void mailimap_body_free(struct mailimap_body * body); + + + +/* + this is the type of MIME body extension +*/ + +enum { + MAILIMAP_BODY_EXTENSION_ERROR, + MAILIMAP_BODY_EXTENSION_NSTRING, /* string */ + MAILIMAP_BODY_EXTENSION_NUMBER, /* number */ + MAILIMAP_BODY_EXTENSION_LIST /* list of + (struct mailimap_body_extension *) */ +}; + +/* + mailimap_body_extension is a future extension header field value + + - type is the type of the body extension (string, number or + list of extension) + + - nstring is a string value if the type is string + + - number is a integer value if the type is number + + - list is a list of body extension if the type is a list +*/ + +struct mailimap_body_extension { + int ext_type; + /* + can be MAILIMAP_BODY_EXTENSION_NSTRING, MAILIMAP_BODY_EXTENSION_NUMBER + or MAILIMAP_BODY_EXTENSION_LIST + */ + union { + char * ext_nstring; /* can be NULL */ + uint32_t ext_number; + clist * ext_body_extension_list; + /* list of (struct mailimap_body_extension *) */ + /* can be NULL */ + } ext_data; +}; + +LIBETPAN_EXPORT +struct mailimap_body_extension * +mailimap_body_extension_new(int ext_type, char * ext_nstring, + uint32_t ext_number, + clist * ext_body_extension_list); + +LIBETPAN_EXPORT +void mailimap_body_extension_free(struct mailimap_body_extension * be); + + +/* + mailimap_body_ext_1part is the extended result part of a single part + bodystructure. + + - body_md5 is the value of the Content-MD5 header field, should be + allocated with malloc() + + - body_disposition is the value of the Content-Disposition header field + + - body_language is the value of the Content-Language header field + + - body_extension_list is the list of extension fields value. +*/ + +struct mailimap_body_ext_1part { + char * bd_md5; /* can be NULL */ + struct mailimap_body_fld_dsp * bd_disposition; /* can be NULL */ + struct mailimap_body_fld_lang * bd_language; /* can be NULL */ + char * bd_loc; /* can be NULL */ + + clist * bd_extension_list; /* list of (struct mailimap_body_extension *) */ + /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_body_ext_1part * +mailimap_body_ext_1part_new(char * bd_md5, + struct mailimap_body_fld_dsp * bd_disposition, + struct mailimap_body_fld_lang * bd_language, + char * bd_loc, + clist * bd_extension_list); + + +LIBETPAN_EXPORT +void +mailimap_body_ext_1part_free(struct mailimap_body_ext_1part * body_ext_1part); + + +/* + mailimap_body_ext_mpart is the extended result part of a multipart + bodystructure. + + - body_parameter is the list of parameters of Content-Type header field + + - body_disposition is the value of Content-Disposition header field + + - body_language is the value of Content-Language header field + + - body_extension_list is the list of extension fields value. +*/ + +struct mailimap_body_ext_mpart { + struct mailimap_body_fld_param * bd_parameter; /* can be NULL */ + struct mailimap_body_fld_dsp * bd_disposition; /* can be NULL */ + struct mailimap_body_fld_lang * bd_language; /* can be NULL */ + char * bd_loc; /* can be NULL */ + clist * bd_extension_list; /* list of (struct mailimap_body_extension *) */ + /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_body_ext_mpart * +mailimap_body_ext_mpart_new(struct mailimap_body_fld_param * bd_parameter, + struct mailimap_body_fld_dsp * bd_disposition, + struct mailimap_body_fld_lang * bd_language, + char * bd_loc, + clist * bd_extension_list); + +LIBETPAN_EXPORT +void +mailimap_body_ext_mpart_free(struct mailimap_body_ext_mpart * body_ext_mpart); + + +/* + mailimap_body_fields is the MIME fields of a MIME part. + + - body_parameter is the list of parameters of Content-Type header field + + - body_id is the value of Content-ID header field, should be allocated + with malloc() + + - body_description is the value of Content-Description header field, + should be allocated with malloc() + + - body_encoding is the value of Content-Transfer-Encoding header field + + - body_disposition is the value of Content-Disposition header field + + - body_size is the size of the MIME part +*/ + +struct mailimap_body_fields { + struct mailimap_body_fld_param * bd_parameter; /* can be NULL */ + char * bd_id; /* can be NULL */ + char * bd_description; /* can be NULL */ + struct mailimap_body_fld_enc * bd_encoding; /* != NULL */ + uint32_t bd_size; +}; + +LIBETPAN_EXPORT +struct mailimap_body_fields * +mailimap_body_fields_new(struct mailimap_body_fld_param * bd_parameter, + char * bd_id, + char * bd_description, + struct mailimap_body_fld_enc * bd_encoding, + uint32_t bd_size); + +LIBETPAN_EXPORT +void +mailimap_body_fields_free(struct mailimap_body_fields * body_fields); + + + +/* + mailimap_body_fld_dsp is the parsed value of the Content-Disposition field + + - disposition_type is the type of Content-Disposition + (usually attachment or inline), should be allocated with malloc() + + - attributes is the list of Content-Disposition attributes +*/ + +struct mailimap_body_fld_dsp { + char * dsp_type; /* != NULL */ + struct mailimap_body_fld_param * dsp_attributes; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_body_fld_dsp * +mailimap_body_fld_dsp_new(char * dsp_type, + struct mailimap_body_fld_param * dsp_attributes); + +LIBETPAN_EXPORT +void mailimap_body_fld_dsp_free(struct mailimap_body_fld_dsp * bfd); + + + +/* these are the different parsed values for Content-Transfer-Encoding */ + +enum { + MAILIMAP_BODY_FLD_ENC_7BIT, /* 7bit */ + MAILIMAP_BODY_FLD_ENC_8BIT, /* 8bit */ + MAILIMAP_BODY_FLD_ENC_BINARY, /* binary */ + MAILIMAP_BODY_FLD_ENC_BASE64, /* base64 */ + MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE, /* quoted-printable */ + MAILIMAP_BODY_FLD_ENC_OTHER /* other */ +}; + +/* + mailimap_body_fld_enc is a parsed value for Content-Transfer-Encoding + + - type is the kind of Content-Transfer-Encoding, this can be + MAILIMAP_BODY_FLD_ENC_7BIT, MAILIMAP_BODY_FLD_ENC_8BIT, + MAILIMAP_BODY_FLD_ENC_BINARY, MAILIMAP_BODY_FLD_ENC_BASE64, + MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE or MAILIMAP_BODY_FLD_ENC_OTHER + + - in case of MAILIMAP_BODY_FLD_ENC_OTHER, this value is defined, + should be allocated with malloc() +*/ + +struct mailimap_body_fld_enc { + int enc_type; + char * enc_value; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_body_fld_enc * +mailimap_body_fld_enc_new(int enc_type, char * enc_value); + +LIBETPAN_EXPORT +void mailimap_body_fld_enc_free(struct mailimap_body_fld_enc * bfe); + + +/* this is the type of Content-Language header field value */ + +enum { + MAILIMAP_BODY_FLD_LANG_ERROR, /* error parse */ + MAILIMAP_BODY_FLD_LANG_SINGLE, /* single value */ + MAILIMAP_BODY_FLD_LANG_LIST /* list of values */ +}; + +/* + mailimap_body_fld_lang is the parsed value of the Content-Language field + + - type is the type of content, this can be MAILIMAP_BODY_FLD_LANG_SINGLE + if this is a single value or MAILIMAP_BODY_FLD_LANG_LIST if there are + several values + + - single is the single value if the type is MAILIMAP_BODY_FLD_LANG_SINGLE, + should be allocated with malloc() + + - list is the list of value if the type is MAILIMAP_BODY_FLD_LANG_LIST, + all elements of the list should be allocated with malloc() +*/ + +struct mailimap_body_fld_lang { + int lg_type; + union { + char * lg_single; /* can be NULL */ + clist * lg_list; /* list of string (char *), can be NULL */ + } lg_data; +}; + +LIBETPAN_EXPORT +struct mailimap_body_fld_lang * +mailimap_body_fld_lang_new(int lg_type, char * lg_single, clist * lg_list); + +LIBETPAN_EXPORT +void +mailimap_body_fld_lang_free(struct mailimap_body_fld_lang * fld_lang); + + + +/* + mailimap_single_body_fld_param is a body field parameter + + - name is the name of the parameter, should be allocated with malloc() + + - value is the value of the parameter, should be allocated with malloc() +*/ + +struct mailimap_single_body_fld_param { + char * pa_name; /* != NULL */ + char * pa_value; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_single_body_fld_param * +mailimap_single_body_fld_param_new(char * pa_name, char * pa_value); + +LIBETPAN_EXPORT +void +mailimap_single_body_fld_param_free(struct mailimap_single_body_fld_param * p); + + +/* + mailmap_body_fld_param is a list of parameters + + - list is the list of parameters. +*/ + +struct mailimap_body_fld_param { + clist * pa_list; /* list of (struct mailimap_single_body_fld_param *) */ + /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_body_fld_param * +mailimap_body_fld_param_new(clist * pa_list); + +LIBETPAN_EXPORT +void +mailimap_body_fld_param_free(struct mailimap_body_fld_param * fld_param); + + +/* + this is the kind of single part: a text part + (when Content-Type is text/xxx), a message part (when Content-Type is + message/rfc2822) or a basic part (others than multpart/xxx) +*/ + +enum { + MAILIMAP_BODY_TYPE_1PART_ERROR, /* parse error */ + MAILIMAP_BODY_TYPE_1PART_BASIC, /* others then multipart/xxx */ + MAILIMAP_BODY_TYPE_1PART_MSG, /* message/rfc2822 */ + MAILIMAP_BODY_TYPE_1PART_TEXT /* text/xxx */ +}; + + +/* + mailimap_body_type_1part is + + - type is the kind of single part, this can be + MAILIMAP_BODY_TYPE_1PART_BASIC, MAILIMAP_BODY_TYPE_1PART_MSG or + MAILIMAP_BODY_TYPE_1PART_TEXT. + + - body_type_basic is the basic part when type is + MAILIMAP_BODY_TYPE_1PART_BASIC + + - body_type_msg is the message part when type is + MAILIMAP_BODY_TYPE_1PART_MSG + + - body_type_text is the text part when type is + MAILIMAP_BODY_TYPE_1PART_TEXT +*/ + +struct mailimap_body_type_1part { + int bd_type; + union { + struct mailimap_body_type_basic * bd_type_basic; /* can be NULL */ + struct mailimap_body_type_msg * bd_type_msg; /* can be NULL */ + struct mailimap_body_type_text * bd_type_text; /* can be NULL */ + } bd_data; + struct mailimap_body_ext_1part * bd_ext_1part; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_body_type_1part * +mailimap_body_type_1part_new(int bd_type, + struct mailimap_body_type_basic * bd_type_basic, + struct mailimap_body_type_msg * bd_type_msg, + struct mailimap_body_type_text * bd_type_text, + struct mailimap_body_ext_1part * bd_ext_1part); + +LIBETPAN_EXPORT +void +mailimap_body_type_1part_free(struct mailimap_body_type_1part * bt1p); + + + +/* + mailimap_body_type_basic is a basic field (with Content-Type other + than multipart/xxx, message/rfc2822 and text/xxx + + - media_basic will be the MIME type of the part + + - body_fields will be the parsed fields of the MIME part +*/ + +struct mailimap_body_type_basic { + struct mailimap_media_basic * bd_media_basic; /* != NULL */ + struct mailimap_body_fields * bd_fields; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_body_type_basic * +mailimap_body_type_basic_new(struct mailimap_media_basic * bd_media_basic, + struct mailimap_body_fields * bd_fields); + +LIBETPAN_EXPORT +void mailimap_body_type_basic_free(struct mailimap_body_type_basic * + body_type_basic); + +/* + mailimap_body_type_mpart is a MIME multipart. + + - body_list is the list of sub-parts. + + - media_subtype is the subtype of the multipart (for example + in multipart/alternative, this is "alternative") + + - body_ext_mpart is the extended fields of the MIME multipart +*/ + +struct mailimap_body_type_mpart { + clist * bd_list; /* list of (struct mailimap_body *) */ + /* != NULL */ + char * bd_media_subtype; /* != NULL */ + struct mailimap_body_ext_mpart * bd_ext_mpart; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_body_type_mpart * +mailimap_body_type_mpart_new(clist * bd_list, char * bd_media_subtype, + struct mailimap_body_ext_mpart * bd_ext_mpart); + +LIBETPAN_EXPORT +void mailimap_body_type_mpart_free(struct mailimap_body_type_mpart * + body_type_mpart); + +/* + mailimap_body_type_msg is a MIME message part + + - body_fields is the MIME fields of the MIME message part + + - envelope is the list of parsed RFC 822 fields of the MIME message + + - body is the sub-part of the message + + - body_lines is the number of lines of the message part +*/ + +struct mailimap_body_type_msg { + struct mailimap_body_fields * bd_fields; /* != NULL */ + struct mailimap_envelope * bd_envelope; /* != NULL */ + struct mailimap_body * bd_body; /* != NULL */ + uint32_t bd_lines; +}; + +LIBETPAN_EXPORT +struct mailimap_body_type_msg * +mailimap_body_type_msg_new(struct mailimap_body_fields * bd_fields, + struct mailimap_envelope * bd_envelope, + struct mailimap_body * bd_body, + uint32_t bd_lines); + +LIBETPAN_EXPORT +void +mailimap_body_type_msg_free(struct mailimap_body_type_msg * body_type_msg); + + + +/* + mailimap_body_type_text is a single MIME part where Content-Type is text/xxx + + - media-text is the subtype of the text part (for example, in "text/plain", + this is "plain", should be allocated with malloc() + + - body_fields is the MIME fields of the MIME message part + + - body_lines is the number of lines of the message part +*/ + +struct mailimap_body_type_text { + char * bd_media_text; /* != NULL */ + struct mailimap_body_fields * bd_fields; /* != NULL */ + uint32_t bd_lines; +}; + +LIBETPAN_EXPORT +struct mailimap_body_type_text * +mailimap_body_type_text_new(char * bd_media_text, + struct mailimap_body_fields * bd_fields, + uint32_t bd_lines); + +LIBETPAN_EXPORT +void +mailimap_body_type_text_free(struct mailimap_body_type_text * body_type_text); + + + +/* this is the type of capability field */ + +enum { + MAILIMAP_CAPABILITY_AUTH_TYPE, /* when the capability is an + authentication type */ + MAILIMAP_CAPABILITY_NAME /* other type of capability */ +}; + +/* + mailimap_capability is a capability of the IMAP server + + - type is the type of capability, this is either a authentication type + (MAILIMAP_CAPABILITY_AUTH_TYPE) or an other type of capability + (MAILIMAP_CAPABILITY_NAME) + + - auth_type is a type of authentication "name" in "AUTH=name", + auth_type can be for example "PLAIN", when this is an authentication type, + should be allocated with malloc() + + - name is a type of capability when this is not an authentication type, + should be allocated with malloc() +*/ + +struct mailimap_capability { + int cap_type; + union { + char * cap_auth_type; /* can be NULL */ + char * cap_name; /* can be NULL */ + } cap_data; +}; + +LIBETPAN_EXPORT +struct mailimap_capability * +mailimap_capability_new(int cap_type, char * cap_auth_type, char * cap_name); + +LIBETPAN_EXPORT +void mailimap_capability_free(struct mailimap_capability * c); + + + + +/* + mailimap_capability_data is a list of capability + + - list is the list of capability +*/ + +struct mailimap_capability_data { + clist * cap_list; /* list of (struct mailimap_capability *), != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_capability_data * +mailimap_capability_data_new(clist * cap_list); + +LIBETPAN_EXPORT +void +mailimap_capability_data_free(struct mailimap_capability_data * cap_data); + + + +/* this is the type of continue request data */ + +enum { + MAILIMAP_CONTINUE_REQ_ERROR, /* on parse error */ + MAILIMAP_CONTINUE_REQ_TEXT, /* when data is a text response */ + MAILIMAP_CONTINUE_REQ_BASE64 /* when data is a base64 response */ +}; + +/* + mailimap_continue_req is a continue request (a response prefixed by "+") + + - type is the type of continue request response + MAILIMAP_CONTINUE_REQ_TEXT (when information data is text), + MAILIMAP_CONTINUE_REQ_BASE64 (when information data is base64) + + - text is the information of type text in case of text data + + - base64 is base64 encoded data in the other case, should be allocated + with malloc() +*/ + +struct mailimap_continue_req { + int cr_type; + union { + struct mailimap_resp_text * cr_text; /* can be NULL */ + char * cr_base64; /* can be NULL */ + } cr_data; +}; + +LIBETPAN_EXPORT +struct mailimap_continue_req * +mailimap_continue_req_new(int cr_type, struct mailimap_resp_text * cr_text, + char * cr_base64); + +LIBETPAN_EXPORT +void mailimap_continue_req_free(struct mailimap_continue_req * cont_req); + + +/* + mailimap_date_time is a date + + - day is the day of month (1 to 31) + + - month (1 to 12) + + - year (4 digits) + + - hour (0 to 23) + + - min (0 to 59) + + - sec (0 to 59) + + - zone (this is the decimal value that we can read, for example: + for "-0200", the value is -200) +*/ + +struct mailimap_date_time { + int dt_day; + int dt_month; + int dt_year; + int dt_hour; + int dt_min; + int dt_sec; + int dt_zone; +}; + +LIBETPAN_EXPORT +struct mailimap_date_time * +mailimap_date_time_new(int dt_day, int dt_month, int dt_year, int dt_hour, + int dt_min, int dt_sec, int dt_zone); + +LIBETPAN_EXPORT +void mailimap_date_time_free(struct mailimap_date_time * date_time); + + + +/* + mailimap_envelope is the list of fields that can be parsed by + the IMAP server. + + - date is the (non-parsed) content of the "Date" header field, + should be allocated with malloc() + + - subject is the subject of the message, should be allocated with + malloc() + + - sender is the the parsed content of the "Sender" field + + - reply-to is the parsed content of the "Reply-To" field + + - to is the parsed content of the "To" field + + - cc is the parsed content of the "Cc" field + + - bcc is the parsed content of the "Bcc" field + + - in_reply_to is the content of the "In-Reply-To" field, + should be allocated with malloc() + + - message_id is the content of the "Message-ID" field, + should be allocated with malloc() +*/ + +struct mailimap_envelope { + char * env_date; /* can be NULL */ + char * env_subject; /* can be NULL */ + struct mailimap_env_from * env_from; /* can be NULL */ + struct mailimap_env_sender * env_sender; /* can be NULL */ + struct mailimap_env_reply_to * env_reply_to; /* can be NULL */ + struct mailimap_env_to * env_to; /* can be NULL */ + struct mailimap_env_cc * env_cc; /* can be NULL */ + struct mailimap_env_bcc * env_bcc; /* can be NULL */ + char * env_in_reply_to; /* can be NULL */ + char * env_message_id; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_envelope * +mailimap_envelope_new(char * env_date, char * env_subject, + struct mailimap_env_from * env_from, + struct mailimap_env_sender * env_sender, + struct mailimap_env_reply_to * env_reply_to, + struct mailimap_env_to * env_to, + struct mailimap_env_cc* env_cc, + struct mailimap_env_bcc * env_bcc, + char * env_in_reply_to, char * env_message_id); + +LIBETPAN_EXPORT +void mailimap_envelope_free(struct mailimap_envelope * env); + + + +/* + mailimap_env_bcc is the parsed "Bcc" field + + - list is the list of addresses +*/ + +struct mailimap_env_bcc { + clist * bcc_list; /* list of (struct mailimap_address *), can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_env_bcc * mailimap_env_bcc_new(clist * bcc_list); + +LIBETPAN_EXPORT +void mailimap_env_bcc_free(struct mailimap_env_bcc * env_bcc); + + +/* + mailimap_env_cc is the parsed "Cc" field + + - list is the list of addresses +*/ + +struct mailimap_env_cc { + clist * cc_list; /* list of (struct mailimap_address *), can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_env_cc * mailimap_env_cc_new(clist * cc_list); + +LIBETPAN_EXPORT +void mailimap_env_cc_free(struct mailimap_env_cc * env_cc); + + + +/* + mailimap_env_from is the parsed "From" field + + - list is the list of addresses +*/ + +struct mailimap_env_from { + clist * frm_list; /* list of (struct mailimap_address *) */ + /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_env_from * mailimap_env_from_new(clist * frm_list); + +LIBETPAN_EXPORT +void mailimap_env_from_free(struct mailimap_env_from * env_from); + + + +/* + mailimap_env_reply_to is the parsed "Reply-To" field + + - list is the list of addresses +*/ + +struct mailimap_env_reply_to { + clist * rt_list; /* list of (struct mailimap_address *), can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_env_reply_to * mailimap_env_reply_to_new(clist * rt_list); + +LIBETPAN_EXPORT +void +mailimap_env_reply_to_free(struct mailimap_env_reply_to * env_reply_to); + + + +/* + mailimap_env_sender is the parsed "Sender" field + + - list is the list of addresses +*/ + +struct mailimap_env_sender { + clist * snd_list; /* list of (struct mailimap_address *), can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_env_sender * mailimap_env_sender_new(clist * snd_list); + +LIBETPAN_EXPORT +void mailimap_env_sender_free(struct mailimap_env_sender * env_sender); + + + +/* + mailimap_env_to is the parsed "To" field + + - list is the list of addresses +*/ + +struct mailimap_env_to { + clist * to_list; /* list of (struct mailimap_address *), can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_env_to * mailimap_env_to_new(clist * to_list); + +LIBETPAN_EXPORT +void mailimap_env_to_free(struct mailimap_env_to * env_to); + + +/* this is the type of flag */ + +enum { + MAILIMAP_FLAG_ANSWERED, /* \Answered flag */ + MAILIMAP_FLAG_FLAGGED, /* \Flagged flag */ + MAILIMAP_FLAG_DELETED, /* \Deleted flag */ + MAILIMAP_FLAG_SEEN, /* \Seen flag */ + MAILIMAP_FLAG_DRAFT, /* \Draft flag */ + MAILIMAP_FLAG_KEYWORD, /* keyword flag */ + MAILIMAP_FLAG_EXTENSION /* \extension flag */ +}; + + +/* + mailimap_flag is a message flag (that we can associate with a message) + + - type is the type of the flag, MAILIMAP_FLAG_XXX + + - keyword is the flag when the flag is of keyword type, + should be allocated with malloc() + + - extension is the flag when the flag is of extension type, should be + allocated with malloc() +*/ + +struct mailimap_flag { + int fl_type; + union { + char * fl_keyword; /* can be NULL */ + char * fl_extension; /* can be NULL */ + } fl_data; +}; + +LIBETPAN_EXPORT +struct mailimap_flag * mailimap_flag_new(int fl_type, + char * fl_keyword, char * fl_extension); + +LIBETPAN_EXPORT +void mailimap_flag_free(struct mailimap_flag * f); + + + + +/* this is the type of flag */ + +enum { + MAILIMAP_FLAG_FETCH_ERROR, /* on parse error */ + MAILIMAP_FLAG_FETCH_RECENT, /* \Recent flag */ + MAILIMAP_FLAG_FETCH_OTHER /* other type of flag */ +}; + +/* + mailimap_flag_fetch is a message flag (when we fetch it) + + - type is the type of flag fetch + + - flag is the flag when this is not a \Recent flag +*/ + +struct mailimap_flag_fetch { + int fl_type; + struct mailimap_flag * fl_flag; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_flag_fetch * +mailimap_flag_fetch_new(int fl_type, struct mailimap_flag * fl_flag); + +LIBETPAN_EXPORT +void mailimap_flag_fetch_free(struct mailimap_flag_fetch * flag_fetch); + + + + +/* this is the type of flag */ + +enum { + MAILIMAP_FLAG_PERM_ERROR, /* on parse error */ + MAILIMAP_FLAG_PERM_FLAG, /* to specify that usual flags can be changed */ + MAILIMAP_FLAG_PERM_ALL /* to specify that new flags can be created */ +}; + + +/* + mailimap_flag_perm is a flag returned in case of PERMANENTFLAGS response + + - type is the type of returned PERMANENTFLAGS, it can be + MAILIMAP_FLAG_PERM_FLAG (the given flag can be changed permanently) or + MAILIMAP_FLAG_PERM_ALL (new flags can be created) + + - flag is the given flag when type is MAILIMAP_FLAG_PERM_FLAG +*/ + +struct mailimap_flag_perm { + int fl_type; + struct mailimap_flag * fl_flag; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_flag_perm * +mailimap_flag_perm_new(int fl_type, struct mailimap_flag * fl_flag); + +LIBETPAN_EXPORT +void mailimap_flag_perm_free(struct mailimap_flag_perm * flag_perm); + + +/* + mailimap_flag_list is a list of flags + + - list is a list of flags +*/ + +struct mailimap_flag_list { + clist * fl_list; /* list of (struct mailimap_flag *), != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_flag_list * +mailimap_flag_list_new(clist * fl_list); + +LIBETPAN_EXPORT +void mailimap_flag_list_free(struct mailimap_flag_list * flag_list); + + + + +/* this is the type of greeting response */ + +enum { + MAILIMAP_GREETING_RESP_COND_ERROR, /* on parse error */ + MAILIMAP_GREETING_RESP_COND_AUTH, /* when connection is accepted */ + MAILIMAP_GREETING_RESP_COND_BYE /* when connection is refused */ +}; + +/* + mailimap_greeting is the response returned on connection + + - type is the type of response on connection, either + MAILIMAP_GREETING_RESP_COND_AUTH if connection is accepted or + MAIMIMAP_GREETING_RESP_COND_BYE if connection is refused +*/ + +struct mailimap_greeting { + int gr_type; + union { + struct mailimap_resp_cond_auth * gr_auth; /* can be NULL */ + struct mailimap_resp_cond_bye * gr_bye; /* can be NULL */ + } gr_data; +}; + +LIBETPAN_EXPORT +struct mailimap_greeting * +mailimap_greeting_new(int gr_type, + struct mailimap_resp_cond_auth * gr_auth, + struct mailimap_resp_cond_bye * gr_bye); + +LIBETPAN_EXPORT +void mailimap_greeting_free(struct mailimap_greeting * greeting); + + +/* + mailimap_header_list is a list of headers that can be specified when + we want to fetch fields + + - list is a list of header names, each header name should be allocated + with malloc() +*/ + +struct mailimap_header_list { + clist * hdr_list; /* list of astring (char *), != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_header_list * +mailimap_header_list_new(clist * hdr_list); + +LIBETPAN_EXPORT +void +mailimap_header_list_free(struct mailimap_header_list * header_list); + + + +/* this is the type of mailbox STATUS that can be returned */ + +enum { + MAILIMAP_STATUS_ATT_MESSAGES, /* when requesting the number of + messages */ + MAILIMAP_STATUS_ATT_RECENT, /* when requesting the number of + recent messages */ + MAILIMAP_STATUS_ATT_UIDNEXT, /* when requesting the next unique + identifier */ + MAILIMAP_STATUS_ATT_UIDVALIDITY, /* when requesting the validity of + message unique identifiers*/ + MAILIMAP_STATUS_ATT_UNSEEN, /* when requesting the number of + unseen messages */ + MAILIMAP_STATUS_ATT_HIGHESTMODSEQ, /* when requesting the highest + mod-sequence value of all messages in + the mailbox */ + MAILIMAP_STATUS_ATT_EXTENSION +}; + +/* + mailimap_status_info is a returned information when a STATUS of + a mailbox is requested + + - att is the type of mailbox STATUS, the value can be + MAILIMAP_STATUS_ATT_MESSAGES, MAILIMAP_STATUS_ATT_RECENT, + MAILIMAP_STATUS_ATT_UIDNEXT, MAILIMAP_STATUS_ATT_UIDVALIDITY, + MAILIMAP_STATUS_ATT_UNSEEN or MAILIMAP_STATUS_ATT_EXTENSION + + - value is the value of the given information + + - st_ext_data is the data of the extension. +*/ + +struct mailimap_status_info { + int st_att; + uint32_t st_value; + struct mailimap_extension_data * st_ext_data; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_status_info * + mailimap_status_info_new(int st_att, uint32_t st_value, + struct mailimap_extension_data * st_ext_data); + +LIBETPAN_EXPORT +void mailimap_status_info_free(struct mailimap_status_info * info); + + + +/* + mailimap_mailbox_data_status is the list of information returned + when a STATUS of a mailbox is requested + + - mailbox is the name of the mailbox, should be allocated with malloc() + + - status_info_list is the list of information returned +*/ + +struct mailimap_mailbox_data_status { + char * st_mailbox; + clist * st_info_list; /* list of (struct mailimap_status_info *) */ + /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_mailbox_data_status * +mailimap_mailbox_data_status_new(char * st_mailbox, + clist * st_info_list); + +LIBETPAN_EXPORT +void +mailimap_mailbox_data_status_free(struct mailimap_mailbox_data_status * info); + + + +/* this is the type of mailbox information that is returned */ + +enum { + MAILIMAP_MAILBOX_DATA_ERROR, /* on parse error */ + MAILIMAP_MAILBOX_DATA_FLAGS, /* flag that are applicable to the mailbox */ + MAILIMAP_MAILBOX_DATA_LIST, /* this is a mailbox in the list of mailboxes + returned on LIST command*/ + MAILIMAP_MAILBOX_DATA_LSUB, /* this is a mailbox in the list of + subscribed mailboxes returned on LSUB + command */ + MAILIMAP_MAILBOX_DATA_SEARCH, /* this is a list of messages numbers or + unique identifiers returned + on a SEARCH command*/ + MAILIMAP_MAILBOX_DATA_STATUS, /* this is the list of information returned + on a STATUS command */ + MAILIMAP_MAILBOX_DATA_EXISTS, /* this is the number of messages in the + mailbox */ + MAILIMAP_MAILBOX_DATA_RECENT, /* this is the number of recent messages + in the mailbox */ + MAILIMAP_MAILBOX_DATA_EXTENSION_DATA /* this mailbox-data stores data + returned by an extension */ +}; + +/* + mailimap_mailbox_data is an information related to a mailbox + + - type is the type of mailbox_data that is filled, the value of this field + can be MAILIMAP_MAILBOX_DATA_FLAGS, MAILIMAP_MAILBOX_DATA_LIST, + MAILIMAP_MAILBOX_DATA_LSUB, MAILIMAP_MAILBOX_DATA_SEARCH, + MAILIMAP_MAILBOX_DATA_STATUS, MAILIMAP_MAILBOX_DATA_EXISTS + or MAILIMAP_MAILBOX_DATA_RECENT. + + - flags is the flags that are applicable to the mailbox when + type is MAILIMAP_MAILBOX_DATA_FLAGS + + - list is a mailbox in the list of mailboxes returned on LIST command + when type is MAILIMAP_MAILBOX_DATA_LIST + + - lsub is a mailbox in the list of subscribed mailboxes returned on + LSUB command when type is MAILIMAP_MAILBOX_DATA_LSUB + + - search is a list of messages numbers or unique identifiers returned + on SEARCH command when type MAILIMAP_MAILBOX_DATA_SEARCH, each element + should be allocated with malloc() + + - status is a list of information returned on STATUS command when + type is MAILIMAP_MAILBOX_DATA_STATUS + + - exists is the number of messages in the mailbox when type + is MAILIMAP_MAILBOX_DATA_EXISTS + + - recent is the number of recent messages in the mailbox when type + is MAILIMAP_MAILBOX_DATA_RECENT +*/ + +struct mailimap_mailbox_data { + int mbd_type; + union { + struct mailimap_flag_list * mbd_flags; /* can be NULL */ + struct mailimap_mailbox_list * mbd_list; /* can be NULL */ + struct mailimap_mailbox_list * mbd_lsub; /* can be NULL */ + clist * mbd_search; /* list of nz-number (uint32_t *), can be NULL */ + struct mailimap_mailbox_data_status * mbd_status; /* can be NULL */ + uint32_t mbd_exists; + uint32_t mbd_recent; + struct mailimap_extension_data * mbd_extension; /* can be NULL */ + } mbd_data; +}; + +LIBETPAN_EXPORT +struct mailimap_mailbox_data * +mailimap_mailbox_data_new(int mbd_type, struct mailimap_flag_list * mbd_flags, + struct mailimap_mailbox_list * mbd_list, + struct mailimap_mailbox_list * mbd_lsub, + clist * mbd_search, + struct mailimap_mailbox_data_status * mbd_status, + uint32_t mbd_exists, + uint32_t mbd_recent, + struct mailimap_extension_data * mbd_extension); + +LIBETPAN_EXPORT +void +mailimap_mailbox_data_free(struct mailimap_mailbox_data * mb_data); + + + +/* this is the type of mailbox flags */ + +enum { + MAILIMAP_MBX_LIST_FLAGS_SFLAG, /* mailbox single flag - a flag in + {\NoSelect, \Marked, \Unmarked} */ + MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG /* mailbox other flag - mailbox flag + other than \NoSelect \Marked and + \Unmarked) */ +}; + +/* this is a single flag type */ + +enum { + MAILIMAP_MBX_LIST_SFLAG_ERROR, + MAILIMAP_MBX_LIST_SFLAG_MARKED, + MAILIMAP_MBX_LIST_SFLAG_NOSELECT, + MAILIMAP_MBX_LIST_SFLAG_UNMARKED +}; + +/* + mailimap_mbx_list_flags is a mailbox flag + + - type is the type of mailbox flag, it can be MAILIMAP_MBX_LIST_FLAGS_SFLAG, + or MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG. + + - oflags is a list of "mailbox other flag" + + - sflag is a mailbox single flag +*/ + +struct mailimap_mbx_list_flags { + int mbf_type; + clist * mbf_oflags; /* list of + (struct mailimap_mbx_list_oflag *), != NULL */ + int mbf_sflag; +}; + +LIBETPAN_EXPORT +struct mailimap_mbx_list_flags * +mailimap_mbx_list_flags_new(int mbf_type, + clist * mbf_oflags, int mbf_sflag); + +LIBETPAN_EXPORT +void +mailimap_mbx_list_flags_free(struct mailimap_mbx_list_flags * mbx_list_flags); + + + +/* this is the type of the mailbox other flag */ + +enum { + MAILIMAP_MBX_LIST_OFLAG_ERROR, /* on parse error */ + MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS, /* \NoInferior flag */ + MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT /* other flag */ +}; + +/* + mailimap_mbx_list_oflag is a mailbox other flag + + - type can be MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS when this is + a \NoInferior flag or MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT + + - flag_ext is set when MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT and is + an extension flag, should be allocated with malloc() +*/ + +struct mailimap_mbx_list_oflag { + int of_type; + char * of_flag_ext; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_mbx_list_oflag * +mailimap_mbx_list_oflag_new(int of_type, char * of_flag_ext); + +LIBETPAN_EXPORT +void +mailimap_mbx_list_oflag_free(struct mailimap_mbx_list_oflag * oflag); + + + +/* + mailimap_mailbox_list is a list of mailbox flags + + - mb_flag is a list of mailbox flags + + - delimiter is the delimiter of the mailbox path + + - mb is the name of the mailbox, should be allocated with malloc() +*/ + +struct mailimap_mailbox_list { + struct mailimap_mbx_list_flags * mb_flag; /* can be NULL */ + char mb_delimiter; + char * mb_name; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_mailbox_list * +mailimap_mailbox_list_new(struct mailimap_mbx_list_flags * mbx_flags, + char mb_delimiter, char * mb_name); + +LIBETPAN_EXPORT +void +mailimap_mailbox_list_free(struct mailimap_mailbox_list * mb_list); + + + +/* this is the MIME type */ + +enum { + MAILIMAP_MEDIA_BASIC_APPLICATION, /* application/xxx */ + MAILIMAP_MEDIA_BASIC_AUDIO, /* audio/xxx */ + MAILIMAP_MEDIA_BASIC_IMAGE, /* image/xxx */ + MAILIMAP_MEDIA_BASIC_MESSAGE, /* message/xxx */ + MAILIMAP_MEDIA_BASIC_VIDEO, /* video/xxx */ + MAILIMAP_MEDIA_BASIC_OTHER /* for all other cases */ +}; + + +/* + mailimap_media_basic is the MIME type + + - type can be MAILIMAP_MEDIA_BASIC_APPLICATION, MAILIMAP_MEDIA_BASIC_AUDIO, + MAILIMAP_MEDIA_BASIC_IMAGE, MAILIMAP_MEDIA_BASIC_MESSAGE, + MAILIMAP_MEDIA_BASIC_VIDEO or MAILIMAP_MEDIA_BASIC_OTHER + + - basic_type is defined when type is MAILIMAP_MEDIA_BASIC_OTHER, should + be allocated with malloc() + + - subtype is the subtype of the MIME type, for example, this is + "data" in "application/data", should be allocated with malloc() +*/ + +struct mailimap_media_basic { + int med_type; + char * med_basic_type; /* can be NULL */ + char * med_subtype; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_media_basic * +mailimap_media_basic_new(int med_type, + char * med_basic_type, char * med_subtype); + +LIBETPAN_EXPORT +void +mailimap_media_basic_free(struct mailimap_media_basic * media_basic); + + + +/* this is the type of message data */ + +enum { + MAILIMAP_MESSAGE_DATA_ERROR, + MAILIMAP_MESSAGE_DATA_EXPUNGE, + MAILIMAP_MESSAGE_DATA_FETCH +}; + +/* + mailimap_message_data is an information related to a message + + - number is the number or the unique identifier of the message + + - type is the type of information, this value can be + MAILIMAP_MESSAGE_DATA_EXPUNGE or MAILIMAP_MESSAGE_DATA_FETCH + + - msg_att is the message data +*/ + +struct mailimap_message_data { + uint32_t mdt_number; + int mdt_type; + struct mailimap_msg_att * mdt_msg_att; /* can be NULL */ + /* if type = EXPUNGE, can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_message_data * +mailimap_message_data_new(uint32_t mdt_number, int mdt_type, + struct mailimap_msg_att * mdt_msg_att); + +LIBETPAN_EXPORT +void +mailimap_message_data_free(struct mailimap_message_data * msg_data); + + + +/* this the type of the message attributes */ + +enum { + MAILIMAP_MSG_ATT_ITEM_ERROR, /* on parse error */ + MAILIMAP_MSG_ATT_ITEM_DYNAMIC, /* dynamic message attributes (flags) */ + MAILIMAP_MSG_ATT_ITEM_STATIC, /* static messages attributes + (message content) */ + MAILIMAP_MSG_ATT_ITEM_EXTENSION /* extension data */ +}; + +/* + mailimap_msg_att_item is a message attribute + + - type is the type of message attribute, the value can be + MAILIMAP_MSG_ATT_ITEM_DYNAMIC, MAILIMAP_MSG_ATT_ITEM_STATIC or MAILIMAP_MSG_ATT_ITEM_EXTENSION + + - att_dyn is a dynamic message attribute when type is + MAILIMAP_MSG_ATT_ITEM_DYNAMIC + + - att_static is a static message attribute when type is + MAILIMAP_MSG_ATT_ITEM_STATIC + + - att_extension_data is an extension data. +*/ + +struct mailimap_msg_att_item { + int att_type; + union { + struct mailimap_msg_att_dynamic * att_dyn; /* can be NULL */ + struct mailimap_msg_att_static * att_static; /* can be NULL */ + struct mailimap_extension_data * att_extension_data; /* can be NULL */ + } att_data; +}; + +LIBETPAN_EXPORT +struct mailimap_msg_att_item * +mailimap_msg_att_item_new(int att_type, + struct mailimap_msg_att_dynamic * att_dyn, + struct mailimap_msg_att_static * att_static, + struct mailimap_extension_data * att_extension_data); + +LIBETPAN_EXPORT +void +mailimap_msg_att_item_free(struct mailimap_msg_att_item * item); + + +/* + mailimap_msg_att is a list of attributes + + - list is a list of message attributes + + - number is the message number or unique identifier, this field + has been added for implementation purpose +*/ + +struct mailimap_msg_att { + clist * att_list; /* list of (struct mailimap_msg_att_item *) */ + /* != NULL */ + uint32_t att_number; /* extra field to store the message number, + used for mailimap */ +}; + +LIBETPAN_EXPORT +struct mailimap_msg_att * mailimap_msg_att_new(clist * att_list); + +LIBETPAN_EXPORT +void mailimap_msg_att_free(struct mailimap_msg_att * msg_att); + + +/* + mailimap_msg_att_dynamic is a dynamic message attribute + + - list is a list of flags (that have been fetched) +*/ + +struct mailimap_msg_att_dynamic { + clist * att_list; /* list of (struct mailimap_flag_fetch *) */ + /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_msg_att_dynamic * +mailimap_msg_att_dynamic_new(clist * att_list); + +LIBETPAN_EXPORT +void +mailimap_msg_att_dynamic_free(struct mailimap_msg_att_dynamic * msg_att_dyn); + + + +/* + mailimap_msg_att_body_section is a MIME part content + + - section is the location of the MIME part in the message + + - origin_octet is the offset of the requested part of the MIME part + + - body_part is the content or partial content of the MIME part, + should be allocated through a MMAPString + + - length is the size of the content +*/ + +struct mailimap_msg_att_body_section { + struct mailimap_section * sec_section; /* != NULL */ + uint32_t sec_origin_octet; + char * sec_body_part; /* can be NULL */ + size_t sec_length; +}; + +LIBETPAN_EXPORT +struct mailimap_msg_att_body_section * +mailimap_msg_att_body_section_new(struct mailimap_section * section, + uint32_t sec_origin_octet, + char * sec_body_part, + size_t sec_length); + +LIBETPAN_EXPORT +void +mailimap_msg_att_body_section_free(struct mailimap_msg_att_body_section * + msg_att_body_section); + + + +/* + this is the type of static message attribute +*/ + +enum { + MAILIMAP_MSG_ATT_ERROR, /* on parse error */ + MAILIMAP_MSG_ATT_ENVELOPE, /* this is the fields that can be + parsed by the server */ + MAILIMAP_MSG_ATT_INTERNALDATE, /* this is the message date kept + by the server */ + MAILIMAP_MSG_ATT_RFC822, /* this is the message content + (header and body) */ + MAILIMAP_MSG_ATT_RFC822_HEADER, /* this is the message header */ + MAILIMAP_MSG_ATT_RFC822_TEXT, /* this is the message text part */ + MAILIMAP_MSG_ATT_RFC822_SIZE, /* this is the size of the message content */ + MAILIMAP_MSG_ATT_BODY, /* this is the MIME description of + the message */ + MAILIMAP_MSG_ATT_BODYSTRUCTURE, /* this is the MIME description of the + message with additional information */ + MAILIMAP_MSG_ATT_BODY_SECTION, /* this is a MIME part content */ + MAILIMAP_MSG_ATT_UID /* this is the message unique identifier */ +}; + +/* + mailimap_msg_att_static is a given part of the message + + - type is the type of the static message attribute, the value can be + MAILIMAP_MSG_ATT_ENVELOPE, MAILIMAP_MSG_ATT_INTERNALDATE, + MAILIMAP_MSG_ATT_RFC822, MAILIMAP_MSG_ATT_RFC822_HEADER, + MAILIMAP_MSG_ATT_RFC822_TEXT, MAILIMAP_MSG_ATT_RFC822_SIZE, + MAILIMAP_MSG_ATT_BODY, MAILIMAP_MSG_ATT_BODYSTRUCTURE, + MAILIMAP_MSG_ATT_BODY_SECTION, MAILIMAP_MSG_ATT_UID + + - env is the headers parsed by the server if type is + MAILIMAP_MSG_ATT_ENVELOPE + + - internal_date is the date of message kept by the server if type is + MAILIMAP_MSG_ATT_INTERNALDATE + + - rfc822 is the message content if type is MAILIMAP_MSG_ATT_RFC822, + should be allocated through a MMAPString + + - rfc822_header is the message header if type is + MAILIMAP_MSG_ATT_RFC822_HEADER, should be allocated through a MMAPString + + - rfc822_text is the message text part if type is + MAILIMAP_MSG_ATT_RFC822_TEXT, should be allocated through a MMAPString + + - rfc822_size is the message size if type is MAILIMAP_MSG_ATT_SIZE + + - body is the MIME description of the message + + - bodystructure is the MIME description of the message with additional + information + + - body_section is a MIME part content + + - uid is a unique message identifier +*/ + +struct mailimap_msg_att_static { + int att_type; + union { + struct mailimap_envelope * att_env; /* can be NULL */ + struct mailimap_date_time * att_internal_date; /* can be NULL */ + struct { + char * att_content; /* can be NULL */ + size_t att_length; + } att_rfc822; + struct { + char * att_content; /* can be NULL */ + size_t att_length; + } att_rfc822_header; + struct { + char * att_content; /* can be NULL */ + size_t att_length; + } att_rfc822_text; + uint32_t att_rfc822_size; + struct mailimap_body * att_bodystructure; /* can be NULL */ + struct mailimap_body * att_body; /* can be NULL */ + struct mailimap_msg_att_body_section * att_body_section; /* can be NULL */ + uint32_t att_uid; + } att_data; +}; + +LIBETPAN_EXPORT +struct mailimap_msg_att_static * +mailimap_msg_att_static_new(int att_type, struct mailimap_envelope * att_env, + struct mailimap_date_time * att_internal_date, + char * att_rfc822, + char * att_rfc822_header, + char * att_rfc822_text, + size_t att_length, + uint32_t att_rfc822_size, + struct mailimap_body * att_bodystructure, + struct mailimap_body * att_body, + struct mailimap_msg_att_body_section * att_body_section, + uint32_t att_uid); + +LIBETPAN_EXPORT +void +mailimap_msg_att_static_free(struct mailimap_msg_att_static * item); + + + +/* this is the type of a response element */ + +enum { + MAILIMAP_RESP_ERROR, /* on parse error */ + MAILIMAP_RESP_CONT_REQ, /* continuation request */ + MAILIMAP_RESP_RESP_DATA /* response data */ +}; + +/* + mailimap_cont_req_or_resp_data is a response element + + - type is the type of response, the value can be MAILIMAP_RESP_CONT_REQ + or MAILIMAP_RESP_RESP_DATA + + - cont_req is a continuation request + + - resp_data is a response data +*/ + +struct mailimap_cont_req_or_resp_data { + int rsp_type; + union { + struct mailimap_continue_req * rsp_cont_req; /* can be NULL */ + struct mailimap_response_data * rsp_resp_data; /* can be NULL */ + } rsp_data; +}; + +LIBETPAN_EXPORT +struct mailimap_cont_req_or_resp_data * +mailimap_cont_req_or_resp_data_new(int rsp_type, + struct mailimap_continue_req * rsp_cont_req, + struct mailimap_response_data * rsp_resp_data); + +LIBETPAN_EXPORT +void +mailimap_cont_req_or_resp_data_free(struct mailimap_cont_req_or_resp_data * + cont_req_or_resp_data); + + +/* + mailimap_response is a list of response elements + + - cont_req_or_resp_data_list is a list of response elements + + - resp_done is an ending response element +*/ + +struct mailimap_response { + clist * rsp_cont_req_or_resp_data_list; + /* list of (struct mailiap_cont_req_or_resp_data *) */ + /* can be NULL */ + struct mailimap_response_done * rsp_resp_done; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_response * +mailimap_response_new(clist * rsp_cont_req_or_resp_data_list, + struct mailimap_response_done * rsp_resp_done); + +LIBETPAN_EXPORT +void +mailimap_response_free(struct mailimap_response * resp); + + + +/* this is the type of an untagged response */ + +enum { + MAILIMAP_RESP_DATA_TYPE_ERROR, /* on parse error */ + MAILIMAP_RESP_DATA_TYPE_COND_STATE, /* condition state response */ + MAILIMAP_RESP_DATA_TYPE_COND_BYE, /* BYE response (server is about + to close the connection) */ + MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA, /* response related to a mailbox */ + MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA, /* response related to a message */ + MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA, /* capability information */ + MAILIMAP_RESP_DATA_TYPE_EXTENSION_DATA /* data parsed by extension */ +}; + +/* + mailimap_reponse_data is an untagged response + + - type is the type of the untagged response, it can be + MAILIMAP_RESP_DATA_COND_STATE, MAILIMAP_RESP_DATA_COND_BYE, + MAILIMAP_RESP_DATA_MAILBOX_DATA, MAILIMAP_RESP_DATA_MESSAGE_DATA + or MAILIMAP_RESP_DATA_CAPABILITY_DATA + + - cond_state is a condition state response + + - bye is a BYE response (server is about to close the connection) + + - mailbox_data is a response related to a mailbox + + - message_data is a response related to a message + + - capability is information about capabilities +*/ + +struct mailimap_response_data { + int rsp_type; + union { + struct mailimap_resp_cond_state * rsp_cond_state; /* can be NULL */ + struct mailimap_resp_cond_bye * rsp_bye; /* can be NULL */ + struct mailimap_mailbox_data * rsp_mailbox_data; /* can be NULL */ + struct mailimap_message_data * rsp_message_data; /* can be NULL */ + struct mailimap_capability_data * rsp_capability_data; /* can be NULL */ + struct mailimap_extension_data * rsp_extension_data; /* can be NULL */ + } rsp_data; +}; + +LIBETPAN_EXPORT +struct mailimap_response_data * +mailimap_response_data_new(int rsp_type, + struct mailimap_resp_cond_state * rsp_cond_state, + struct mailimap_resp_cond_bye * rsp_bye, + struct mailimap_mailbox_data * rsp_mailbox_data, + struct mailimap_message_data * rsp_message_data, + struct mailimap_capability_data * rsp_capability_data, + struct mailimap_extension_data * rsp_extension_data); + +LIBETPAN_EXPORT +void +mailimap_response_data_free(struct mailimap_response_data * resp_data); + + + +/* this is the type of an ending response */ + +enum { + MAILIMAP_RESP_DONE_TYPE_ERROR, /* on parse error */ + MAILIMAP_RESP_DONE_TYPE_TAGGED, /* tagged response */ + MAILIMAP_RESP_DONE_TYPE_FATAL /* fatal error response */ +}; + +/* + mailimap_response_done is an ending response + + - type is the type of the ending response + + - tagged is a tagged response + + - fatal is a fatal error response +*/ + +struct mailimap_response_done { + int rsp_type; + union { + struct mailimap_response_tagged * rsp_tagged; /* can be NULL */ + struct mailimap_response_fatal * rsp_fatal; /* can be NULL */ + } rsp_data; +}; + +LIBETPAN_EXPORT +struct mailimap_response_done * +mailimap_response_done_new(int rsp_type, + struct mailimap_response_tagged * rsp_tagged, + struct mailimap_response_fatal * rsp_fatal); + +LIBETPAN_EXPORT +void mailimap_response_done_free(struct mailimap_response_done * + resp_done); + + +/* + mailimap_response_fatal is a fatal error response + + - bye is a BYE response text +*/ + +struct mailimap_response_fatal { + struct mailimap_resp_cond_bye * rsp_bye; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_response_fatal * +mailimap_response_fatal_new(struct mailimap_resp_cond_bye * rsp_bye); + +LIBETPAN_EXPORT +void mailimap_response_fatal_free(struct mailimap_response_fatal * resp_fatal); + + + +/* + mailimap_response_tagged is a tagged response + + - tag is the sent tag, should be allocated with malloc() + + - cond_state is a condition state response +*/ + +struct mailimap_response_tagged { + char * rsp_tag; /* != NULL */ + struct mailimap_resp_cond_state * rsp_cond_state; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_response_tagged * +mailimap_response_tagged_new(char * rsp_tag, + struct mailimap_resp_cond_state * rsp_cond_state); + +LIBETPAN_EXPORT +void +mailimap_response_tagged_free(struct mailimap_response_tagged * tagged); + + +/* this is the type of an authentication condition response */ + +enum { + MAILIMAP_RESP_COND_AUTH_ERROR, /* on parse error */ + MAILIMAP_RESP_COND_AUTH_OK, /* authentication is needed */ + MAILIMAP_RESP_COND_AUTH_PREAUTH /* authentication is not needed */ +}; + +/* + mailimap_resp_cond_auth is an authentication condition response + + - type is the type of the authentication condition response, + the value can be MAILIMAP_RESP_COND_AUTH_OK or + MAILIMAP_RESP_COND_AUTH_PREAUTH + + - text is a text response +*/ + +struct mailimap_resp_cond_auth { + int rsp_type; + struct mailimap_resp_text * rsp_text; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_resp_cond_auth * +mailimap_resp_cond_auth_new(int rsp_type, + struct mailimap_resp_text * rsp_text); + +LIBETPAN_EXPORT +void +mailimap_resp_cond_auth_free(struct mailimap_resp_cond_auth * cond_auth); + + + +/* + mailimap_resp_cond_bye is a BYE response + + - text is a text response +*/ + +struct mailimap_resp_cond_bye { + struct mailimap_resp_text * rsp_text; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_resp_cond_bye * +mailimap_resp_cond_bye_new(struct mailimap_resp_text * rsp_text); + +LIBETPAN_EXPORT +void +mailimap_resp_cond_bye_free(struct mailimap_resp_cond_bye * cond_bye); + + + +/* this is the type of a condition state response */ + +enum { + MAILIMAP_RESP_COND_STATE_OK, + MAILIMAP_RESP_COND_STATE_NO, + MAILIMAP_RESP_COND_STATE_BAD +}; + +/* + mailimap_resp_cond_state is a condition state response + + - type is the type of the condition state response + + - text is a text response +*/ + +struct mailimap_resp_cond_state { + int rsp_type; + struct mailimap_resp_text * rsp_text; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_resp_cond_state * +mailimap_resp_cond_state_new(int rsp_type, + struct mailimap_resp_text * rsp_text); + +LIBETPAN_EXPORT +void +mailimap_resp_cond_state_free(struct mailimap_resp_cond_state * cond_state); + + + +/* + mailimap_resp_text is a text response + + - resp_code is a response code + + - text is a human readable text, should be allocated with malloc() +*/ + +struct mailimap_resp_text { + struct mailimap_resp_text_code * rsp_code; /* can be NULL */ + char * rsp_text; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_resp_text * +mailimap_resp_text_new(struct mailimap_resp_text_code * resp_code, + char * rsp_text); + +LIBETPAN_EXPORT +void mailimap_resp_text_free(struct mailimap_resp_text * resp_text); + + + +/* this is the type of the response code */ + +enum { + MAILIMAP_RESP_TEXT_CODE_ALERT, /* ALERT response */ + MAILIMAP_RESP_TEXT_CODE_BADCHARSET, /* BADCHARSET response */ + MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA, /* CAPABILITY response */ + MAILIMAP_RESP_TEXT_CODE_PARSE, /* PARSE response */ + MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS, /* PERMANENTFLAGS response */ + MAILIMAP_RESP_TEXT_CODE_READ_ONLY, /* READONLY response */ + MAILIMAP_RESP_TEXT_CODE_READ_WRITE, /* READWRITE response */ + MAILIMAP_RESP_TEXT_CODE_TRY_CREATE, /* TRYCREATE response */ + MAILIMAP_RESP_TEXT_CODE_UIDNEXT, /* UIDNEXT response */ + MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY, /* UIDVALIDITY response */ + MAILIMAP_RESP_TEXT_CODE_UNSEEN, /* UNSEEN response */ + MAILIMAP_RESP_TEXT_CODE_OTHER, /* other type of response */ + MAILIMAP_RESP_TEXT_CODE_EXTENSION /* extension response */ +}; + +/* + mailimap_resp_text_code is a response code + + - type is the type of the response code, the value can be + MAILIMAP_RESP_TEXT_CODE_ALERT, MAILIMAP_RESP_TEXT_CODE_BADCHARSET, + MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA, MAILIMAP_RESP_TEXT_CODE_PARSE, + MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS, MAILIMAP_RESP_TEXT_CODE_READ_ONLY, + MAILIMAP_RESP_TEXT_CODE_READ_WRITE, MAILIMAP_RESP_TEXT_CODE_TRY_CREATE, + MAILIMAP_RESP_TEXT_CODE_UIDNEXT, MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY, + MAILIMAP_RESP_TEXT_CODE_UNSEEN or MAILIMAP_RESP_TEXT_CODE_OTHER + + - badcharset is a list of charsets if type + is MAILIMAP_RESP_TEXT_CODE_BADCHARSET, each element should be + allocated with malloc() + + - cap_data is a list of capabilities + + - perm_flags is a list of flags, this is the flags that can be changed + permanently on the messages of the mailbox. + + - uidnext is the next unique identifier of a message + + - uidvalidity is the unique identifier validity value + + - first_unseen is the number of the first message without the \Seen flag + + - atom is a keyword for an extension response code, should be allocated + with malloc() + + - atom_value is the data related with the extension response code, + should be allocated with malloc() +*/ + +struct mailimap_resp_text_code { + int rc_type; + union { + clist * rc_badcharset; /* list of astring (char *) */ + /* can be NULL */ + struct mailimap_capability_data * rc_cap_data; /* != NULL */ + clist * rc_perm_flags; /* list of (struct mailimap_flag_perm *) */ + /* can be NULL */ + uint32_t rc_uidnext; + uint32_t rc_uidvalidity; + uint32_t rc_first_unseen; + struct { + char * atom_name; /* can be NULL */ + char * atom_value; /* can be NULL */ + } rc_atom; + struct mailimap_extension_data * rc_ext_data; /* can be NULL */ + } rc_data; +}; + +LIBETPAN_EXPORT +struct mailimap_resp_text_code * +mailimap_resp_text_code_new(int rc_type, clist * rc_badcharset, + struct mailimap_capability_data * rc_cap_data, + clist * rc_perm_flags, + uint32_t rc_uidnext, uint32_t rc_uidvalidity, + uint32_t rc_first_unseen, char * rc_atom, char * rc_atom_value, + struct mailimap_extension_data * rc_ext_data); + +LIBETPAN_EXPORT +void +mailimap_resp_text_code_free(struct mailimap_resp_text_code * resp_text_code); + + +/* + mailimap_section is a MIME part section identifier + + section_spec is the MIME section identifier +*/ + +struct mailimap_section { + struct mailimap_section_spec * sec_spec; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new(struct mailimap_section_spec * sec_spec); + +LIBETPAN_EXPORT +void mailimap_section_free(struct mailimap_section * section); + + +/* this is the type of the message/rfc822 part description */ + +enum { + MAILIMAP_SECTION_MSGTEXT_HEADER, /* header fields part of the + message */ + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, /* given header fields of the + message */ + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT, /* header fields of the + message except the given */ + MAILIMAP_SECTION_MSGTEXT_TEXT /* text part */ +}; + +/* + mailimap_section_msgtext is a message/rfc822 part description + + - type is the type of the content part and the value can be + MAILIMAP_SECTION_MSGTEXT_HEADER, MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT + or MAILIMAP_SECTION_MSGTEXT_TEXT + + - header_list is the list of headers when type is + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS or + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT +*/ + +struct mailimap_section_msgtext { + int sec_type; + struct mailimap_header_list * sec_header_list; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_section_msgtext * +mailimap_section_msgtext_new(int sec_type, + struct mailimap_header_list * sec_header_list); + +LIBETPAN_EXPORT +void +mailimap_section_msgtext_free(struct mailimap_section_msgtext * msgtext); + + + +/* + mailimap_section_part is the MIME part location in a message + + - section_id is a list of number index of the sub-part in the mail structure, + each element should be allocated with malloc() + +*/ + +struct mailimap_section_part { + clist * sec_id; /* list of nz-number (uint32_t *) */ + /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_section_part * +mailimap_section_part_new(clist * sec_id); + +LIBETPAN_EXPORT +void +mailimap_section_part_free(struct mailimap_section_part * section_part); + + + +/* this is the type of section specification */ + +enum { + MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT, /* if requesting data of the root + MIME message/rfc822 part */ + MAILIMAP_SECTION_SPEC_SECTION_PART /* location of the MIME part + in the message */ +}; + +/* + mailimap_section_spec is a section specification + + - type is the type of the section specification, the value can be + MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT or + MAILIMAP_SECTION_SPEC_SECTION_PART + + - section_msgtext is a message/rfc822 part description if type is + MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT + + - section_part is a body part location in the message if type is + MAILIMAP_SECTION_SPEC_SECTION_PART + + - section_text is a body part location for a given MIME part, + this can be NULL if the body of the part is requested (and not + the MIME header). +*/ + +struct mailimap_section_spec { + int sec_type; + union { + struct mailimap_section_msgtext * sec_msgtext; /* can be NULL */ + struct mailimap_section_part * sec_part; /* can be NULL */ + } sec_data; + struct mailimap_section_text * sec_text; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_section_spec * +mailimap_section_spec_new(int sec_type, + struct mailimap_section_msgtext * sec_msgtext, + struct mailimap_section_part * sec_part, + struct mailimap_section_text * sec_text); + +LIBETPAN_EXPORT +void +mailimap_section_spec_free(struct mailimap_section_spec * section_spec); + + + +/* this is the type of body part location for a given MIME part */ + +enum { + MAILIMAP_SECTION_TEXT_ERROR, /* on parse error **/ + MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT, /* if the MIME type is + message/rfc822, headers or text + can be requested */ + MAILIMAP_SECTION_TEXT_MIME /* for all MIME types, + MIME headers can be requested */ +}; + +/* + mailimap_section_text is the body part location for a given MIME part + + - type can be MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT or + MAILIMAP_SECTION_TEXT_MIME + + - section_msgtext is the part of the MIME part when MIME type is + message/rfc822 than can be requested, when type is + MAILIMAP_TEXT_SECTION_MSGTEXT +*/ + +struct mailimap_section_text { + int sec_type; + struct mailimap_section_msgtext * sec_msgtext; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_section_text * +mailimap_section_text_new(int sec_type, + struct mailimap_section_msgtext * sec_msgtext); + +LIBETPAN_EXPORT +void +mailimap_section_text_free(struct mailimap_section_text * section_text); + + + + + + + + + + +/* ************************************************************************* */ +/* the following part concerns only the IMAP command that are sent */ + + +/* + mailimap_set_item is a message set + + - first is the first message of the set + - last is the last message of the set + + this can be message numbers of message unique identifiers +*/ + +struct mailimap_set_item { + uint32_t set_first; + uint32_t set_last; +}; + +LIBETPAN_EXPORT +struct mailimap_set_item * +mailimap_set_item_new(uint32_t set_first, uint32_t set_last); + +LIBETPAN_EXPORT +void mailimap_set_item_free(struct mailimap_set_item * set_item); + + + +/* + set is a list of message sets + + - list is a list of message sets +*/ + +struct mailimap_set { + clist * set_list; /* list of (struct mailimap_set_item *) */ +}; + +LIBETPAN_EXPORT +struct mailimap_set * mailimap_set_new(clist * list); + +LIBETPAN_EXPORT +void mailimap_set_free(struct mailimap_set * set); + + +/* + mailimap_date is a date + + - day is the day in the month (1 to 31) + + - month (1 to 12) + + - year (4 digits) +*/ + +struct mailimap_date { + int dt_day; + int dt_month; + int dt_year; +}; + +LIBETPAN_EXPORT +struct mailimap_date * +mailimap_date_new(int dt_day, int dt_month, int dt_year); + +LIBETPAN_EXPORT +void mailimap_date_free(struct mailimap_date * date); + + + + +/* this is the type of fetch attribute for a given message */ + +enum { + MAILIMAP_FETCH_ATT_ENVELOPE, /* to fetch the headers parsed by + the IMAP server */ + MAILIMAP_FETCH_ATT_FLAGS, /* to fetch the flags */ + MAILIMAP_FETCH_ATT_INTERNALDATE, /* to fetch the date of the message + kept by the server */ + MAILIMAP_FETCH_ATT_RFC822, /* to fetch the entire message */ + MAILIMAP_FETCH_ATT_RFC822_HEADER, /* to fetch the headers */ + MAILIMAP_FETCH_ATT_RFC822_SIZE, /* to fetch the size */ + MAILIMAP_FETCH_ATT_RFC822_TEXT, /* to fetch the text part */ + MAILIMAP_FETCH_ATT_BODY, /* to fetch the MIME structure */ + MAILIMAP_FETCH_ATT_BODYSTRUCTURE, /* to fetch the MIME structure with + additional information */ + MAILIMAP_FETCH_ATT_UID, /* to fetch the unique identifier */ + MAILIMAP_FETCH_ATT_BODY_SECTION, /* to fetch a given part */ + MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION, /* to fetch a given part without + marking the message as read */ + MAILIMAP_FETCH_ATT_EXTENSION +}; + + +/* + mailimap_fetch_att is the description of the fetch attribute + + - type is the type of fetch attribute, the value can be + MAILIMAP_FETCH_ATT_ENVELOPE, MAILIMAP_FETCH_ATT_FLAGS, + MAILIMAP_FETCH_ATT_INTERNALDATE, MAILIMAP_FETCH_ATT_RFC822, + MAILIMAP_FETCH_ATT_RFC822_HEADER, MAILIMAP_FETCH_ATT_RFC822_SIZE, + MAILIMAP_FETCH_ATT_RFC822_TEXT, MAILIMAP_FETCH_ATT_BODY, + MAILIMAP_FETCH_ATT_BODYSTRUCTURE, MAILIMAP_FETCH_ATT_UID, + MAILIMAP_FETCH_ATT_BODY_SECTION, MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION, + MAILIMAP_FETCH_ATT_EXTENSION + + - section is the location of the part to fetch if type is + MAILIMAP_FETCH_ATT_BODY_SECTION or MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION + + - offset is the first byte to fetch in the given part + + - size is the maximum size of the part to fetch + + - att_extension: keyword to send when MAILIMAP_FETCH_ATT_EXTENSION is used +*/ + +struct mailimap_fetch_att { + int att_type; + struct mailimap_section * att_section; + uint32_t att_offset; + uint32_t att_size; + char * att_extension; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new(int att_type, struct mailimap_section * att_section, + uint32_t att_offset, uint32_t att_size, char * att_extension); + + +LIBETPAN_EXPORT +void mailimap_fetch_att_free(struct mailimap_fetch_att * fetch_att); + + +/* this is the type of a FETCH operation */ + +enum { + MAILIMAP_FETCH_TYPE_ALL, /* equivalent to (FLAGS INTERNALDATE + RFC822.SIZE ENVELOPE) */ + MAILIMAP_FETCH_TYPE_FULL, /* equivalent to (FLAGS INTERNALDATE + RFC822.SIZE ENVELOPE BODY) */ + MAILIMAP_FETCH_TYPE_FAST, /* equivalent to (FLAGS INTERNALDATE + RFC822.SIZE) */ + MAILIMAP_FETCH_TYPE_FETCH_ATT, /* when there is only of fetch + attribute */ + MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST /* when there is a list of fetch + attributes */ +}; + +/* + mailimap_fetch_type is the description of the FETCH operation + + - type can be MAILIMAP_FETCH_TYPE_ALL, MAILIMAP_FETCH_TYPE_FULL, + MAILIMAP_FETCH_TYPE_FAST, MAILIMAP_FETCH_TYPE_FETCH_ATT or + MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST + + - fetch_att is a fetch attribute if type is MAILIMAP_FETCH_TYPE_FETCH_ATT + + - fetch_att_list is a list of fetch attributes if type is + MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST +*/ + +struct mailimap_fetch_type { + int ft_type; + union { + struct mailimap_fetch_att * ft_fetch_att; + clist * ft_fetch_att_list; /* list of (struct mailimap_fetch_att *) */ + } ft_data; +}; + +LIBETPAN_EXPORT +struct mailimap_fetch_type * +mailimap_fetch_type_new(int ft_type, + struct mailimap_fetch_att * ft_fetch_att, + clist * ft_fetch_att_list); + + +LIBETPAN_EXPORT +void mailimap_fetch_type_free(struct mailimap_fetch_type * fetch_type); + + + +/* + mailimap_store_att_flags is the description of the STORE operation + (change flags of a message) + + - sign can be 0 (set flag), +1 (add flag) or -1 (remove flag) + + - silent has a value of 1 if the flags are changed with no server + response + + - flag_list is the list of flags to change +*/ + +struct mailimap_store_att_flags { + int fl_sign; + int fl_silent; + struct mailimap_flag_list * fl_flag_list; +}; + +LIBETPAN_EXPORT +struct mailimap_store_att_flags * +mailimap_store_att_flags_new(int fl_sign, int fl_silent, + struct mailimap_flag_list * fl_flag_list); + +LIBETPAN_EXPORT +void mailimap_store_att_flags_free(struct mailimap_store_att_flags * + store_att_flags); + + + +/* this is the condition of the SEARCH operation */ + +enum { + MAILIMAP_SEARCH_KEY_ALL, /* all messages */ + MAILIMAP_SEARCH_KEY_ANSWERED, /* messages with the flag \Answered */ + MAILIMAP_SEARCH_KEY_BCC, /* messages whose Bcc field contains the + given string */ + MAILIMAP_SEARCH_KEY_BEFORE, /* messages whose internal date is earlier + than the specified date */ + MAILIMAP_SEARCH_KEY_BODY, /* message that contains the given string + (in header and text parts) */ + MAILIMAP_SEARCH_KEY_CC, /* messages whose Cc field contains the + given string */ + MAILIMAP_SEARCH_KEY_DELETED, /* messages with the flag \Deleted */ + MAILIMAP_SEARCH_KEY_FLAGGED, /* messages with the flag \Flagged */ + MAILIMAP_SEARCH_KEY_FROM, /* messages whose From field contains the + given string */ + MAILIMAP_SEARCH_KEY_KEYWORD, /* messages with the flag keyword set */ + MAILIMAP_SEARCH_KEY_NEW, /* messages with the flag \Recent and not + the \Seen flag */ + MAILIMAP_SEARCH_KEY_OLD, /* messages that do not have the + \Recent flag set */ + MAILIMAP_SEARCH_KEY_ON, /* messages whose internal date is the + specified date */ + MAILIMAP_SEARCH_KEY_RECENT, /* messages with the flag \Recent */ + MAILIMAP_SEARCH_KEY_SEEN, /* messages with the flag \Seen */ + MAILIMAP_SEARCH_KEY_SINCE, /* messages whose internal date is later + than specified date */ + MAILIMAP_SEARCH_KEY_SUBJECT, /* messages whose Subject field contains the + given string */ + MAILIMAP_SEARCH_KEY_TEXT, /* messages whose text part contains the + given string */ + MAILIMAP_SEARCH_KEY_TO, /* messages whose To field contains the + given string */ + MAILIMAP_SEARCH_KEY_UNANSWERED, /* messages with no flag \Answered */ + MAILIMAP_SEARCH_KEY_UNDELETED, /* messages with no flag \Deleted */ + MAILIMAP_SEARCH_KEY_UNFLAGGED, /* messages with no flag \Flagged */ + MAILIMAP_SEARCH_KEY_UNKEYWORD, /* messages with no flag keyword */ + MAILIMAP_SEARCH_KEY_UNSEEN, /* messages with no flag \Seen */ + MAILIMAP_SEARCH_KEY_DRAFT, /* messages with no flag \Draft */ + MAILIMAP_SEARCH_KEY_HEADER, /* messages whose given field + contains the given string */ + MAILIMAP_SEARCH_KEY_LARGER, /* messages whose size is larger then + the given size */ + MAILIMAP_SEARCH_KEY_NOT, /* not operation of the condition */ + MAILIMAP_SEARCH_KEY_OR, /* or operation between two conditions */ + MAILIMAP_SEARCH_KEY_SENTBEFORE, /* messages whose date given in Date header + is earlier than the specified date */ + MAILIMAP_SEARCH_KEY_SENTON, /* messages whose date given in Date header + is the specified date */ + MAILIMAP_SEARCH_KEY_SENTSINCE, /* messages whose date given in Date header + is later than specified date */ + MAILIMAP_SEARCH_KEY_SMALLER, /* messages whose size is smaller than + the given size */ + MAILIMAP_SEARCH_KEY_UID, /* messages whose unique identifiers are + in the given range */ + MAILIMAP_SEARCH_KEY_UNDRAFT, /* messages with no flag \Draft */ + MAILIMAP_SEARCH_KEY_SET, /* messages whose number (or unique + identifiers in case of UID SEARCH) are + in the given range */ + MAILIMAP_SEARCH_KEY_MULTIPLE, /* the boolean operator between the + conditions is AND */ + MAILIMAP_SEARCH_KEY_MODSEQ, /* mod sequence */ + MAILIMAP_SEARCH_KEY_XGMTHRID, /* Gmail thread id */ + MAILIMAP_SEARCH_KEY_XGMMSGID, /* Gmail Message id */ + MAILIMAP_SEARCH_KEY_XGMRAW /* Gmail RAW expression */ +}; + +/* + mailimap_search_key is the condition on the messages to return + + - type is the type of the condition + + - bcc is the text to search in the Bcc field when type is + MAILIMAP_SEARCH_KEY_BCC, should be allocated with malloc() + + - before is a date when type is MAILIMAP_SEARCH_KEY_BEFORE + + - body is the text to search in the message when type is + MAILIMAP_SEARCH_KEY_BODY, should be allocated with malloc() + + - cc is the text to search in the Cc field when type is + MAILIMAP_SEARCH_KEY_CC, should be allocated with malloc() + + - from is the text to search in the From field when type is + MAILIMAP_SEARCH_KEY_FROM, should be allocated with malloc() + + - keyword is the keyword flag name when type is MAILIMAP_SEARCH_KEY_KEYWORD, + should be allocated with malloc() + + - on is a date when type is MAILIMAP_SEARCH_KEY_ON + + - since is a date when type is MAILIMAP_SEARCH_KEY_SINCE + + - subject is the text to search in the Subject field when type is + MAILIMAP_SEARCH_KEY_SUBJECT, should be allocated with malloc() + + - text is the text to search in the text part of the message when + type is MAILIMAP_SEARCH_KEY_TEXT, should be allocated with malloc() + + - to is the text to search in the To field when type is + MAILIMAP_SEARCH_KEY_TO, should be allocated with malloc() + + - unkeyword is the keyword flag name when type is + MAILIMAP_SEARCH_KEY_UNKEYWORD, should be allocated with malloc() + + - header_name is the header name when type is MAILIMAP_SEARCH_KEY_HEADER, + should be allocated with malloc() + + - header_value is the text to search in the given header when type is + MAILIMAP_SEARCH_KEY_HEADER, should be allocated with malloc() + + - larger is a size when type is MAILIMAP_SEARCH_KEY_LARGER + + - not is a condition when type is MAILIMAP_SEARCH_KEY_NOT + + - or1 is a condition when type is MAILIMAP_SEARCH_KEY_OR + + - or2 is a condition when type is MAILIMAP_SEARCH_KEY_OR + + - sentbefore is a date when type is MAILIMAP_SEARCH_KEY_SENTBEFORE + + - senton is a date when type is MAILIMAP_SEARCH_KEY_SENTON + + - sentsince is a date when type is MAILIMAP_SEARCH_KEY_SENTSINCE + + - smaller is a size when type is MAILIMAP_SEARCH_KEY_SMALLER + + - uid is a set of messages when type is MAILIMAP_SEARCH_KEY_UID + + - set is a set of messages when type is MAILIMAP_SEARCH_KEY_SET + + - xgmthrid is a number of the gmail thread id when type is MAILIMAP_SEARCH_KEY_XGMTHRID + use mailimap_search_key_new_xgmthrid() for this key + + - xgmmsgid is a gmail message id expression when type is MAILIMAP_SEARCH_KEY_XGMMSGID + use mailimap_search_key_new_xgmmsgid() for this key + + - xgmraw is a raw gmail search expression when type is MAILIMAP_SEARCH_KEY_XGMRAW + use mailimap_search_key_new_xgmraw() for this key + + - multiple is a set of message when type is MAILIMAP_SEARCH_KEY_MULTIPLE +*/ + +enum { + MAILIMAP_SEARCH_KEY_MODSEQ_ENTRY_TYPE_REQ_PRIV, + MAILIMAP_SEARCH_KEY_MODSEQ_ENTRY_TYPE_REQ_SHARED, + MAILIMAP_SEARCH_KEY_MODSEQ_ENTRY_TYPE_REQ_ALL, +}; + +struct mailimap_search_key { + int sk_type; + union { + char * sk_bcc; + struct mailimap_date * sk_before; + char * sk_body; + char * sk_cc; + char * sk_from; + char * sk_keyword; + struct mailimap_date * sk_on; + struct mailimap_date * sk_since; + char * sk_subject; + char * sk_text; + char * sk_to; + char * sk_unkeyword; + struct { + char * sk_header_name; + char * sk_header_value; + } sk_header; + uint32_t sk_larger; + struct mailimap_search_key * sk_not; + struct { + struct mailimap_search_key * sk_or1; + struct mailimap_search_key * sk_or2; + } sk_or; + struct mailimap_date * sk_sentbefore; + struct mailimap_date * sk_senton; + struct mailimap_date * sk_sentsince; + uint32_t sk_smaller; + struct mailimap_set * sk_uid; + struct mailimap_set * sk_set; + uint64_t sk_xgmthrid; + uint64_t sk_xgmmsgid; + char * sk_xgmraw; + clist * sk_multiple; /* list of (struct mailimap_search_key *) */ + struct { + struct mailimap_flag * sk_entry_name; + int sk_entry_type_req; + uint64_t sk_modseq_valzer; + } sk_modseq; + } sk_data; +}; + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new(int sk_type, + char * sk_bcc, struct mailimap_date * sk_before, char * sk_body, + char * sk_cc, char * sk_from, char * sk_keyword, + struct mailimap_date * sk_on, struct mailimap_date * sk_since, + char * sk_subject, char * sk_text, char * sk_to, + char * sk_unkeyword, char * sk_header_name, + char * sk_header_value, uint32_t sk_larger, + struct mailimap_search_key * sk_not, + struct mailimap_search_key * sk_or1, + struct mailimap_search_key * sk_or2, + struct mailimap_date * sk_sentbefore, + struct mailimap_date * sk_senton, + struct mailimap_date * sk_sentsince, + uint32_t sk_smaller, struct mailimap_set * sk_uid, + struct mailimap_set * sk_set, clist * sk_multiple); + +/* + this function creates a condition structure to match messages with + the given gmail thread id +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_xgmthrid(uint64_t sk_xgmthrid); + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_xgmmsgid(uint64_t sk_xgmmsgid); + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_xgmraw(char * sk_xgmraw); + +LIBETPAN_EXPORT +void mailimap_search_key_free(struct mailimap_search_key * key); + +/* + mailimap_status_att_list is a list of mailbox STATUS request type + + - list is a list of mailbox STATUS request type + (value of elements in the list can be MAILIMAP_STATUS_ATT_MESSAGES, + MAILIMAP_STATUS_ATT_RECENT, MAILIMAP_STATUS_ATT_UIDNEXT, + MAILIMAP_STATUS_ATT_UIDVALIDITY or MAILIMAP_STATUS_ATT_UNSEEN), + each element should be allocated with malloc() +*/ + +struct mailimap_status_att_list { + clist * att_list; /* list of (uint32_t *) */ +}; + +LIBETPAN_EXPORT +struct mailimap_status_att_list * +mailimap_status_att_list_new(clist * att_list); + +LIBETPAN_EXPORT +void mailimap_status_att_list_free(struct mailimap_status_att_list * + status_att_list); + + + + +/* internal use functions */ + + +LIBETPAN_EXPORT +uint32_t * mailimap_number_alloc_new(uint32_t number); + +LIBETPAN_EXPORT +void mailimap_number_alloc_free(uint32_t * pnumber); + + +LIBETPAN_EXPORT +void mailimap_addr_host_free(char * addr_host); + +LIBETPAN_EXPORT +void mailimap_addr_mailbox_free(char * addr_mailbox); + +LIBETPAN_EXPORT +void mailimap_addr_adl_free(char * addr_adl); + +LIBETPAN_EXPORT +void mailimap_addr_name_free(char * addr_name); + +LIBETPAN_EXPORT +void mailimap_astring_free(char * astring); + +LIBETPAN_EXPORT +void mailimap_atom_free(char * atom); + +LIBETPAN_EXPORT +void mailimap_auth_type_free(char * auth_type); + +LIBETPAN_EXPORT +void mailimap_base64_free(char * base64); + +LIBETPAN_EXPORT +void mailimap_body_fld_desc_free(char * body_fld_desc); + +LIBETPAN_EXPORT +void mailimap_body_fld_id_free(char * body_fld_id); + +LIBETPAN_EXPORT +void mailimap_body_fld_md5_free(char * body_fld_md5); + +LIBETPAN_EXPORT +void mailimap_body_fld_loc_free(char * body_fld_loc); + +LIBETPAN_EXPORT +void mailimap_env_date_free(char * date); + +LIBETPAN_EXPORT +void mailimap_env_in_reply_to_free(char * in_reply_to); + +LIBETPAN_EXPORT +void mailimap_env_message_id_free(char * message_id); + +LIBETPAN_EXPORT +void mailimap_env_subject_free(char * subject); + +LIBETPAN_EXPORT +void mailimap_flag_extension_free(char * flag_extension); + +LIBETPAN_EXPORT +void mailimap_flag_keyword_free(char * flag_keyword); + +LIBETPAN_EXPORT +void +mailimap_header_fld_name_free(char * header_fld_name); + +LIBETPAN_EXPORT +void mailimap_literal_free(char * literal); + +LIBETPAN_EXPORT +void mailimap_mailbox_free(char * mailbox); + +LIBETPAN_EXPORT +void +mailimap_mailbox_data_search_free(clist * data_search); + +LIBETPAN_EXPORT +void mailimap_media_subtype_free(char * media_subtype); + +LIBETPAN_EXPORT +void mailimap_media_text_free(char * media_text); + +LIBETPAN_EXPORT +void mailimap_msg_att_envelope_free(struct mailimap_envelope * env); + +LIBETPAN_EXPORT +void +mailimap_msg_att_internaldate_free(struct mailimap_date_time * date_time); + +LIBETPAN_EXPORT +void +mailimap_msg_att_rfc822_free(char * str); + +LIBETPAN_EXPORT +void +mailimap_msg_att_rfc822_header_free(char * str); + +LIBETPAN_EXPORT +void +mailimap_msg_att_rfc822_text_free(char * str); + +LIBETPAN_EXPORT +void +mailimap_msg_att_body_free(struct mailimap_body * body); + +LIBETPAN_EXPORT +void +mailimap_msg_att_bodystructure_free(struct mailimap_body * body); + +LIBETPAN_EXPORT +void mailimap_nstring_free(char * str); + +LIBETPAN_EXPORT +void +mailimap_string_free(char * str); + +LIBETPAN_EXPORT +void mailimap_tag_free(char * tag); + +LIBETPAN_EXPORT +void mailimap_text_free(char * text); + + + + + +/* IMAP connection */ + +/* this is the state of the IMAP connection */ + +enum { + MAILIMAP_STATE_DISCONNECTED, + MAILIMAP_STATE_NON_AUTHENTICATED, + MAILIMAP_STATE_AUTHENTICATED, + MAILIMAP_STATE_SELECTED, + MAILIMAP_STATE_LOGOUT +}; + +/* + mailimap is an IMAP connection + + - response is a human readable message returned with a response, + must be accessed read-only + + - stream is the connection with the IMAP server + + - stream_buffer is the buffer where the data to parse are stored + + - state is the state of IMAP connection + + - tag is the current tag being used in IMAP connection + + - response_buffer is the buffer for response messages + + - connection_info is the information returned in response + for the last command about the connection + + - selection_info is the information returned in response + for the last command about the current selected mailbox + + - response_info is the other information returned in response + for the last command +*/ + +typedef void mailimap_msg_att_handler(struct mailimap_msg_att * msg_att, void * context); + +typedef bool mailimap_msg_body_handler(int msg_att_type, struct mailimap_msg_att_body_section * section, + const char * bytes, size_t length, void * context); + +typedef struct mailimap mailimap; + +struct mailimap { + char * imap_response; + + /* internals */ + mailstream * imap_stream; + + size_t imap_progr_rate; + progress_function * imap_progr_fun; + + MMAPString * imap_stream_buffer; + MMAPString * imap_response_buffer; + + int imap_state; + int imap_tag; + + struct mailimap_connection_info * imap_connection_info; + struct mailimap_selection_info * imap_selection_info; + struct mailimap_response_info * imap_response_info; + + struct { + void * sasl_conn; + const char * sasl_server_fqdn; + const char * sasl_login; + const char * sasl_auth_name; + const char * sasl_password; + const char * sasl_realm; + void * sasl_secret; + } imap_sasl; + + time_t imap_idle_timestamp; + time_t imap_idle_maxdelay; + + mailprogress_function * imap_body_progress_fun; + mailprogress_function * imap_items_progress_fun; + void * imap_progress_context; + mailimap_msg_att_handler * imap_msg_att_handler; + void * imap_msg_att_handler_context; + mailimap_msg_body_handler * imap_msg_body_handler; + void * imap_msg_body_handler_context; + + time_t imap_timeout; + + void (* imap_logger)(mailimap * session, int log_type, const char * str, size_t size, void * context); + void * imap_logger_context; + + int is_163_workaround_enabled; + int is_rambler_workaround_enabled; + int is_qip_workaround_enabled; +}; + + + +/* + mailimap_connection_info is the information about the connection + + - capability is the list of capability of the IMAP server +*/ + +struct mailimap_connection_info { + struct mailimap_capability_data * imap_capability; +}; + +LIBETPAN_EXPORT +struct mailimap_connection_info * +mailimap_connection_info_new(void); + +LIBETPAN_EXPORT +void +mailimap_connection_info_free(struct mailimap_connection_info * conn_info); + + +/* this is the type of mailbox access */ + +enum { + MAILIMAP_MAILBOX_READONLY, + MAILIMAP_MAILBOX_READWRITE +}; + +/* + mailimap_selection_info is information about the current selected mailbox + + - perm_flags is a list of flags that can be changed permanently on the + messages of the mailbox + + - perm is the access on the mailbox, value can be + MAILIMAP_MAILBOX_READONLY or MAILIMAP_MAILBOX_READWRITE + + - uidnext is the next unique identifier + + - uidvalidity is the unique identifiers validity + + - first_unseen is the number of the first unseen message + + - flags is a list of flags that can be used on the messages of + the mailbox + + - exists is the number of messages in the mailbox + + - recent is the number of recent messages in the mailbox + + - unseen is the number of unseen messages in the mailbox +*/ + +struct mailimap_selection_info { + clist * sel_perm_flags; /* list of (struct flag_perm *) */ + int sel_perm; + uint32_t sel_uidnext; + uint32_t sel_uidvalidity; + uint32_t sel_first_unseen; + struct mailimap_flag_list * sel_flags; + uint32_t sel_exists; + uint32_t sel_recent; + uint32_t sel_unseen; + uint8_t sel_has_exists:1; + uint8_t sel_has_recent:1; +}; + +LIBETPAN_EXPORT +struct mailimap_selection_info * +mailimap_selection_info_new(void); + +LIBETPAN_EXPORT +void +mailimap_selection_info_free(struct mailimap_selection_info * sel_info); + + +/* + mailimap_response_info is the other information returned in the + response for a command + + - alert is the human readable text returned with ALERT response + + - parse is the human readable text returned with PARSE response + + - badcharset is a list of charset returned with a BADCHARSET response + + - trycreate is set to 1 if a trycreate response was returned + + - mailbox_list is a list of mailboxes + + - mailbox_lsub is a list of subscribed mailboxes + + - search_result is a list of message numbers or unique identifiers + + - status is a STATUS response + + - expunged is a list of message numbers + + - fetch_list is a list of fetch response +*/ + +struct mailimap_response_info { + char * rsp_alert; + char * rsp_parse; + clist * rsp_badcharset; /* list of (char *) */ + int rsp_trycreate; + clist * rsp_mailbox_list; /* list of (struct mailimap_mailbox_list *) */ + clist * rsp_mailbox_lsub; /* list of (struct mailimap_mailbox_list *) */ + clist * rsp_search_result; /* list of (uint32_t *) */ + struct mailimap_mailbox_data_status * rsp_status; + clist * rsp_expunged; /* list of (uint32_t 32 *) */ + clist * rsp_fetch_list; /* list of (struct mailimap_msg_att *) */ + clist * rsp_extension_list; /* list of (struct mailimap_extension_data *) */ + char * rsp_atom; + char * rsp_value; +}; + +LIBETPAN_EXPORT +struct mailimap_response_info * +mailimap_response_info_new(void); + +LIBETPAN_EXPORT +void +mailimap_response_info_free(struct mailimap_response_info * resp_info); + + +/* these are the possible returned error codes */ + +enum { + MAILIMAP_NO_ERROR = 0, + MAILIMAP_NO_ERROR_AUTHENTICATED = 1, + MAILIMAP_NO_ERROR_NON_AUTHENTICATED = 2, + MAILIMAP_ERROR_BAD_STATE, + MAILIMAP_ERROR_STREAM, + MAILIMAP_ERROR_PARSE, + MAILIMAP_ERROR_CONNECTION_REFUSED, + MAILIMAP_ERROR_MEMORY, + MAILIMAP_ERROR_FATAL, + MAILIMAP_ERROR_PROTOCOL, + MAILIMAP_ERROR_DONT_ACCEPT_CONNECTION, + MAILIMAP_ERROR_APPEND, + MAILIMAP_ERROR_NOOP, + MAILIMAP_ERROR_LOGOUT, + MAILIMAP_ERROR_CAPABILITY, + MAILIMAP_ERROR_CHECK, + MAILIMAP_ERROR_CLOSE, + MAILIMAP_ERROR_EXPUNGE, + MAILIMAP_ERROR_COPY, + MAILIMAP_ERROR_UID_COPY, + MAILIMAP_ERROR_MOVE, + MAILIMAP_ERROR_UID_MOVE, + MAILIMAP_ERROR_CREATE, + MAILIMAP_ERROR_DELETE, + MAILIMAP_ERROR_EXAMINE, + MAILIMAP_ERROR_FETCH, + MAILIMAP_ERROR_UID_FETCH, + MAILIMAP_ERROR_LIST, + MAILIMAP_ERROR_LOGIN, + MAILIMAP_ERROR_LSUB, + MAILIMAP_ERROR_RENAME, + MAILIMAP_ERROR_SEARCH, + MAILIMAP_ERROR_UID_SEARCH, + MAILIMAP_ERROR_SELECT, + MAILIMAP_ERROR_STATUS, + MAILIMAP_ERROR_STORE, + MAILIMAP_ERROR_UID_STORE, + MAILIMAP_ERROR_SUBSCRIBE, + MAILIMAP_ERROR_UNSUBSCRIBE, + MAILIMAP_ERROR_STARTTLS, + MAILIMAP_ERROR_INVAL, + MAILIMAP_ERROR_EXTENSION, + MAILIMAP_ERROR_SASL, + MAILIMAP_ERROR_SSL, + MAILIMAP_ERROR_NEEDS_MORE_DATA, + MAILIMAP_ERROR_CUSTOM_COMMAND, + MAILIMAP_ERROR_CLIENTID, +}; + +/* information about parser context */ + +struct mailimap_parser_context { + int is_rambler_workaround_enabled; + int is_qip_workaround_enabled; + + mailimap_msg_body_handler * msg_body_handler; + void * msg_body_handler_context; + struct mailimap_msg_att_body_section * msg_body_section; + int msg_body_att_type; + bool msg_body_parse_in_progress; +}; + +LIBETPAN_EXPORT +struct mailimap_parser_context * +mailimap_parser_context_new(mailimap * session); + +LIBETPAN_EXPORT +void +mailimap_parser_context_free(struct mailimap_parser_context * ctx); + +LIBETPAN_EXPORT +int +mailimap_parser_context_is_rambler_workaround_enabled(struct mailimap_parser_context * parser_ctx); + +LIBETPAN_EXPORT +int +mailimap_parser_context_is_qip_workaround_enabled(struct mailimap_parser_context * parser_ctx); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Sources/libetpan/low-level/imap/mailimap_types_helper.c b/Sources/libetpan/low-level/imap/mailimap_types_helper.c new file mode 100644 index 00000000..ce3be9c3 --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_types_helper.c @@ -0,0 +1,1351 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_types_helper.c,v 1.15 2010/09/15 16:26:12 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailimap_types.h" +#include "mail.h" + +#include + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + +/* in helper */ + + + + +LIBETPAN_EXPORT +struct mailimap_set_item * mailimap_set_item_new_single(uint32_t indx) +{ + return mailimap_set_item_new(indx, indx); +} + +LIBETPAN_EXPORT +struct mailimap_set * +mailimap_set_new_single_item(struct mailimap_set_item * item) +{ + struct mailimap_set * set; + clist * list; + int r; + + list = clist_new(); + if (list == NULL) + return NULL; + + r = clist_append(list, item); + if (r < 0) { + clist_free(list); + return NULL; + } + + set = mailimap_set_new(list); + if (set == NULL) { + clist_free(list); + return NULL; + } + + return set; +} + +LIBETPAN_EXPORT +struct mailimap_set * mailimap_set_new_interval(uint32_t first, uint32_t last) +{ + struct mailimap_set_item * item; + struct mailimap_set * set; + + item = mailimap_set_item_new(first, last); + if (item == NULL) + return NULL; + + set = mailimap_set_new_single_item(item); + if (set == NULL) { + mailimap_set_item_free(item); + return NULL; + } + + return set; +} + +LIBETPAN_EXPORT +struct mailimap_set * mailimap_set_new_single(uint32_t indx) +{ + return mailimap_set_new_interval(indx, indx); +} + + +LIBETPAN_EXPORT +struct mailimap_set * mailimap_set_new_empty(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_set_new(list); +} + +LIBETPAN_EXPORT +int mailimap_set_add(struct mailimap_set * set, + struct mailimap_set_item * set_item) +{ + int r; + + r = clist_append(set->set_list, set_item); + if (r < 0) + return MAILIMAP_ERROR_MEMORY; + + return MAILIMAP_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailimap_set_add_interval(struct mailimap_set * set, + uint32_t first, uint32_t last) +{ + struct mailimap_set_item * item; + int r; + + item = mailimap_set_item_new(first, last); + if (item == NULL) + return MAILIMAP_ERROR_MEMORY; + + r = mailimap_set_add(set, item); + if (r != MAILIMAP_NO_ERROR) { + mailimap_set_item_free(item); + return r; + } + else + return MAILIMAP_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailimap_set_add_single(struct mailimap_set * set, + uint32_t indx) +{ + return mailimap_set_add_interval(set, indx, indx); +} + +/* CHECK */ +/* no args */ + +/* CLOSE */ +/* no args */ + +/* EXPUNGE */ +/* no args */ + +/* COPY */ +/* set and gchar */ + +/* FETCH */ +/* set and gchar fetch_type */ + + + +/* section */ + +static struct mailimap_section * +mailimap_section_new_msgtext(struct mailimap_section_msgtext * msgtext) +{ + struct mailimap_section_spec * spec; + struct mailimap_section * section; + + spec = mailimap_section_spec_new(MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT, + msgtext, NULL, NULL); + if (spec == NULL) + return NULL; + + section = mailimap_section_new(spec); + if (section == NULL) { + /* detach section_msgtext so that it will not be freed */ + spec->sec_data.sec_msgtext = NULL; + mailimap_section_spec_free(spec); + return NULL; + } + + return section; +} + +static struct mailimap_section * +mailimap_section_new_part_msgtext(struct mailimap_section_part * part, + struct mailimap_section_msgtext * msgtext) +{ + struct mailimap_section_spec * spec; + struct mailimap_section * section; + struct mailimap_section_text * text; + + text = mailimap_section_text_new(MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT, + msgtext); + if (text == NULL) + return NULL; + + spec = mailimap_section_spec_new(MAILIMAP_SECTION_SPEC_SECTION_PART, + NULL, part, text); + if (spec == NULL) { + /* detach section_msgtext so that it will not be freed */ + text->sec_msgtext = NULL; + mailimap_section_text_free(text); + return NULL; + } + + section = mailimap_section_new(spec); + if (section == NULL) { + /* detach section_msgtext so that it will not be freed */ + text->sec_msgtext = NULL; + mailimap_section_spec_free(spec); + return NULL; + } + + return section; +} + +/* +HEADER +HEADER.FIELDS fields +HEADER.FIELDS.NOT fields +TEXT +*/ + +LIBETPAN_EXPORT +struct mailimap_section * mailimap_section_new_header(void) +{ + struct mailimap_section_msgtext * msgtext; + struct mailimap_section * section; + + msgtext = mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER, + NULL); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_msgtext(msgtext); + if (section == NULL) { + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new_header_fields(struct mailimap_header_list * header_list) +{ + struct mailimap_section * section; + struct mailimap_section_msgtext * msgtext; + + msgtext = + mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, + header_list); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_msgtext(msgtext); + if (section == NULL) { + /* detach header_list so that it will not be freed */ + msgtext->sec_header_list = NULL; + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new_header_fields_not(struct mailimap_header_list * header_list) +{ + struct mailimap_section * section; + struct mailimap_section_msgtext * msgtext; + + msgtext = + mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT, + header_list); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_msgtext(msgtext); + if (section == NULL) { + /* detach header_list so that it will not be freed */ + msgtext->sec_header_list = NULL; + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +LIBETPAN_EXPORT +struct mailimap_section * mailimap_section_new_text(void) +{ + struct mailimap_section * section; + struct mailimap_section_msgtext * msgtext; + + msgtext = mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_TEXT, NULL); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_msgtext(msgtext); + if (section == NULL) { + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +/* +section-part +section-part . MIME +section-part . HEADER +section-part . HEADER.FIELDS fields +section-part . HEADER.FIELDS.NOT fields +section-part . TEXT +*/ + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new_part(struct mailimap_section_part * part) +{ + struct mailimap_section_spec * spec; + struct mailimap_section * section; + + spec = mailimap_section_spec_new(MAILIMAP_SECTION_SPEC_SECTION_PART, + NULL, part, NULL); + if (spec == NULL) + return NULL; + + section = mailimap_section_new(spec); + if (section == NULL) { + /* detach section_part so that it will not be freed */ + spec->sec_data.sec_part = NULL; + mailimap_section_spec_free(spec); + return NULL; + } + + return section; +} + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new_part_mime(struct mailimap_section_part * part) +{ + struct mailimap_section_spec * spec; + struct mailimap_section * section; + struct mailimap_section_text * text; + + text = mailimap_section_text_new(MAILIMAP_SECTION_TEXT_MIME, NULL); + if (text == NULL) + return NULL; + + spec = mailimap_section_spec_new(MAILIMAP_SECTION_SPEC_SECTION_PART, + NULL, part, text); + if (spec == NULL) { + mailimap_section_text_free(text); + return NULL; + } + + section = mailimap_section_new(spec); + if (section == NULL) { + /* detach section_part so that it will not be freed */ + spec->sec_data.sec_part = NULL; + mailimap_section_spec_free(spec); + return NULL; + } + + return section; +} + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new_part_header(struct mailimap_section_part * part) +{ + struct mailimap_section_msgtext * msgtext; + struct mailimap_section * section; + + msgtext = mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER, + NULL); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_part_msgtext(part, msgtext); + if (section == NULL) { + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new_part_header_fields(struct mailimap_section_part * + part, + struct mailimap_header_list * + header_list) +{ + struct mailimap_section * section; + struct mailimap_section_msgtext * msgtext; + + msgtext = + mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, + header_list); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_part_msgtext(part, msgtext); + if (section == NULL) { + /* detach header_list so that it will not be freed */ + msgtext->sec_header_list = NULL; + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new_part_header_fields_not(struct mailimap_section_part + * part, + struct mailimap_header_list + * header_list) +{ + struct mailimap_section * section; + struct mailimap_section_msgtext * msgtext; + + msgtext = + mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT, + header_list); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_part_msgtext(part, msgtext); + if (section == NULL) { + /* detach header_list so that it will not be freed */ + msgtext->sec_header_list = NULL; + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new_part_text(struct mailimap_section_part * part) +{ + struct mailimap_section * section; + struct mailimap_section_msgtext * msgtext; + + msgtext = mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_TEXT, NULL); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_part_msgtext(part, msgtext); + if (section == NULL) { + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +/* end of section */ + + + + + + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_envelope(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_ENVELOPE, NULL, 0, 0, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_flags(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_FLAGS, NULL, 0, 0, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_internaldate(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_INTERNALDATE, NULL, 0, 0, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_RFC822, NULL, 0, 0, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_header(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_RFC822_HEADER, NULL, 0, 0, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_size(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_RFC822_SIZE, NULL, 0, 0, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_text(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_RFC822_TEXT, NULL, 0, 0, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_body(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODY, NULL, 0, 0, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_bodystructure(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODYSTRUCTURE, NULL, 0, 0, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_uid(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_UID, NULL, 0, 0, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_section(struct mailimap_section * section) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODY_SECTION, section, 0, 0, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_peek_section(struct mailimap_section * section) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION, section, 0, 0, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_section_partial(struct mailimap_section * section, + uint32_t offset, uint32_t size) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODY_SECTION, section, + offset, size, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_peek_section_partial(struct mailimap_section * section, + uint32_t offset, uint32_t size) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION, section, + offset, size, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_extension(char * ext_keyword) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_EXTENSION, NULL, 0, 0, ext_keyword); +} + + +LIBETPAN_EXPORT +struct mailimap_fetch_type * +mailimap_fetch_type_new_all(void) +{ + return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_ALL, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_fetch_type * +mailimap_fetch_type_new_full(void) +{ + return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_FULL, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_fetch_type * +mailimap_fetch_type_new_fast(void) +{ + return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_FAST, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att(struct mailimap_fetch_att * fetch_att) +{ + return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_FETCH_ATT, fetch_att, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att_list(clist * fetch_att_list) +{ + return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST, + NULL, fetch_att_list); +} + +LIBETPAN_EXPORT +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att_list_empty(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST, + NULL, list); +} + +LIBETPAN_EXPORT +int +mailimap_fetch_type_new_fetch_att_list_add(struct mailimap_fetch_type * + fetch_type, + struct mailimap_fetch_att * fetch_att) +{ + int r; + + r = clist_append(fetch_type->ft_data.ft_fetch_att_list, fetch_att); + if (r < 0) + return MAILIMAP_ERROR_MEMORY; + + return MAILIMAP_NO_ERROR; +} + + + +/* STORE */ +/* set and store_att_flags */ + +LIBETPAN_EXPORT +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_set_flags(struct mailimap_flag_list * flags) +{ + return mailimap_store_att_flags_new(0, FALSE, flags); +} + +LIBETPAN_EXPORT +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_set_flags_silent(struct mailimap_flag_list * + flags) +{ + return mailimap_store_att_flags_new(0, TRUE, flags); +} + +LIBETPAN_EXPORT +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_add_flags(struct mailimap_flag_list * flags) +{ + return mailimap_store_att_flags_new(1, FALSE, flags); +} + +LIBETPAN_EXPORT +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_add_flags_silent(struct mailimap_flag_list * + flags) +{ + return mailimap_store_att_flags_new(1, TRUE, flags); +} + +LIBETPAN_EXPORT +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_remove_flags(struct mailimap_flag_list * flags) +{ + return mailimap_store_att_flags_new(-1, FALSE, flags); +} + +LIBETPAN_EXPORT +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_remove_flags_silent(struct mailimap_flag_list * + flags) +{ + return mailimap_store_att_flags_new(-1, TRUE, flags); +} + +/* SEARCH */ +/* date search-key set */ + +/* + return mailimap_search_key_new(type, bcc, before, + body, cc, from, keyword, on, since, + subject, text, to, unkeyword, header_name, + header_value, larger, not, + or1, or2, sentbefore, senton, sentsince, + smaller, uid, set, multiple); +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_all(void) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_ALL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_bcc(char * sk_bcc) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_BCC, sk_bcc, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_before(struct mailimap_date * sk_before) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_BEFORE, NULL, sk_before, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_body(char * sk_body) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_BODY, NULL, NULL, + sk_body, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_cc(char * sk_cc) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_CC, NULL, NULL, + NULL, sk_cc, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_from(char * sk_from) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_FROM, NULL, NULL, + NULL, NULL, sk_from, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_keyword(char * sk_keyword) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_KEYWORD, NULL, NULL, + NULL, NULL, NULL, sk_keyword, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_on(struct mailimap_date * sk_on) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_ON, NULL, NULL, + NULL, NULL, NULL, NULL, sk_on, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_since(struct mailimap_date * sk_since) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SINCE, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, sk_since, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_subject(char * sk_subject) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SUBJECT, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + sk_subject, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_text(char * sk_text) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_TEXT, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, sk_text, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_to(char * sk_to) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_TO, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, sk_to, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_unkeyword(char * sk_unkeyword) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNKEYWORD, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, sk_unkeyword, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_header(char * sk_header_name, char * sk_header_value) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_HEADER, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, sk_header_name, + sk_header_value, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_larger(uint32_t sk_larger) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_LARGER, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, sk_larger, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_not(struct mailimap_search_key * sk_not) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_NOT, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, sk_not, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_or(struct mailimap_search_key * sk_or1, + struct mailimap_search_key * sk_or2) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_OR, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + sk_or1, sk_or2, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_sentbefore(struct mailimap_date * sk_sentbefore) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SENTBEFORE, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, sk_sentbefore, NULL, NULL, + 0, NULL, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_senton(struct mailimap_date * sk_senton) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SENTON, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, sk_senton, NULL, + 0, NULL, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_sentsince(struct mailimap_date * sk_sentsince) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SENTSINCE, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, sk_sentsince, + 0, NULL, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_smaller(uint32_t sk_smaller) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SMALLER, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + sk_smaller, NULL, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_uid(struct mailimap_set * sk_uid) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UID, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, sk_uid, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_set(struct mailimap_set * sk_set) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SET, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, sk_set, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_multiple(clist * sk_multiple) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_MULTIPLE, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, sk_multiple); +} + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_multiple_empty(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_search_key_new_multiple(list); +} + +LIBETPAN_EXPORT +int +mailimap_search_key_multiple_add(struct mailimap_search_key * keys, + struct mailimap_search_key * key_item) +{ + int r; + + r = clist_append(keys->sk_data.sk_multiple, key_item); + if (r < 0) + return MAILIMAP_ERROR_MEMORY; + + return MAILIMAP_NO_ERROR; +} + + + +/* CAPABILITY */ +/* no args */ + +/* LOGOUT */ +/* no args */ + +/* NOOP */ +/* no args */ + +/* APPEND */ +/* gchar flag_list date_time gchar */ + +LIBETPAN_EXPORT +struct mailimap_flag_list * +mailimap_flag_list_new_empty(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_flag_list_new(list); +} + +LIBETPAN_EXPORT +int mailimap_flag_list_add(struct mailimap_flag_list * flag_list, + struct mailimap_flag * f) +{ + int r; + + r = clist_append(flag_list->fl_list, f); + if (r < 0) + return MAILIMAP_ERROR_MEMORY; + + return MAILIMAP_NO_ERROR; +} + +LIBETPAN_EXPORT +struct mailimap_flag * mailimap_flag_new_answered(void) +{ + return mailimap_flag_new(MAILIMAP_FLAG_ANSWERED, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_flag * mailimap_flag_new_flagged(void) +{ + return mailimap_flag_new(MAILIMAP_FLAG_FLAGGED, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_flag * mailimap_flag_new_deleted(void) +{ + return mailimap_flag_new(MAILIMAP_FLAG_DELETED, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_flag * mailimap_flag_new_seen(void) +{ + return mailimap_flag_new(MAILIMAP_FLAG_SEEN, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_flag * mailimap_flag_new_draft(void) +{ + return mailimap_flag_new(MAILIMAP_FLAG_DRAFT, NULL, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_flag * mailimap_flag_new_flag_keyword(char * flag_keyword) +{ + return mailimap_flag_new(MAILIMAP_FLAG_KEYWORD, flag_keyword, NULL); +} + +LIBETPAN_EXPORT +struct mailimap_flag * mailimap_flag_new_flag_extension(char * flag_extension) +{ + return mailimap_flag_new(MAILIMAP_FLAG_EXTENSION, NULL, flag_extension); +} + + + + +/* CREATE */ +/* gchar */ + +/* DELETE */ +/* gchar */ + +/* EXAMINE */ +/* gchar */ + +/* LIST */ +/* gchar gchar */ + +/* LSUB */ +/* gchar gchar */ + +/* RENAME */ +/* gchar gchar */ + +/* SELECT */ +/* gchar */ + +/* STATUS */ +/* gchar GList of status_att */ + +LIBETPAN_EXPORT +struct mailimap_status_att_list * mailimap_status_att_list_new_empty(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_status_att_list_new(list); +} + +LIBETPAN_EXPORT +int +mailimap_status_att_list_add(struct mailimap_status_att_list * sa_list, + int status_att) +{ + int * pstatus_att; + int r; + + pstatus_att = malloc(sizeof(* pstatus_att)); + if (pstatus_att == NULL) + return MAILIMAP_ERROR_MEMORY; + + * pstatus_att = status_att; + + r = clist_append(sa_list->att_list, pstatus_att); + if (r < 0) { + free(pstatus_att); + return MAILIMAP_ERROR_MEMORY; + } + + return MAILIMAP_NO_ERROR; +} + +/* SUBSCRIBE */ +/* gchar */ + +/* UNSUBSCRIBE */ +/* gchar */ + +/* LOGIN */ +/* gchar gchar */ + +/* AUTHENTICATE */ +/* gchar */ + + +static int recursive_build_path(struct mailimap_body * root_part, + struct mailimap_body * part, + clist ** result); + +static int try_build_part(struct mailimap_body * root_part, + struct mailimap_body * part, uint32_t count, + clist ** result) +{ + int r; + clist * imap_id_list; + uint32_t * id; + + r = recursive_build_path(root_part, part, &imap_id_list); + if (r != MAILIMAP_NO_ERROR) + return r; + + id = malloc(sizeof(* id)); + if (id == NULL) { + clist_free(imap_id_list); + return MAILIMAP_ERROR_MEMORY; + } + + * id = count; + + r = clist_prepend(imap_id_list, id); + if (r < 0) { + free(id); + clist_free(imap_id_list); + return MAILIMAP_ERROR_MEMORY; + } + + * result = imap_id_list; + + return MAILIMAP_NO_ERROR; +} + + +static int recursive_build_path(struct mailimap_body * root_part, + struct mailimap_body * part, + clist ** result) +{ + clistiter * cur; + uint32_t count; + int r; + clist * imap_id_list; + + if (part == root_part) { + imap_id_list = clist_new(); + if (imap_id_list == NULL) { + return MAILIMAP_ERROR_MEMORY; + } + + * result = imap_id_list; + + return MAILIMAP_NO_ERROR; + } + + switch (root_part->bd_type) { + case MAILIMAP_BODY_MPART: + count = 0; + for(cur = clist_begin(root_part->bd_data.bd_body_mpart->bd_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailimap_body * current_part; + + current_part = clist_content(cur); + count ++; + + r = try_build_part(current_part, part, count, &imap_id_list); + if (r == MAILIMAP_ERROR_INVAL) { + continue; + } + else if (r != MAILIMAP_NO_ERROR) { + return r; + } + else { + * result = imap_id_list; + return MAILIMAP_NO_ERROR; + } + } + return MAILIMAP_ERROR_INVAL; + + case MAILIMAP_BODY_1PART: + if (root_part->bd_data.bd_body_1part->bd_type == + MAILIMAP_BODY_TYPE_1PART_MSG) { + struct mailimap_body * current_part; + + current_part = + root_part->bd_data.bd_body_1part->bd_data.bd_type_msg->bd_body; + + r = try_build_part(current_part, part, 1, &imap_id_list); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + else { + * result = imap_id_list; + return MAILIMAP_NO_ERROR; + } + } + else { + return MAILIMAP_ERROR_INVAL; + } + break; + + default: + return MAILIMAP_ERROR_INVAL; + } +} + +/* return mailimap_section_part from a given mailimap_body */ + +LIBETPAN_EXPORT +int mailimap_get_section_part_from_body(struct mailimap_body * root_part, + struct mailimap_body * part, + struct mailimap_section_part ** result) +{ + struct mailimap_section_part * section_part; + clist * id_list; + int r; + int res; + + r = recursive_build_path(root_part, part, &id_list); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + section_part = mailimap_section_part_new(id_list); + if (section_part == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_list; + } + + * result = section_part; + + return MAILIMAP_NO_ERROR; + + free_list: + clist_foreach(id_list, (clist_func) free, NULL); + clist_free(id_list); + err: + return res; +} diff --git a/Sources/libetpan/low-level/imap/mailimap_types_helper.h b/Sources/libetpan/low-level/imap/mailimap_types_helper.h new file mode 100644 index 00000000..e3df041e --- /dev/null +++ b/Sources/libetpan/low-level/imap/mailimap_types_helper.h @@ -0,0 +1,849 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_types_helper.h,v 1.12 2008/02/20 22:15:52 hoa Exp $ + */ + +#ifndef MAILIMAP_TYPES_HELPER_H + +#define MAILIMAP_TYPES_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + IMPORTANT NOTE: + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + allocation functions will return NULL on failure +*/ + +/* + this function creates a new set item with a single message + given by indx +*/ + +LIBETPAN_EXPORT +struct mailimap_set_item * mailimap_set_item_new_single(uint32_t indx); + +/* + this function creates a new set with one set item + */ + +LIBETPAN_EXPORT +struct mailimap_set * +mailimap_set_new_single_item(struct mailimap_set_item * item); + +/* + this function creates a set with a single interval +*/ + +LIBETPAN_EXPORT +struct mailimap_set * mailimap_set_new_interval(uint32_t first, uint32_t last); + +/* + this function creates a set with a single message +*/ + +LIBETPAN_EXPORT +struct mailimap_set * mailimap_set_new_single(uint32_t indx); + +/* + this function creates an empty set of messages +*/ + +LIBETPAN_EXPORT +struct mailimap_set * mailimap_set_new_empty(void); + +/* + this function adds a set item to the set of messages + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int mailimap_set_add(struct mailimap_set * set, + struct mailimap_set_item * set_item); + +/* + this function adds an interval to the set + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int mailimap_set_add_interval(struct mailimap_set * set, + uint32_t first, uint32_t last); + +/* + this function adds a single message to the set + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int mailimap_set_add_single(struct mailimap_set * set, + uint32_t indx); + +/* + this function creates a mailimap_section structure to request + the header of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_section * mailimap_section_new_header(void); + +/* + this function creates a mailimap_section structure to describe + a list of headers +*/ + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new_header_fields(struct mailimap_header_list * header_list); + +/* + this function creates a mailimap_section structure to describe headers + other than those given +*/ + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new_header_fields_not(struct mailimap_header_list * header_list); + +/* + this function creates a mailimap_section structure to describe the + text of a message + */ + +LIBETPAN_EXPORT +struct mailimap_section * mailimap_section_new_text(void); + +/* + this function creates a mailimap_section structure to describe the + content of a MIME part +*/ + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new_part(struct mailimap_section_part * part); + +/* + this function creates a mailimap_section structure to describe the + MIME fields of a MIME part +*/ + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new_part_mime(struct mailimap_section_part * part); + +/* + this function creates a mailimap_section structure to describe the + headers of a MIME part if the MIME type is a message/rfc822 +*/ + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new_part_header(struct mailimap_section_part * part); + +/* + this function creates a mailimap_section structure to describe + a list of headers of a MIME part if the MIME type is a message/rfc822 +*/ + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new_part_header_fields(struct mailimap_section_part * + part, + struct mailimap_header_list * + header_list); + +/* + this function creates a mailimap_section structure to describe + headers of a MIME part other than those given if the MIME type + is a message/rfc822 +*/ + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new_part_header_fields_not(struct mailimap_section_part + * part, + struct mailimap_header_list + * header_list); + +/* + this function creates a mailimap_section structure to describe + text part of message if the MIME type is a message/rfc822 +*/ + +LIBETPAN_EXPORT +struct mailimap_section * +mailimap_section_new_part_text(struct mailimap_section_part * part); + + +/* + this function creates a mailimap_fetch_att structure to request + envelope of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_envelope(void); + + +/* + this function creates a mailimap_fetch_att structure to request + flags of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_flags(void); + +/* + this function creates a mailimap_fetch_att structure to request + internal date of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_internaldate(void); + + +/* + this function creates a mailimap_fetch_att structure to request + text part of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822(void); + + +/* + this function creates a mailimap_fetch_att structure to request + header of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_header(void); + +/* + this function creates a mailimap_fetch_att structure to request + size of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_size(void); + +/* + this function creates a mailimap_fetch_att structure to request + envelope of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_text(void); + +/* + this function creates a mailimap_fetch_att structure to request + the MIME structure of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_body(void); + +/* + this function creates a mailimap_fetch_att structure to request + the MIME structure of a message and additional MIME information +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_bodystructure(void); + +/* + this function creates a mailimap_fetch_att structure to request + unique identifier of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_uid(void); + +/* + this function creates a mailimap_fetch_att structure to request + a given section of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_section(struct mailimap_section * section); + +/* + this function creates a mailimap_fetch_att structure to request + a given section of a message without marking it as read +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_peek_section(struct mailimap_section * section); + +/* + this function creates a mailimap_fetch_att structure to request + a part of a section of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_section_partial(struct mailimap_section * section, + uint32_t offset, uint32_t size); + +/* + this function creates a mailimap_fetch_att structure to request + a part of a section of a message without marking it as read +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_peek_section_partial(struct mailimap_section * section, + uint32_t offset, uint32_t size); + +/* + creates a mailimap_fetch_att extension +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_att * + mailimap_fetch_att_new_extension(char * ext_keyword); + +/* + this function creates a mailimap_fetch_type structure to request + (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE) of a message +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_type * +mailimap_fetch_type_new_all(void); + +/* + this function creates a mailimap_fetch_type structure to request + (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE BODY) +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_type * +mailimap_fetch_type_new_full(void); + +/* + this function creates a mailimap_fetch_type structure to request + (FLAGS INTERNALDATE RFC822.SIZE) +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_type * +mailimap_fetch_type_new_fast(void); + +/* + this function creates a mailimap_fetch_type structure to request + the given fetch attribute +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att(struct mailimap_fetch_att * fetch_att); + +/* + this function creates a mailimap_fetch_type structure to request + the list of fetch attributes +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att_list(clist * fetch_att_list); + +/* + this function creates a mailimap_fetch_type structure +*/ + +LIBETPAN_EXPORT +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att_list_empty(void); + +/* + this function adds a given fetch attribute to the mailimap_fetch + structure + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int +mailimap_fetch_type_new_fetch_att_list_add(struct mailimap_fetch_type * + fetch_type, + struct mailimap_fetch_att * + fetch_att); + +/* + this function creates a store attribute to set the given flags +*/ + +LIBETPAN_EXPORT +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_set_flags(struct mailimap_flag_list * flags); + +/* + this function creates a store attribute to silently set the given flags +*/ + +LIBETPAN_EXPORT +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_set_flags_silent(struct mailimap_flag_list * + flags); + +/* + this function creates a store attribute to add the given flags +*/ + +LIBETPAN_EXPORT +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_add_flags(struct mailimap_flag_list * flags); + +/* + this function creates a store attribute to add silently the given flags +*/ + +LIBETPAN_EXPORT +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_add_flags_silent(struct mailimap_flag_list * + flags); + +/* + this function creates a store attribute to remove the given flags +*/ + +LIBETPAN_EXPORT +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_remove_flags(struct mailimap_flag_list * flags); + +/* + this function creates a store attribute to remove silently the given flags +*/ + +LIBETPAN_EXPORT +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_remove_flags_silent(struct mailimap_flag_list * + flags); + + +/* + this function creates a condition structure to match all messages +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_all(void); + +/* + this function creates a condition structure to match messages with Bcc field + + @param bcc this is the content of Bcc to match, it should be allocated + with malloc() +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_bcc(char * sk_bcc); + +/* + this function creates a condition structure to match messages with + internal date +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_before(struct mailimap_date * sk_before); + +/* + this function creates a condition structure to match messages with + message content + + @param body this is the content of the message to match, it should + be allocated with malloc() +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_body(char * sk_body); + +/* + this function creates a condition structure to match messages with + Cc field + + + @param cc this is the content of Cc to match, it should be allocated + with malloc() +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_cc(char * sk_cc); + +/* + this function creates a condition structure to match messages with + From field + + @param from this is the content of From to match, it should be allocated + with malloc() +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_from(char * sk_from); + +/* + this function creates a condition structure to match messages with + a flag given by keyword +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_keyword(char * sk_keyword); + +/* + this function creates a condition structure to match messages with + internal date +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_on(struct mailimap_date * sk_on); + +/* + this function creates a condition structure to match messages with + internal date +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_since(struct mailimap_date * sk_since); + +/* + this function creates a condition structure to match messages with + Subject field + + @param subject this is the content of Subject to match, it should + be allocated with malloc() +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_subject(char * sk_subject); + +/* + this function creates a condition structure to match messages with + message text part + + @param text this is the message text to match, it should + be allocated with malloc() +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_text(char * sk_text); + +/* + this function creates a condition structure to match messages with + To field + + @param to this is the content of To to match, it should be allocated + with malloc() +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_to(char * sk_to); + +/* + this function creates a condition structure to match messages with + no a flag given by unkeyword +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_unkeyword(char * sk_unkeyword); + +/* + this function creates a condition structure to match messages with + the given field + + @param header_name this is the name of the field to match, it + should be allocated with malloc() + + @param header_value this is the content, it should be allocated + with malloc() +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_header(char * sk_header_name, char * sk_header_value); + +/* + this function creates a condition structure to match messages with size +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_larger(uint32_t sk_larger); + +/* + this function creates a condition structure to match messages that + do not match the given condition +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_not(struct mailimap_search_key * sk_not); + +/* + this function creates a condition structure to match messages that + match one of the given conditions +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_or(struct mailimap_search_key * sk_or1, + struct mailimap_search_key * sk_or2); + +/* + this function creates a condition structure to match messages + with Date field +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_sentbefore(struct mailimap_date * sk_sentbefore); + +/* + this function creates a condition structure to match messages + with Date field +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_senton(struct mailimap_date * sk_senton); + +/* + this function creates a condition structure to match messages + with Date field +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_sentsince(struct mailimap_date * sk_sentsince); + +/* + this function creates a condition structure to match messages with size +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_smaller(uint32_t sk_smaller); + +/* + this function creates a condition structure to match messages with unique + identifier +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_uid(struct mailimap_set * sk_uid); + +/* + this function creates a condition structure to match messages with number + or unique identifier (depending whether SEARCH or UID SEARCH is used) +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_set(struct mailimap_set * sk_set); + +/* + this function creates a condition structure to match messages that match + all the conditions given in the list +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_multiple(clist * sk_multiple); + + +/* + same as previous but the list is empty +*/ + +LIBETPAN_EXPORT +struct mailimap_search_key * +mailimap_search_key_new_multiple_empty(void); + +/* + this function adds a condition to the condition list + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int +mailimap_search_key_multiple_add(struct mailimap_search_key * keys, + struct mailimap_search_key * key_item); + + + +/* + this function creates an empty list of flags +*/ + +LIBETPAN_EXPORT +struct mailimap_flag_list * +mailimap_flag_list_new_empty(void); + +/* + this function adds a flag to the list of flags + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int mailimap_flag_list_add(struct mailimap_flag_list * flag_list, + struct mailimap_flag * f); + +/* + this function creates a \Answered flag +*/ + +LIBETPAN_EXPORT +struct mailimap_flag * mailimap_flag_new_answered(void); + +/* + this function creates a \Flagged flag +*/ + +LIBETPAN_EXPORT +struct mailimap_flag * mailimap_flag_new_flagged(void); + +/* + this function creates a \Deleted flag +*/ + +LIBETPAN_EXPORT +struct mailimap_flag * mailimap_flag_new_deleted(void); + +/* + this function creates a \Seen flag +*/ + +LIBETPAN_EXPORT +struct mailimap_flag * mailimap_flag_new_seen(void); + +/* + this function creates a \Draft flag +*/ + +LIBETPAN_EXPORT +struct mailimap_flag * mailimap_flag_new_draft(void); + +/* + this function creates a keyword flag + + @param flag_keyword this should be allocated with malloc() +*/ + +LIBETPAN_EXPORT +struct mailimap_flag * mailimap_flag_new_flag_keyword(char * flag_keyword); + + +/* + this function creates an extension flag + + @param flag_extension this should be allocated with malloc() +*/ + +LIBETPAN_EXPORT +struct mailimap_flag * mailimap_flag_new_flag_extension(char * flag_extension); + +/* + this function creates an empty list of status attributes +*/ + +LIBETPAN_EXPORT +struct mailimap_status_att_list * mailimap_status_att_list_new_empty(void); + +/* + this function adds status attributes to the list + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int +mailimap_status_att_list_add(struct mailimap_status_att_list * sa_list, + int status_att); + +/* return mailimap_section_part from a given mailimap_body */ + +LIBETPAN_EXPORT +int mailimap_get_section_part_from_body(struct mailimap_body * root_part, + struct mailimap_body * part, + struct mailimap_section_part ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/namespace.c b/Sources/libetpan/low-level/imap/namespace.c new file mode 100644 index 00000000..38c02e07 --- /dev/null +++ b/Sources/libetpan/low-level/imap/namespace.c @@ -0,0 +1,145 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2011 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "namespace.h" +#include "mailimap.h" +#include "mailimap_extension.h" +#include "namespace_types.h" +#include "namespace_parser.h" +#include "namespace_sender.h" + +#include + +static void +mailimap_namespace_extension_data_free(struct mailimap_extension_data * ext_data); + +LIBETPAN_EXPORT +struct mailimap_extension_api mailimap_extension_namespace = { + /* name */ "NAMESPACE", + /* extension_id */ MAILIMAP_EXTENSION_NAMESPACE, + /* parser */ mailimap_namespace_extension_parse, + /* free */ mailimap_namespace_extension_data_free +}; + +int mailimap_namespace(mailimap * session, struct mailimap_namespace_data ** result) +{ + struct mailimap_namespace_data * namespace_data; + struct mailimap_response * response; + clistiter * cur; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_namespace_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + namespace_data = NULL; + for (cur = clist_begin(session->imap_response_info->rsp_extension_list); + cur != NULL; cur = clist_next(cur)) { + struct mailimap_extension_data * ext_data; + + ext_data = (struct mailimap_extension_data *) clist_content(cur); + if (ext_data->ext_extension->ext_id == MAILIMAP_EXTENSION_NAMESPACE) { + if (namespace_data == NULL) { + namespace_data = ext_data->ext_data; + ext_data->ext_data = NULL; + ext_data->ext_type = -1; + } + } + } + + clist_foreach(session->imap_response_info->rsp_extension_list, + (clist_func) mailimap_extension_data_free, NULL); + clist_free(session->imap_response_info->rsp_extension_list); + session->imap_response_info->rsp_extension_list = NULL; + + if (namespace_data == NULL) { + return MAILIMAP_ERROR_EXTENSION; + } + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + break; + + default: + mailimap_namespace_data_free(namespace_data); + return MAILIMAP_ERROR_EXTENSION; + } + + mailimap_response_free(response); + + * result = namespace_data; + + return MAILIMAP_NO_ERROR; +} + +static void +mailimap_namespace_extension_data_free(struct mailimap_extension_data * ext_data) +{ + if (ext_data->ext_data != NULL) { + mailimap_namespace_data_free((struct mailimap_namespace_data *) ext_data->ext_data); + } + free(ext_data); +} + +LIBETPAN_EXPORT +int mailimap_has_namespace(mailimap * session) +{ + return mailimap_has_extension(session, "NAMESPACE"); +} + diff --git a/Sources/libetpan/low-level/imap/namespace.h b/Sources/libetpan/low-level/imap/namespace.h new file mode 100644 index 00000000..e807150a --- /dev/null +++ b/Sources/libetpan/low-level/imap/namespace.h @@ -0,0 +1,57 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2011 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef NAMESPACE_H + +#define NAMESPACE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +LIBETPAN_EXPORT +extern struct mailimap_extension_api mailimap_extension_namespace; + +LIBETPAN_EXPORT +int mailimap_namespace(mailimap * session, struct mailimap_namespace_data ** result); + +LIBETPAN_EXPORT +int mailimap_has_namespace(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/namespace_parser.c b/Sources/libetpan/low-level/imap/namespace_parser.c new file mode 100644 index 00000000..0f4a8e95 --- /dev/null +++ b/Sources/libetpan/low-level/imap/namespace_parser.c @@ -0,0 +1,461 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2011 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "namespace_parser.h" + +#include "namespace_types.h" +#include "mailimap_keywords.h" +#include "mailimap_extension.h" +#include "namespace.h" + +#include +#include + +static int mailimap_namespace_data_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_namespace_data ** result, + size_t progr_rate, progress_function * progr_fun); + +static int mailimap_namespace_response_extension_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_namespace_response_extension ** result, + size_t progr_rate, progress_function * progr_fun); + +int +mailimap_namespace_extension_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, progress_function * progr_fun) +{ + int r; + struct mailimap_namespace_data * namespace_data = NULL; + struct mailimap_extension_data * ext_data; + void * data; + int type; + size_t cur_token; + + cur_token = * indx; + + switch (calling_parser) + { + case MAILIMAP_EXTENDED_PARSER_RESPONSE_DATA: + r = mailimap_namespace_data_parse(fd, buffer, parser_ctx, &cur_token, + &namespace_data, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + type = MAILIMAP_NAMESPACE_TYPE_NAMESPACE; + data = namespace_data; + + ext_data = mailimap_extension_data_new(&mailimap_extension_namespace, + type, data); + if (ext_data == NULL) { + if (namespace_data != NULL) + mailimap_namespace_data_free(namespace_data); + return MAILIMAP_ERROR_MEMORY; + } + + * result = ext_data; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + default: + /* return a MAILIMAP_ERROR_PARSE if the extension + doesn't extend calling_parser. */ + return MAILIMAP_ERROR_PARSE; + } +} + +/* + "(" string SP (<"> QUOTED_CHAR <"> / + nil) *(Namespace_Response_Extension) ")" + */ + +static int mailimap_namespace_info_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_namespace_info ** result, + size_t progr_rate, progress_function * progr_fun) +{ + size_t cur_token = * indx; + int r; + int res; + char * prefix; + size_t prefix_len; + clistiter * cur; + clist * ext_list; + char delimiter; + struct mailimap_namespace_info * info; + + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_string_parse(fd, buffer, parser_ctx, &cur_token, &prefix, &prefix_len, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_ERROR_PARSE) { + /* do nothing */ + } + + r = mailimap_nil_parse(fd, buffer, parser_ctx, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + delimiter = 0; + } + else { + r = mailimap_dquote_parse(fd, buffer, parser_ctx, &cur_token); + if (r == MAILIMAP_ERROR_PARSE) { + res = r; + goto free_prefix; + } + + r = mailimap_quoted_char_parse(fd, buffer, parser_ctx, &cur_token, &delimiter); + if (r == MAILIMAP_ERROR_PARSE) { + // could not parse, use delimiter as fallback + // this is an issue on Courier-IMAP + delimiter = prefix[strlen(prefix) - 1]; + } + + r = mailimap_dquote_parse(fd, buffer, parser_ctx, &cur_token); + if (r == MAILIMAP_ERROR_PARSE) { + res = r; + goto free_prefix; + } + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_prefix; + } + + r = mailimap_struct_multiple_parse(fd, buffer, parser_ctx, &cur_token, + &ext_list, + (mailimap_struct_parser *) + mailimap_namespace_response_extension_parse, + (mailimap_struct_destructor *) + mailimap_namespace_response_extension_free, + progr_rate, progr_fun); + if (r == MAILIMAP_ERROR_PARSE) { + ext_list = NULL; + } + else if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_prefix; + } + + info = mailimap_namespace_info_new(prefix, delimiter, ext_list); + if (info == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_ext; + } + + * result = info; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + +free_ext: + if (ext_list != NULL) { + for(cur = clist_begin(ext_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_namespace_response_extension * ext; + + ext = clist_content(cur); + mailimap_namespace_response_extension_free(ext); + } + clist_free(ext_list); + } +free_prefix: + mailimap_string_free(prefix); +err: + return res; +} + +/* + Namespace = nil / "(" 1*( "(" string SP (<"> QUOTED_CHAR <"> / + nil) *(Namespace_Response_Extension) ")" ) ")" + + Namespace = nil / "(" 1*( info ) ")" +*/ + + +static int mailimap_namespace_item_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_namespace_item ** result, + size_t progr_rate, progress_function * progr_fun) +{ + size_t cur_token = * indx; + int r; + int res; + clist * info_list; + clistiter * cur; + struct mailimap_namespace_item * item; + + r = mailimap_nil_parse(fd, buffer, parser_ctx, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + * indx = cur_token; + * result = NULL; + return MAILIMAP_NO_ERROR; + } + + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + r = mailimap_struct_multiple_parse(fd, buffer, parser_ctx, &cur_token, + &info_list, + (mailimap_struct_parser *) + mailimap_namespace_info_parse, + (mailimap_struct_destructor *) + mailimap_namespace_info_free, + progr_rate, progr_fun); + if (r == MAILIMAP_ERROR_PARSE) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_info_list; + } + + item = mailimap_namespace_item_new(info_list); + if (item == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_info_list; + } + + * indx = cur_token; + * result = item; + + return MAILIMAP_NO_ERROR; + +free_info_list: + for(cur = clist_begin(info_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_namespace_info * info; + + info = clist_content(cur); + mailimap_namespace_info_free(info); + } + clist_free(info_list); +err: + return res; +} + +/* + Namespace_Command = "NAMESPACE" + */ + +/* + Namespace_Response_Extension = SP string SP "(" string *(SP string) ")" + */ + +static int namespace_extension_value_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t result_len; + + return mailimap_string_parse(fd, buffer, parser_ctx, indx, result, &result_len, progr_rate, progr_fun); +} + +static int mailimap_namespace_response_extension_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_namespace_response_extension ** result, + size_t progr_rate, progress_function * progr_fun) +{ + int r; + int res; + size_t cur_token; + char * name; + size_t name_len; + clist * value_list; + struct mailimap_namespace_response_extension * ext; + clistiter * cur; + + cur_token = * indx; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_ERROR_PARSE) { + /* do nothing */ + } + + r = mailimap_string_parse(fd, buffer, parser_ctx, &cur_token, &name, &name_len, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_ERROR_PARSE) { + /* do nothing */ + } + + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, &cur_token, &value_list, + (mailimap_struct_parser *) namespace_extension_value_parse, + (mailimap_struct_destructor *) mailimap_string_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_name; + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_value_list; + } + + ext = mailimap_namespace_response_extension_new(name, value_list); + if (ext == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_value_list; + } + + * indx = cur_token; + * result = ext; + + return MAILIMAP_NO_ERROR; + +free_value_list: + for(cur = clist_begin(value_list) ; cur != NULL ; cur = clist_next(cur)) { + char * value; + + value = clist_content(cur); + mailimap_string_free(value); + } + clist_free(value_list); +free_name: + mailimap_string_free(name); +err: + return res; +} + + /* + Namespace_Response = "*" SP "NAMESPACE" SP Namespace SP Namespace SP + Namespace + + ; The first Namespace is the Personal Namespace(s) + ; The second Namespace is the Other Users' Namespace(s) + ; The third Namespace is the Shared Namespace(s) +*/ + +static int mailimap_namespace_data_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_namespace_data ** result, + size_t progr_rate, progress_function * progr_fun) +{ + size_t cur_token; + int r; + int res; + struct mailimap_namespace_item * personal_namespace; + struct mailimap_namespace_item * other_namespace; + struct mailimap_namespace_item * shared_namespace; + struct mailimap_namespace_data * ns; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "NAMESPACE"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_namespace_item_parse(fd, buffer, parser_ctx, &cur_token, &personal_namespace, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_namespace_item_parse(fd, buffer, parser_ctx, &cur_token, &other_namespace, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_personal; + } + + r = mailimap_namespace_item_parse(fd, buffer, parser_ctx, &cur_token, &shared_namespace, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_other; + } + + ns = mailimap_namespace_data_new(personal_namespace, other_namespace, shared_namespace); + if (ns == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_shared; + } + + * result = ns; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + +free_shared: + if (shared_namespace != NULL) { + mailimap_namespace_item_free(shared_namespace); + } +free_other: + if (other_namespace != NULL) { + mailimap_namespace_item_free(other_namespace); + } +free_personal: + if (personal_namespace != NULL) { + mailimap_namespace_item_free(personal_namespace); + } +err: + return res; +} diff --git a/Sources/libetpan/low-level/imap/namespace_parser.h b/Sources/libetpan/low-level/imap/namespace_parser.h new file mode 100644 index 00000000..9be2f501 --- /dev/null +++ b/Sources/libetpan/low-level/imap/namespace_parser.h @@ -0,0 +1,55 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2011 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + + +#ifndef NAMESPACE_PARSER_H + +#define NAMESPACE_PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_parser.h" +#include "namespace_types.h" + +int +mailimap_namespace_extension_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, progress_function * progr_fun); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/namespace_sender.c b/Sources/libetpan/low-level/imap/namespace_sender.c new file mode 100644 index 00000000..17d2e9ab --- /dev/null +++ b/Sources/libetpan/low-level/imap/namespace_sender.c @@ -0,0 +1,43 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "namespace_sender.h" + +int mailimap_namespace_send(mailstream * fd) +{ + int r; + + r = mailimap_token_send(fd, "NAMESPACE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} diff --git a/Sources/libetpan/low-level/imap/namespace_sender.h b/Sources/libetpan/low-level/imap/namespace_sender.h new file mode 100644 index 00000000..bb95b277 --- /dev/null +++ b/Sources/libetpan/low-level/imap/namespace_sender.h @@ -0,0 +1,48 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef NAMESPACE_SENDER_H + +#define NAMESPACE_SENDER_H + +#include "mailimap_sender.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int mailimap_namespace_send(mailstream * fd); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/namespace_types.c b/Sources/libetpan/low-level/imap/namespace_types.c new file mode 100644 index 00000000..91c05126 --- /dev/null +++ b/Sources/libetpan/low-level/imap/namespace_types.c @@ -0,0 +1,165 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "namespace_types.h" + +#include "mailimap_types.h" +#include + +LIBETPAN_EXPORT +struct mailimap_namespace_response_extension * +mailimap_namespace_response_extension_new(char * name, + clist * values) +{ + struct mailimap_namespace_response_extension * ext; + + ext = malloc(sizeof(* ext)); + if (ext == NULL) + return NULL; + + ext->ns_name = name; + ext->ns_values = values; + + return ext; +} + +LIBETPAN_EXPORT +void mailimap_namespace_response_extension_free(struct mailimap_namespace_response_extension * ext) +{ + clistiter * cur; + + for(cur = clist_begin(ext->ns_values) ; cur != NULL ; cur = clist_next(cur)) { + char * value; + + value = clist_content(cur); + mailimap_string_free(value); + } + clist_free(ext->ns_values); + mailimap_string_free(ext->ns_name); + free(ext); +} + +LIBETPAN_EXPORT +struct mailimap_namespace_info * mailimap_namespace_info_new(char * prefix, char delimiter, + clist * extensions) +{ + struct mailimap_namespace_info * info; + + info = malloc(sizeof(* info)); + if (info == NULL) + return NULL; + + info->ns_prefix = prefix; + info->ns_delimiter = delimiter; + info->ns_extensions = extensions; + + return info; +} + +LIBETPAN_EXPORT +void mailimap_namespace_info_free(struct mailimap_namespace_info * info) +{ + clistiter * cur; + + if (info->ns_extensions != NULL) { + for(cur = clist_begin(info->ns_extensions) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_namespace_response_extension * ext; + + ext = clist_content(cur); + mailimap_namespace_response_extension_free(ext); + } + clist_free(info->ns_extensions); + } + mailimap_string_free(info->ns_prefix); + free(info); +} + +LIBETPAN_EXPORT +struct mailimap_namespace_item * mailimap_namespace_item_new(clist * data_list) +{ + struct mailimap_namespace_item * item; + + item = malloc(sizeof(* item)); + if (item == NULL) + return NULL; + + item->ns_data_list = data_list; + + return item; +} + +LIBETPAN_EXPORT +void mailimap_namespace_item_free(struct mailimap_namespace_item * item) +{ + clistiter * cur; + + for(cur = clist_begin(item->ns_data_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_namespace_info * info; + + info = clist_content(cur); + mailimap_namespace_info_free(info); + } + clist_free(item->ns_data_list); + free(item); +} + +LIBETPAN_EXPORT +struct mailimap_namespace_data * mailimap_namespace_data_new(struct mailimap_namespace_item * personal, + struct mailimap_namespace_item * other, + struct mailimap_namespace_item * shared) +{ + struct mailimap_namespace_data * ns; + + ns = malloc(sizeof(* ns)); + if (ns == NULL) + return NULL; + + ns->ns_personal = personal; + ns->ns_other = other; + ns->ns_shared = shared; + + return ns; +} + +LIBETPAN_EXPORT +void mailimap_namespace_data_free(struct mailimap_namespace_data * ns) +{ + if (ns->ns_personal != NULL) { + mailimap_namespace_item_free(ns->ns_personal); + } + if (ns->ns_other != NULL) { + mailimap_namespace_item_free(ns->ns_other); + } + if (ns->ns_shared != NULL) { + mailimap_namespace_item_free(ns->ns_shared); + } + free(ns); +} diff --git a/Sources/libetpan/low-level/imap/namespace_types.h b/Sources/libetpan/low-level/imap/namespace_types.h new file mode 100644 index 00000000..37ac1596 --- /dev/null +++ b/Sources/libetpan/low-level/imap/namespace_types.h @@ -0,0 +1,93 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef NAMESPACE_TYPES_H + +#define NAMESPACE_TYPES_H + +#include + +enum { + MAILIMAP_NAMESPACE_TYPE_NAMESPACE +}; + +struct mailimap_namespace_response_extension { + char * ns_name; /* != NULL */ + clist * ns_values; /* != NULL, list of char * */ +}; + +LIBETPAN_EXPORT +struct mailimap_namespace_response_extension * +mailimap_namespace_response_extension_new(char * name, + clist * values); + +LIBETPAN_EXPORT +void mailimap_namespace_response_extension_free(struct mailimap_namespace_response_extension * ext); + +struct mailimap_namespace_info { + char * ns_prefix; /* != NULL */ + char ns_delimiter; + clist * ns_extensions; /* can be NULL, list of mailimap_namespace_response_extension */ +}; + +LIBETPAN_EXPORT +struct mailimap_namespace_info * mailimap_namespace_info_new(char * prefix, char delimiter, + clist * extensions); + +LIBETPAN_EXPORT +void mailimap_namespace_info_free(struct mailimap_namespace_info * info); + +struct mailimap_namespace_item { + clist * ns_data_list; /* != NULL, list of mailimap_namespace_info */ +}; + +LIBETPAN_EXPORT +struct mailimap_namespace_item * mailimap_namespace_item_new(clist * data_list); + +LIBETPAN_EXPORT +void mailimap_namespace_item_free(struct mailimap_namespace_item * item); + +struct mailimap_namespace_data { + struct mailimap_namespace_item * ns_personal; /* can be NULL */ + struct mailimap_namespace_item * ns_other; /* can be NULL */ + struct mailimap_namespace_item * ns_shared; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimap_namespace_data * +mailimap_namespace_data_new(struct mailimap_namespace_item * personal, + struct mailimap_namespace_item * other, + struct mailimap_namespace_item * shared); + +LIBETPAN_EXPORT +void mailimap_namespace_data_free(struct mailimap_namespace_data * ns); + +#endif diff --git a/Sources/libetpan/low-level/imap/qresync.c b/Sources/libetpan/low-level/imap/qresync.c new file mode 100644 index 00000000..98b76ef8 --- /dev/null +++ b/Sources/libetpan/low-level/imap/qresync.c @@ -0,0 +1,688 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2013 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "qresync.h" +#include "qresync_private.h" + +#include +#include +#include + +#include "mailimap_sender.h" +#include "mailimap.h" +#include "condstore.h" +#include "condstore_private.h" +#include "mailimap_keywords.h" +#include "mailimap_parser.h" + +/* +capability =/ "QRESYNC" + +select-param = "QRESYNC" SP "(" uidvalidity SP +mod-sequence-value [SP known-uids] +[SP seq-match-data] ")" +;; conforms to the generic select-param +;; syntax defined in [IMAPABNF] + +seq-match-data = "(" known-sequence-set SP known-uid-set ")" + +uidvalidity = nz-number + +known-uids = sequence-set +;; sequence of UIDs, "*" is not allowed + +known-sequence-set = sequence-set +;; set of message numbers corresponding to +;; the UIDs in known-uid-set, in ascending order. +;; * is not allowed. + +known-uid-set = sequence-set +;; set of UIDs corresponding to the messages in +;; known-sequence-set, in ascending order. +;; * is not allowed. + +message-data =/ expunged-resp + +expunged-resp = "VANISHED" [SP "(EARLIER)"] SP known-uids + +rexpunges-fetch-mod = "VANISHED" +;; VANISHED UID FETCH modifier conforms +;; to the fetch-modifier syntax +;; defined in [IMAPABNF]. It is only +;; allowed in the UID FETCH command. + +resp-text-code =/ "CLOSED" +*/ + +static void + mailimap_qresync_extension_data_free(struct mailimap_extension_data * ext_data); + +static int + mailimap_qresync_extension_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, progress_function * progr_fun); + +struct mailimap_extension_api mailimap_extension_qresync = { + /* name */ "QRESYNC", + /* extension_id */ MAILIMAP_EXTENSION_QRESYNC, + /* parser */ mailimap_qresync_extension_parse, + /* free */ mailimap_qresync_extension_data_free +}; + +int mailimap_select_qresync_send(mailstream * fd, const char * mb, + uint32_t uidvalidity, uint64_t modseq_value, + struct mailimap_set * known_uids, + struct mailimap_set * seq_match_data_sequences, + struct mailimap_set * seq_match_data_uids) +{ + int r; + + /* + select-param = "QRESYNC" SP "(" uidvalidity SP + mod-sequence-value [SP known-uids] + [SP seq-match-data] ")" + */ + + r = mailimap_token_send(fd, "SELECT"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_token_send(fd, "QRESYNC"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_oparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_number_send(fd, uidvalidity); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_mod_sequence_value_send(fd, modseq_value); + if (r != MAILIMAP_NO_ERROR) + return r; + if (known_uids != NULL) { + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_set_send(fd, known_uids); + if (r != MAILIMAP_NO_ERROR) + return r; + } + if ((seq_match_data_sequences != NULL) && (seq_match_data_uids != NULL)) { + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + /* seq-match-data = "(" known-sequence-set SP known-uid-set ")" */ + r = mailimap_oparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_set_send(fd, seq_match_data_sequences); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_set_send(fd, seq_match_data_uids); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_cparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + } + r = mailimap_cparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +static struct mailimap_qresync_vanished * get_vanished(mailimap * session) +{ + struct mailimap_qresync_vanished * vanished; + clistiter * cur; + + vanished = NULL; + for(cur = clist_begin(session->imap_response_info->rsp_extension_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_extension_data * ext_data; + + ext_data = clist_content(cur); + if (ext_data->ext_extension->ext_id != MAILIMAP_EXTENSION_QRESYNC) { + continue; + } + if (ext_data->ext_type != MAILIMAP_QRESYNC_TYPE_VANISHED) { + continue; + } + + vanished = ext_data->ext_data; + ext_data->ext_data = NULL; + break; + } + + return vanished; +} + +static uint64_t get_mod_sequence_value(mailimap * session) +{ + uint64_t mod_sequence_value; + clistiter * cur; + + mod_sequence_value = 0; + for(cur = clist_begin(session->imap_response_info->rsp_extension_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_extension_data * ext_data; + struct mailimap_condstore_resptextcode * resptextcode; + + ext_data = clist_content(cur); + if (ext_data->ext_extension->ext_id != MAILIMAP_EXTENSION_CONDSTORE) { + continue; + } + if (ext_data->ext_type != MAILIMAP_CONDSTORE_TYPE_RESP_TEXT_CODE) { + continue; + } + + resptextcode = ext_data->ext_data; + switch (resptextcode->cs_type) { + case MAILIMAP_CONDSTORE_RESPTEXTCODE_HIGHESTMODSEQ: + mod_sequence_value = resptextcode->cs_data.cs_modseq_value; + break; + case MAILIMAP_CONDSTORE_RESPTEXTCODE_NOMODSEQ: + mod_sequence_value = 0; + break; + } + } + + return mod_sequence_value; +} + +int mailimap_select_qresync(mailimap * session, const char * mb, + uint32_t uidvalidity, uint64_t modseq_value, + struct mailimap_set * known_uids, + struct mailimap_set * seq_match_data_sequences, + struct mailimap_set * seq_match_data_uids, + clist ** fetch_result, struct mailimap_qresync_vanished ** p_vanished, + uint64_t * p_mod_sequence_value) +{ + struct mailimap_response * response; + int r; + int error_code; + uint64_t mod_sequence_value; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_select_qresync_send(session->imap_stream, mb, uidvalidity, modseq_value, + known_uids, seq_match_data_sequences, seq_match_data_uids); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + if (session->imap_selection_info != NULL) + mailimap_selection_info_free(session->imap_selection_info); + session->imap_selection_info = mailimap_selection_info_new(); + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * fetch_result = session->imap_response_info->rsp_fetch_list; + session->imap_response_info->rsp_fetch_list = NULL; + if (p_vanished != NULL) { + * p_vanished = get_vanished(session); + } + + mod_sequence_value = get_mod_sequence_value(session); + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + session->imap_state = MAILIMAP_STATE_SELECTED; + * p_mod_sequence_value = mod_sequence_value; + return MAILIMAP_NO_ERROR; + + default: + mailimap_selection_info_free(session->imap_selection_info); + session->imap_selection_info = NULL; + session->imap_state = MAILIMAP_STATE_AUTHENTICATED; + * p_mod_sequence_value = mod_sequence_value; + if (* fetch_result != NULL) { + mailimap_fetch_list_free(* fetch_result); + } + if (p_vanished != NULL) { + if (* p_vanished != NULL) { + mailimap_qresync_vanished_free(* p_vanished); + } + } + return MAILIMAP_ERROR_SELECT; + } +} + +int mailimap_fetch_qresync(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, uint64_t mod_sequence_value, + clist ** fetch_result, struct mailimap_qresync_vanished ** p_vanished) +{ + return mailimap_fetch_qresync_vanished(session, set, fetch_type, mod_sequence_value, 1, + fetch_result, p_vanished); +} + +static int send_fetch_param(mailstream * fd, uint64_t mod_sequence_value, int vanished) +{ + int r; + + if (mod_sequence_value == 0) + return MAILIMAP_NO_ERROR; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_oparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_send(fd, "CHANGEDSINCE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mod_sequence_value_send(fd, mod_sequence_value); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (vanished) { + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_token_send(fd, "VANISHED"); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_cparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_fetch_qresync_vanished(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, uint64_t mod_sequence_value, int vanished, + clist ** fetch_result, struct mailimap_qresync_vanished ** p_vanished) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_fetch_send(session->imap_stream, set, fetch_type); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = send_fetch_param(session->imap_stream, mod_sequence_value, vanished); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * fetch_result = session->imap_response_info->rsp_fetch_list; + session->imap_response_info->rsp_fetch_list = NULL; + if (p_vanished != NULL) { + * p_vanished = get_vanished(session); + } + + if (* fetch_result == NULL || clist_count(* fetch_result) == 0) { + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + } + else { + error_code = MAILIMAP_RESP_COND_STATE_OK; + } + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + if (* fetch_result != NULL) { + mailimap_fetch_list_free(* fetch_result); + } + if (p_vanished != NULL && * p_vanished != NULL) { + mailimap_qresync_vanished_free(* p_vanished); + } + return MAILIMAP_ERROR_FETCH; + } +} + +int mailimap_uid_fetch_qresync(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, uint64_t mod_sequence_value, + clist ** fetch_result, struct mailimap_qresync_vanished ** p_vanished) +{ + return mailimap_uid_fetch_qresync_vanished(session, set, fetch_type, mod_sequence_value, 1, + fetch_result, p_vanished); +} + +int mailimap_uid_fetch_qresync_vanished(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, uint64_t mod_sequence_value, int vanished, + clist ** fetch_result, struct mailimap_qresync_vanished ** p_vanished) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uid_fetch_send(session->imap_stream, set, fetch_type); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = send_fetch_param(session->imap_stream, mod_sequence_value, vanished); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + * fetch_result = session->imap_response_info->rsp_fetch_list; + session->imap_response_info->rsp_fetch_list = NULL; + if (p_vanished != NULL) { + * p_vanished = get_vanished(session); + } + + if (* fetch_result == NULL || clist_count(* fetch_result) == 0) { + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + } + else { + error_code = MAILIMAP_RESP_COND_STATE_OK; + } + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + if (* fetch_result != NULL) { + mailimap_fetch_list_free(* fetch_result); + } + if (p_vanished != NULL) { + if (* p_vanished != NULL) { + mailimap_qresync_vanished_free(* p_vanished); + } + } + return MAILIMAP_ERROR_UID_FETCH; + } +} + +int mailimap_has_qresync(mailimap * session) +{ + return mailimap_has_extension(session, "QRESYNC"); +} + +static void + mailimap_qresync_extension_data_free(struct mailimap_extension_data * ext_data) +{ + switch (ext_data->ext_type) { + case MAILIMAP_QRESYNC_TYPE_VANISHED: + if (ext_data->ext_data != NULL) { + mailimap_qresync_vanished_free(ext_data->ext_data); + } + break; + case MAILIMAP_QRESYNC_TYPE_RESP_TEXT_CODE: + if (ext_data->ext_data != NULL) { + mailimap_qresync_resptextcode_free(ext_data->ext_data); + } + break; + } + + free(ext_data); +} + +static int resp_text_code_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_qresync_resptextcode ** result); + +static int vanished_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_qresync_vanished ** result); + +static int + mailimap_qresync_extension_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, progress_function * progr_fun) +{ + size_t cur_token; + int r; + + cur_token = * indx; + + switch (calling_parser) { + case MAILIMAP_EXTENDED_PARSER_RESP_TEXT_CODE: { + struct mailimap_qresync_resptextcode * resptextcode; + struct mailimap_extension_data * ext_data; + + r = resp_text_code_parse(fd, buffer, parser_ctx, &cur_token, &resptextcode); + if (r != MAILIMAP_NO_ERROR) + return r; + ext_data = mailimap_extension_data_new(&mailimap_extension_qresync, + MAILIMAP_QRESYNC_TYPE_RESP_TEXT_CODE, resptextcode); + if (ext_data == NULL) { + mailimap_qresync_resptextcode_free(resptextcode); + return MAILIMAP_ERROR_MEMORY; + } + * indx = cur_token; + * result = ext_data; + return MAILIMAP_NO_ERROR; + } + + case MAILIMAP_EXTENDED_PARSER_RESPONSE_DATA: { + struct mailimap_qresync_vanished * vanished; + struct mailimap_extension_data * ext_data; + + r = vanished_parse(fd, buffer, parser_ctx, &cur_token, &vanished); + if (r != MAILIMAP_NO_ERROR) + return r; + ext_data = mailimap_extension_data_new(&mailimap_extension_qresync, + MAILIMAP_QRESYNC_TYPE_VANISHED, vanished); + if (ext_data == NULL) { + mailimap_qresync_vanished_free(vanished); + return MAILIMAP_ERROR_MEMORY; + } + * indx = cur_token; + * result = ext_data; + return MAILIMAP_NO_ERROR; + } + } + + return MAILIMAP_ERROR_PARSE; +} + +static int resp_text_code_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_qresync_resptextcode ** result) +{ + int r; + size_t cur_token; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "CLOSED"); + if (r == MAILIMAP_NO_ERROR) { + struct mailimap_qresync_resptextcode * resptextcode; + + resptextcode = mailimap_qresync_resptextcode_new(MAILIMAP_QRESYNC_RESPTEXTCODE_CLOSED); + if (resptextcode == NULL) + return MAILIMAP_ERROR_MEMORY; + + * indx = cur_token; + * result = resptextcode; + + return MAILIMAP_NO_ERROR; + } + + return MAILIMAP_ERROR_PARSE; +} + +/* +expunged-resp = "VANISHED" [SP "(EARLIER)"] SP known-uids +*/ + +static int vanished_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_qresync_vanished ** result) +{ + int r; + struct mailimap_set * set; + int earlier; + struct mailimap_qresync_vanished * vanished; + size_t cur_token; + int res; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "VANISHED"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + earlier = 0; + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "(EARLIER)"); + if (r == MAILIMAP_NO_ERROR) { + earlier = 1; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + } + + r = mailimap_set_parse(fd, buffer, parser_ctx, &cur_token, &set); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + vanished = mailimap_qresync_vanished_new(earlier, set); + if (vanished == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_set; + } + + * indx = cur_token; + * result = vanished; + + return MAILIMAP_NO_ERROR; + + free_set: + mailimap_set_free(set); + err: + return res; +} diff --git a/Sources/libetpan/low-level/imap/qresync.h b/Sources/libetpan/low-level/imap/qresync.h new file mode 100644 index 00000000..edbdb6d1 --- /dev/null +++ b/Sources/libetpan/low-level/imap/qresync.h @@ -0,0 +1,75 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2013 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef QRESYNC_H + +#define QRESYNC_H + +#include +#include +#include +#include + +LIBETPAN_EXPORT +extern struct mailimap_extension_api mailimap_extension_qresync; + +/* +mailimap_select_qresync() +known_uids can be NULL +seq_match_data_sequences can be NULL +seq_match_data_uids can be NULL +*/ + +LIBETPAN_EXPORT + int mailimap_select_qresync(mailimap * session, const char * mb, + uint32_t uidvalidity, uint64_t modseq_value, + struct mailimap_set * known_uids, + struct mailimap_set * seq_match_data_sequences, + struct mailimap_set * seq_match_data_uids, + clist ** fetch_result, struct mailimap_qresync_vanished ** p_vanished, + uint64_t * p_mod_sequence_value); + +LIBETPAN_EXPORT +int mailimap_fetch_qresync(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, uint64_t mod_sequence_value, + clist ** fetch_result, struct mailimap_qresync_vanished ** p_vanished); + +LIBETPAN_EXPORT +int mailimap_uid_fetch_qresync(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, uint64_t mod_sequence_value, + clist ** fetch_result, struct mailimap_qresync_vanished ** p_vanished); + +LIBETPAN_EXPORT +int mailimap_has_qresync(mailimap * session); + +#endif diff --git a/Sources/libetpan/low-level/imap/qresync_private.h b/Sources/libetpan/low-level/imap/qresync_private.h new file mode 100644 index 00000000..14a5eaec --- /dev/null +++ b/Sources/libetpan/low-level/imap/qresync_private.h @@ -0,0 +1,46 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2013 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef QRESYNC_PRIVATE_H +#define QRESYNC_PRIVATE_H + +int mailimap_fetch_qresync_vanished(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, uint64_t mod_sequence_value, int vanished, + clist ** fetch_result, struct mailimap_qresync_vanished ** p_vanished); + +LIBETPAN_EXPORT +int mailimap_uid_fetch_qresync_vanished(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, uint64_t mod_sequence_value, int vanished, + clist ** fetch_result, struct mailimap_qresync_vanished ** p_vanished); + +#endif diff --git a/Sources/libetpan/low-level/imap/qresync_types.c b/Sources/libetpan/low-level/imap/qresync_types.c new file mode 100644 index 00000000..8a157dd7 --- /dev/null +++ b/Sources/libetpan/low-level/imap/qresync_types.c @@ -0,0 +1,78 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2013 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "qresync_types.h" + +#include + +#include "mailimap_types.h" + +LIBETPAN_EXPORT +struct mailimap_qresync_vanished * mailimap_qresync_vanished_new(int qr_earlier, struct mailimap_set * qr_known_uids) +{ + struct mailimap_qresync_vanished * vanished; + + vanished = malloc(sizeof(* vanished)); + if (vanished == NULL) + return vanished; + + vanished->qr_earlier = qr_earlier; + vanished->qr_known_uids = qr_known_uids; + + return vanished; +} + +LIBETPAN_EXPORT +void mailimap_qresync_vanished_free(struct mailimap_qresync_vanished * vanished) +{ + mailimap_set_free(vanished->qr_known_uids); + free(vanished); +} + +LIBETPAN_EXPORT +struct mailimap_qresync_resptextcode * mailimap_qresync_resptextcode_new(int qr_type) +{ + struct mailimap_qresync_resptextcode * resptextcode; + + resptextcode = malloc(sizeof(* resptextcode)); + if (resptextcode == NULL) + return resptextcode; + + resptextcode->qr_type = qr_type; + + return resptextcode; +} + +LIBETPAN_EXPORT +void mailimap_qresync_resptextcode_free(struct mailimap_qresync_resptextcode * resptextcode) +{ + free(resptextcode); +} diff --git a/Sources/libetpan/low-level/imap/qresync_types.h b/Sources/libetpan/low-level/imap/qresync_types.h new file mode 100644 index 00000000..dce137c9 --- /dev/null +++ b/Sources/libetpan/low-level/imap/qresync_types.h @@ -0,0 +1,68 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2013 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef QRESYNC_TYPES_H + +#define QRESYNC_TYPES_H + +#include + +enum { + MAILIMAP_QRESYNC_TYPE_VANISHED, + MAILIMAP_QRESYNC_TYPE_RESP_TEXT_CODE +}; + +struct mailimap_qresync_vanished { + int qr_earlier; + struct mailimap_set * qr_known_uids; +}; + +enum { + MAILIMAP_QRESYNC_RESPTEXTCODE_CLOSED +}; + +struct mailimap_qresync_resptextcode { + int qr_type; +}; + +LIBETPAN_EXPORT +struct mailimap_qresync_vanished * mailimap_qresync_vanished_new(int qr_earlier, struct mailimap_set * qr_known_uids); + +LIBETPAN_EXPORT +void mailimap_qresync_vanished_free(struct mailimap_qresync_vanished * vanished); + +LIBETPAN_EXPORT +struct mailimap_qresync_resptextcode * mailimap_qresync_resptextcode_new(int qr_type); + +LIBETPAN_EXPORT +void mailimap_qresync_resptextcode_free(struct mailimap_qresync_resptextcode * resptextcode); + +#endif diff --git a/Sources/libetpan/low-level/imap/quota.c b/Sources/libetpan/low-level/imap/quota.c new file mode 100644 index 00000000..c4f5929d --- /dev/null +++ b/Sources/libetpan/low-level/imap/quota.c @@ -0,0 +1,185 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailimap.h" +#include "mailimap_extension.h" +#include "quota.h" +#include "quota_types.h" +#include "quota_parser.h" +#include "quota_sender.h" + +#include + +LIBETPAN_EXPORT +struct mailimap_extension_api mailimap_extension_quota = { + /* name */ "QUOTA", + /* extension_id */ MAILIMAP_EXTENSION_QUOTA, + /* parser */ mailimap_quota_parse, + /* free */ mailimap_quota_free +}; + +/* + this is one of the imap commands quota adds. +*/ +LIBETPAN_EXPORT +int mailimap_quota_getquotaroot(mailimap * session, + const char * list_mb, + struct mailimap_quota_complete_data ** result) +{ + struct mailimap_response * response; + struct mailimap_extension_data * ext_data; + clistiter * cur; + int r; + int error_code; + struct mailimap_quota_quotaroot_data * quotaroot_data = NULL; + clist * quota_list = NULL; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_quota_getquotaroot_send(session->imap_stream, + list_mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + quota_list = clist_new(); + if (quota_list == NULL) + return MAILIMAP_ERROR_MEMORY; + + for (cur = clist_begin(session->imap_response_info->rsp_extension_list); + cur != NULL; cur = clist_next(cur)) { + ext_data = (struct mailimap_extension_data *) clist_content(cur); + if (ext_data->ext_extension->ext_id == MAILIMAP_EXTENSION_QUOTA) { + if (ext_data->ext_type == MAILIMAP_QUOTA_TYPE_QUOTA_DATA) { + r = clist_append(quota_list, ext_data->ext_data); + if (r != 0) { + clist_foreach(quota_list, + (clist_func) &mailimap_quota_quota_data_free, NULL); + clist_free(quota_list); + if (quotaroot_data) + mailimap_quota_quotaroot_data_free(quotaroot_data); + clist_foreach(session->imap_response_info->rsp_extension_list, + (clist_func) mailimap_extension_data_free, NULL); + clist_free(session->imap_response_info->rsp_extension_list); + session->imap_response_info->rsp_extension_list = NULL; + mailimap_response_free(response); + return MAILIMAP_ERROR_MEMORY; + } + ext_data->ext_data = NULL; + ext_data->ext_type = -1; + } else if (ext_data->ext_type == MAILIMAP_QUOTA_TYPE_QUOTAROOT_DATA) { + if (!quotaroot_data) { + quotaroot_data = ext_data->ext_data; + ext_data->ext_data = NULL; + ext_data->ext_type = -1; + } + } + } + } + + clist_foreach(session->imap_response_info->rsp_extension_list, + (clist_func) mailimap_extension_data_free, NULL); + clist_free(session->imap_response_info->rsp_extension_list); + session->imap_response_info->rsp_extension_list = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + if (!quotaroot_data) { + clist_foreach(quota_list, + (clist_func) &mailimap_quota_quota_data_free, NULL); + clist_free(quota_list); + return MAILIMAP_ERROR_EXTENSION; + } + + * result = mailimap_quota_complete_data_new(quotaroot_data, quota_list); + if (!*result) { + clist_foreach(quota_list, + (clist_func) &mailimap_quota_quota_data_free, NULL); + clist_free(quota_list); + mailimap_quota_quotaroot_data_free(quotaroot_data); + return MAILIMAP_ERROR_MEMORY; + } + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_EXTENSION; + } +} + +void +mailimap_quota_free(struct mailimap_extension_data * ext_data) +{ + switch (ext_data->ext_type) { + case MAILIMAP_QUOTA_TYPE_QUOTA_DATA: + mailimap_quota_quota_data_free(ext_data->ext_data); + break; + + case MAILIMAP_QUOTA_TYPE_QUOTAROOT_DATA: + mailimap_quota_quotaroot_data_free(ext_data->ext_data); + break; + } + + free(ext_data); +} + +LIBETPAN_EXPORT +int mailimap_has_quota(mailimap * session) +{ + return mailimap_has_extension(session, "QUOTA"); +} + diff --git a/Sources/libetpan/low-level/imap/quota.h b/Sources/libetpan/low-level/imap/quota.h new file mode 100644 index 00000000..8ffe4c85 --- /dev/null +++ b/Sources/libetpan/low-level/imap/quota.h @@ -0,0 +1,62 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef QUOTA_H + +#define QUOTA_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +LIBETPAN_EXPORT +extern struct mailimap_extension_api mailimap_extension_quota; + +void +mailimap_quota_free(struct mailimap_extension_data * ext_data); + +LIBETPAN_EXPORT +int mailimap_quota_getquotaroot(mailimap * session, + const char * list_mb, + struct mailimap_quota_complete_data ** result); + +LIBETPAN_EXPORT +int mailimap_has_quota(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/quota_parser.c b/Sources/libetpan/low-level/imap/quota_parser.c new file mode 100644 index 00000000..95226b0c --- /dev/null +++ b/Sources/libetpan/low-level/imap/quota_parser.c @@ -0,0 +1,428 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "quota_parser.h" +#include "mailimap_keywords.h" +#include "mailimap_extension.h" +#include "quota.h" +#include "quota_parser.h" + +#include + +int +mailimap_quota_quota_resource_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, void * result_ptr, + size_t progr_rate, progress_function * progr_fun) +{ + struct mailimap_quota_quota_resource ** result = result_ptr; + size_t cur_token = * indx; + int r, res; + char * resource_name; + uint32_t usage, limit; + struct mailimap_quota_quota_resource * resource; + + r = mailimap_atom_parse(fd, buffer, parser_ctx, &cur_token, &resource_name, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto resource_name_free; + } + + r = mailimap_number_parse(fd, buffer, &cur_token, &usage); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto resource_name_free; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto resource_name_free; + } + + r = mailimap_number_parse(fd, buffer, &cur_token, &limit); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto resource_name_free; + } + + resource = mailimap_quota_quota_resource_new(resource_name, + usage, limit); + if (!resource) { + res = r; + goto resource_name_free; + } + + * result = resource; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + resource_name_free: + mailimap_atom_free(resource_name); + err: + return res; +} + +static int +mailimap_quota_quota_list_nonempty_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, clist ** result, + size_t progr_rate, progress_function * progr_fun) +{ + size_t cur_token; + int r; + int res; + clist * quota_resource_list; + + cur_token = * indx; + + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, + &cur_token, "a_resource_list, + &mailimap_quota_quota_resource_parse, + (mailimap_struct_destructor *) + &mailimap_quota_quota_resource_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto quota_list_free; + } + + * result = quota_resource_list; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + quota_list_free: + clist_foreach(quota_resource_list, + (clist_func) &mailimap_quota_quota_resource_free, NULL); + clist_free(quota_resource_list); + err: + return res; +} + +static int +mailimap_quota_quota_list_empty_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, clist ** result, + size_t progr_rate, progress_function * progr_fun) +{ + size_t cur_token; + int r; + clist * quota_resource_list; + + cur_token = * indx; + + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + quota_resource_list = clist_new(); + if (!quota_resource_list) { + return MAILIMAP_ERROR_MEMORY; + } + + * result = quota_resource_list; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +static int +mailimap_quota_quota_list_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, clist ** result, + size_t progr_rate, progress_function * progr_fun) +{ + int r; + + r = mailimap_quota_quota_list_empty_parse(fd, buffer, parser_ctx, indx, result, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) { + return r; + } + + return mailimap_quota_quota_list_nonempty_parse(fd, buffer, parser_ctx, indx, result, + progr_rate, progr_fun); +} + +static int +mailimap_quota_quota_response_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_quota_quota_data ** result, + size_t progr_rate, progress_function * progr_fun) +{ + size_t cur_token; + char * quotaroot; + clist * quota_list; + struct mailimap_quota_quota_data * quota_data; + int r; + int res; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "QUOTA"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_astring_parse(fd, buffer, parser_ctx, &cur_token, "aroot, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto quotaroot_free; + } + + r = mailimap_quota_quota_list_parse(fd, buffer, parser_ctx, &cur_token, + "a_list, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto quotaroot_free; + } + + quota_data = mailimap_quota_quota_data_new(quotaroot, quota_list); + if (quota_data == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto quota_list_free; + } + + * result = quota_data; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + quota_list_free: + clist_foreach(quota_list, + (clist_func) &mailimap_quota_quota_resource_free, NULL); + clist_free(quota_list); + quotaroot_free: + mailimap_astring_free(quotaroot); + err: + return res; +} + +static int +mailimap_quota_quotaroot_response_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_quota_quotaroot_data ** result, + size_t progr_rate, progress_function * progr_fun) +{ + size_t cur_token; + char * mailbox; + char * quotaroot; + clist * quotaroot_list; + struct mailimap_quota_quotaroot_data * quotaroot_data; + int r; + int res; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "QUOTAROOT"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_mailbox_parse(fd, buffer, parser_ctx, &cur_token, &mailbox, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + quotaroot_list = clist_new(); + if (!quotaroot_list) { + res = MAILIMAP_ERROR_MEMORY; + goto mailbox_free; + } + + for (;;) { + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_ERROR_PARSE) { + break; + } else if (r != MAILIMAP_NO_ERROR) { + res = r; + goto quotaroot_list_free; + } + + r = mailimap_astring_parse(fd, buffer, parser_ctx, &cur_token, "aroot, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto quotaroot_list_free; + } + + if (clist_append(quotaroot_list, quotaroot) < 0) { + mailimap_astring_free(quotaroot); + res = MAILIMAP_ERROR_MEMORY; + goto quotaroot_list_free; + } + } + + quotaroot_data = mailimap_quota_quotaroot_data_new(mailbox, + quotaroot_list); + if (quotaroot_data == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto quotaroot_list_free; + } + + * result = quotaroot_data; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + quotaroot_list_free: + clist_foreach(quotaroot_list, + (clist_func) &mailimap_astring_free, NULL); + clist_free(quotaroot_list); + mailbox_free: + mailimap_mailbox_free(mailbox); + err: + return res; +} + +/* + this is the extension's initial parser. it switches on calling_parser + and calls the corresponding actual parser. quota extends + imap as follows: + mailbox-data /= "*" SP quota_response CRLF / + "*" SP quotaroot_response CRLF + + quota_response ::= "QUOTA" SP astring SP quota_list + + quotaroot_response ::= "QUOTAROOT" SP astring *(SP astring) + + quota_list ::= "(" #quota_resource ")" + + note that RFC2087 doesn't actually specify whether the responses augment + mailbox-data or augment the cases in response-data; I have chosen to + place them in mailbox-data (the difference is academic as the byte stream + is identical in either case) +*/ +int mailimap_quota_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int r; + struct mailimap_quota_quota_data * quota_data = 0; + struct mailimap_quota_quotaroot_data * quotaroot_data = 0; + void * data; + int type; + + switch (calling_parser) + { + case MAILIMAP_EXTENDED_PARSER_MAILBOX_DATA: + r = mailimap_quota_quota_response_parse(fd, buffer, parser_ctx, indx, + "a_data, progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) { + type = MAILIMAP_QUOTA_TYPE_QUOTA_DATA; + data = quota_data; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_quota_quotaroot_response_parse(fd, buffer, parser_ctx, indx, + "aroot_data, progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) { + type = MAILIMAP_QUOTA_TYPE_QUOTAROOT_DATA; + data = quotaroot_data; + } + } + + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + * result = mailimap_extension_data_new(&mailimap_extension_quota, + type, data); + if (*result == NULL) { + if (quota_data) + mailimap_quota_quota_data_free(quota_data); + if (quotaroot_data) + mailimap_quota_quotaroot_data_free(quotaroot_data); + return MAILIMAP_ERROR_MEMORY; + } + break; + default: + /* return a MAILIMAP_ERROR_PARSE if the extension + doesn't extend calling_parser. */ + return MAILIMAP_ERROR_PARSE; + break; + } + + return MAILIMAP_NO_ERROR; +} + diff --git a/Sources/libetpan/low-level/imap/quota_parser.h b/Sources/libetpan/low-level/imap/quota_parser.h new file mode 100644 index 00000000..a2f67f4b --- /dev/null +++ b/Sources/libetpan/low-level/imap/quota_parser.h @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef QUOTA_PARSER_H + +#define QUOTA_PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_parser.h" +#include "quota_types.h" + +int +mailimap_quota_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, progress_function * progr_fun); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/quota_sender.c b/Sources/libetpan/low-level/imap/quota_sender.c new file mode 100644 index 00000000..45f92aef --- /dev/null +++ b/Sources/libetpan/low-level/imap/quota_sender.c @@ -0,0 +1,79 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailimap_sender.h" +#include "quota_sender.h" +#include "quota_types.h" + +int mailimap_quota_getquota_send(mailstream * fd, + const char * quotaroot) +{ + int r; + + r = mailimap_token_send(fd, "GETQUOTA"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_astring_send(fd, quotaroot); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_quota_getquotaroot_send(mailstream * fd, + const char * list_mb) +{ + int r; + + r = mailimap_token_send(fd, "GETQUOTAROOT"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, list_mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + diff --git a/Sources/libetpan/low-level/imap/quota_sender.h b/Sources/libetpan/low-level/imap/quota_sender.h new file mode 100644 index 00000000..130eaf70 --- /dev/null +++ b/Sources/libetpan/low-level/imap/quota_sender.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef QUOTA_SENDER_H + +#define QUOTA_SENDER_H + +#include "mailimap_sender.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int mailimap_quota_getquota_send(mailstream * fd, + const char * quotaroot); + +int mailimap_quota_getquotaroot_send(mailstream * fd, + const char * list_mb); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/quota_types.c b/Sources/libetpan/low-level/imap/quota_types.c new file mode 100644 index 00000000..338b8025 --- /dev/null +++ b/Sources/libetpan/low-level/imap/quota_types.c @@ -0,0 +1,151 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailimap_types.h" +#include "quota_types.h" +#include "mailimap_extension.h" + +#include +#include + +LIBETPAN_EXPORT +struct mailimap_quota_quota_resource * +mailimap_quota_quota_resource_new(char * resource_name, + uint32_t usage, uint32_t limit) +{ + struct mailimap_quota_quota_resource * res; + + res = malloc(sizeof(* res)); + if (!res) + return NULL; + + res->resource_name = resource_name; + res->usage = usage; + res->limit = limit; + + return res; +} + +LIBETPAN_EXPORT +void +mailimap_quota_quota_resource_free( + struct mailimap_quota_quota_resource * res) { + mailimap_atom_free(res->resource_name); + free(res); +} + +LIBETPAN_EXPORT +struct mailimap_quota_quota_data * +mailimap_quota_quota_data_new(char * quotaroot, clist * quota_list) +{ + struct mailimap_quota_quota_data * data; + + data = malloc(sizeof(* data)); + if (!data) + return NULL; + + data->quotaroot = quotaroot; + data->quota_list = quota_list; + + return data; +} + +LIBETPAN_EXPORT +void +mailimap_quota_quota_data_free(struct mailimap_quota_quota_data * data) +{ + mailimap_astring_free(data->quotaroot); + clist_foreach(data->quota_list, + (clist_func) &mailimap_quota_quota_resource_free, NULL); + clist_free(data->quota_list); + free(data); +} + +LIBETPAN_EXPORT +struct mailimap_quota_quotaroot_data * +mailimap_quota_quotaroot_data_new(char * mailbox, clist * quotaroot_list) +{ + struct mailimap_quota_quotaroot_data * data; + + data = malloc(sizeof(* data)); + if (!data) + return NULL; + + data->mailbox = mailbox; + data->quotaroot_list = quotaroot_list; + + return data; +} + +LIBETPAN_EXPORT +void +mailimap_quota_quotaroot_data_free(struct mailimap_quota_quotaroot_data * data) +{ + mailimap_mailbox_free(data->mailbox); + clist_foreach(data->quotaroot_list, + (clist_func) &mailimap_astring_free, NULL); + clist_free(data->quotaroot_list); + free(data); +} + +LIBETPAN_EXPORT +struct mailimap_quota_complete_data * +mailimap_quota_complete_data_new( + struct mailimap_quota_quotaroot_data * quotaroot_data, + clist * quota_list) +{ + struct mailimap_quota_complete_data * data; + + data = malloc(sizeof(* data)); + if (!data) + return NULL; + + data->quotaroot_data = quotaroot_data; + data->quota_list = quota_list; + + return data; +} + +LIBETPAN_EXPORT +void +mailimap_quota_complete_data_free(struct mailimap_quota_complete_data * data) +{ + mailimap_quota_quotaroot_data_free(data->quotaroot_data); + clist_foreach(data->quota_list, + (clist_func) &mailimap_quota_quota_data_free, NULL); + clist_free(data->quota_list); + free(data); +} + diff --git a/Sources/libetpan/low-level/imap/quota_types.h b/Sources/libetpan/low-level/imap/quota_types.h new file mode 100644 index 00000000..0f57d8ca --- /dev/null +++ b/Sources/libetpan/low-level/imap/quota_types.h @@ -0,0 +1,121 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef QUOTA_TYPES_H + +#define QUOTA_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +struct mailimap_quota_quota_resource { + char * resource_name; + uint32_t usage; + uint32_t limit; +}; + +LIBETPAN_EXPORT +struct mailimap_quota_quota_resource * +mailimap_quota_quota_resource_new(char * resource_name, + uint32_t usage, uint32_t limit); + +LIBETPAN_EXPORT +void +mailimap_quota_quota_resource_free(struct mailimap_quota_quota_resource * res); + + + +struct mailimap_quota_quota_data { + char * quotaroot; + clist * quota_list; + /* list of (struct mailimap_quota_quota_resource *) */ +}; + +LIBETPAN_EXPORT +struct mailimap_quota_quota_data * +mailimap_quota_quota_data_new(char * quotaroot, clist * quota_list); + +LIBETPAN_EXPORT +void +mailimap_quota_quota_data_free(struct mailimap_quota_quota_data * data); + + + +struct mailimap_quota_quotaroot_data { + char * mailbox; + clist * quotaroot_list; + /* list of (char *) */ +}; + +LIBETPAN_EXPORT +struct mailimap_quota_quotaroot_data * +mailimap_quota_quotaroot_data_new(char * mailbox, clist * quotaroot_list); + +LIBETPAN_EXPORT +void +mailimap_quota_quotaroot_data_free( + struct mailimap_quota_quotaroot_data * data); + + + +enum { + MAILIMAP_QUOTA_TYPE_QUOTA_DATA, /* child of mailbox-data */ + MAILIMAP_QUOTA_TYPE_QUOTAROOT_DATA /* child of mailbox-data */ +}; + + + +struct mailimap_quota_complete_data { + struct mailimap_quota_quotaroot_data * quotaroot_data; + clist * quota_list; + /* list of (struct mailimap_quota_quota_data *) */ +}; + +LIBETPAN_EXPORT +struct mailimap_quota_complete_data * +mailimap_quota_complete_data_new( + struct mailimap_quota_quotaroot_data * quotaroot_data, + clist * quota_list); + +LIBETPAN_EXPORT +void +mailimap_quota_complete_data_free(struct mailimap_quota_complete_data * data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/uidplus.c b/Sources/libetpan/low-level/imap/uidplus.c new file mode 100644 index 00000000..d75b95fe --- /dev/null +++ b/Sources/libetpan/low-level/imap/uidplus.c @@ -0,0 +1,311 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailimap.h" +#include "mailimap_extension.h" +#include "uidplus.h" +#include "uidplus_types.h" +#include "uidplus_parser.h" +#include "mailimap_sender.h" +#include "uidplus_sender.h" + +#include +#include + +void +mailimap_uidplus_free(struct mailimap_extension_data * ext_data); + +LIBETPAN_EXPORT +struct mailimap_extension_api mailimap_extension_uidplus = { + /* name */ "UIDPLUS", + /* extension_id */ MAILIMAP_EXTENSION_UIDPLUS, + /* parser */ mailimap_uidplus_parse, + /* free */ mailimap_uidplus_free +}; + +LIBETPAN_EXPORT +int mailimap_uid_expunge(mailimap * session, struct mailimap_set * set) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uid_expunge_send(session->imap_stream, set); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_EXPUNGE; + } +} + +static void extract_copy_uid(mailimap * session, + uint32_t * uidvalidity_result, + struct mailimap_set ** source_result, + struct mailimap_set ** dest_result) +{ + clistiter * cur; + + * uidvalidity_result = 0; + * source_result = NULL; + * dest_result = NULL; + + if (session->imap_response_info == NULL) { + return; + } + + for(cur = clist_begin(session->imap_response_info->rsp_extension_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailimap_extension_data * ext_data; + struct mailimap_uidplus_resp_code_copy * resp_code_copy; + + ext_data = clist_content(cur); + if (ext_data->ext_extension != &mailimap_extension_uidplus) + continue; + + if (ext_data->ext_type != MAILIMAP_UIDPLUS_RESP_CODE_COPY) + continue; + + resp_code_copy = ext_data->ext_data; + + * uidvalidity_result = resp_code_copy->uid_uidvalidity; + * source_result = resp_code_copy->uid_source_set; + * dest_result = resp_code_copy->uid_dest_set; + resp_code_copy->uid_source_set = NULL; + resp_code_copy->uid_dest_set = NULL; + break; + } +} + +LIBETPAN_EXPORT +int mailimap_uidplus_copy(mailimap * session, struct mailimap_set * set, + const char * mb, + uint32_t * uidvalidity_result, + struct mailimap_set ** source_result, + struct mailimap_set ** dest_result) +{ + int r; + + r = mailimap_copy(session, set, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + extract_copy_uid(session, uidvalidity_result, source_result, dest_result); + + return MAILIMAP_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailimap_uidplus_uid_copy(mailimap * session, struct mailimap_set * set, + const char * mb, + uint32_t * uidvalidity_result, + struct mailimap_set ** source_result, + struct mailimap_set ** dest_result) +{ + int r; + + r = mailimap_uid_copy(session, set, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + extract_copy_uid(session, uidvalidity_result, source_result, dest_result); + + return MAILIMAP_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailimap_uidplus_move(mailimap * session, struct mailimap_set * set, + const char * mb, + uint32_t * uidvalidity_result, + struct mailimap_set ** source_result, + struct mailimap_set ** dest_result) +{ + int r; + + r = mailimap_move(session, set, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + extract_copy_uid(session, uidvalidity_result, source_result, dest_result); + + return MAILIMAP_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailimap_uidplus_uid_move(mailimap * session, struct mailimap_set * set, + const char * mb, + uint32_t * uidvalidity_result, + struct mailimap_set ** source_result, + struct mailimap_set ** dest_result) +{ + int r; + + r = mailimap_uid_move(session, set, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + extract_copy_uid(session, uidvalidity_result, source_result, dest_result); + + return MAILIMAP_NO_ERROR; +} + +static void extract_apnd_uid(mailimap * session, + uint32_t * uidvalidity_result, + struct mailimap_set ** result) +{ + clistiter * cur; + + * uidvalidity_result = 0; + * result = NULL; + + if (session->imap_response_info == NULL) { + return; + } + + for(cur = clist_begin(session->imap_response_info->rsp_extension_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailimap_extension_data * ext_data; + struct mailimap_uidplus_resp_code_apnd * resp_code_apnd; + + ext_data = clist_content(cur); + if (ext_data->ext_extension != &mailimap_extension_uidplus) + continue; + + if (ext_data->ext_type != MAILIMAP_UIDPLUS_RESP_CODE_APND) + continue; + + resp_code_apnd = ext_data->ext_data; + + * uidvalidity_result = resp_code_apnd->uid_uidvalidity; + * result = resp_code_apnd->uid_set; + resp_code_apnd->uid_set = NULL; + break; + } +} + +static void extract_apnd_single_uid(mailimap * session, + uint32_t * uidvalidity_result, + uint32_t * uid_result) +{ + struct mailimap_set * set; + + extract_apnd_uid(session, uidvalidity_result, &set); + * uid_result = 0; + if (set != NULL) { + clistiter * cur; + + cur = clist_begin(set->set_list); + if (cur != NULL) { + struct mailimap_set_item * item; + + item = clist_content(cur); + * uid_result = item->set_first; + } + mailimap_set_free(set); + } +} + +LIBETPAN_EXPORT +int mailimap_uidplus_append(mailimap * session, const char * mailbox, + struct mailimap_flag_list * flag_list, + struct mailimap_date_time * date_time, + const char * literal, size_t literal_size, + uint32_t * uidvalidity_result, + uint32_t * uid_result) +{ + int r; + + r = mailimap_append(session, mailbox, flag_list, date_time, + literal, literal_size); + if (r != MAILIMAP_NO_ERROR) + return r; + + extract_apnd_single_uid(session, uidvalidity_result, uid_result); + + return MAILIMAP_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailimap_uidplus_append_simple(mailimap * session, const char * mailbox, + const char * content, size_t size, + uint32_t * uidvalidity_result, + uint32_t * uid_result) +{ + int r; + + r = mailimap_append_simple(session, mailbox, + content, size); + if (r != MAILIMAP_NO_ERROR) + return r; + + extract_apnd_single_uid(session, uidvalidity_result, uid_result); + + return MAILIMAP_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailimap_has_uidplus(mailimap * session) +{ + return mailimap_has_extension(session, "UIDPLUS"); +} diff --git a/Sources/libetpan/low-level/imap/uidplus.h b/Sources/libetpan/low-level/imap/uidplus.h new file mode 100644 index 00000000..78e23747 --- /dev/null +++ b/Sources/libetpan/low-level/imap/uidplus.h @@ -0,0 +1,98 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef UIDPLUS_H + +#define UIDPLUS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +LIBETPAN_EXPORT +extern struct mailimap_extension_api mailimap_extension_uidplus; + +LIBETPAN_EXPORT +int mailimap_uid_expunge(mailimap * session, struct mailimap_set * set); + +LIBETPAN_EXPORT +int mailimap_uidplus_copy(mailimap * session, struct mailimap_set * set, + const char * mb, + uint32_t * uidvalidity_result, + struct mailimap_set ** source_result, + struct mailimap_set ** dest_result); + +LIBETPAN_EXPORT +int mailimap_uidplus_uid_copy(mailimap * session, struct mailimap_set * set, + const char * mb, + uint32_t * uidvalidity_result, + struct mailimap_set ** source_result, + struct mailimap_set ** dest_result); + +LIBETPAN_EXPORT +int mailimap_uidplus_move(mailimap * session, struct mailimap_set * set, + const char * mb, + uint32_t * uidvalidity_result, + struct mailimap_set ** source_result, + struct mailimap_set ** dest_result); + +LIBETPAN_EXPORT +int mailimap_uidplus_uid_move(mailimap * session, struct mailimap_set * set, + const char * mb, + uint32_t * uidvalidity_result, + struct mailimap_set ** source_result, + struct mailimap_set ** dest_result); + +LIBETPAN_EXPORT +int mailimap_uidplus_append(mailimap * session, const char * mailbox, + struct mailimap_flag_list * flag_list, + struct mailimap_date_time * date_time, + const char * literal, size_t literal_size, + uint32_t * uidvalidity_result, + uint32_t * uid_result); + +LIBETPAN_EXPORT +int mailimap_uidplus_append_simple(mailimap * session, const char * mailbox, + const char * content, size_t size, + uint32_t * uidvalidity_result, + uint32_t * uid_result); + +LIBETPAN_EXPORT +int mailimap_has_uidplus(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/uidplus_parser.c b/Sources/libetpan/low-level/imap/uidplus_parser.c new file mode 100644 index 00000000..0816acc5 --- /dev/null +++ b/Sources/libetpan/low-level/imap/uidplus_parser.c @@ -0,0 +1,411 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "uidplus_parser.h" + +#include +#include + +#include "mailimap_parser.h" +#include "mailimap_keywords.h" +#include "mailimap_extension.h" +#include "uidplus_types.h" +#include "uidplus.h" + +static int mailimap_uid_range_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_set_item ** result); + +static int mailimap_uidplus_resp_code_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_extension_data ** result); + +int mailimap_uidplus_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + if (calling_parser != MAILIMAP_EXTENDED_PARSER_RESP_TEXT_CODE) + return MAILIMAP_ERROR_PARSE; + + return mailimap_uidplus_resp_code_parse(fd, buffer, parser_ctx, indx, result); +} + + +/* + uid-set = (uniqueid / uid-range) *("," uid-set) +*/ + +static int uid_set_item_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_set_item ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int r; + struct mailimap_set_item * set_item; + uint32_t uniqueid; + size_t cur_token; + + cur_token = * indx; + + r = mailimap_uid_range_parse(fd, buffer, parser_ctx, &cur_token, &set_item); + if (r == MAILIMAP_NO_ERROR) { + * result = set_item; + * indx = cur_token; + return r; + } + + if (r != MAILIMAP_ERROR_PARSE) + return r; + + r = mailimap_uniqueid_parse(fd, buffer, parser_ctx, &cur_token, &uniqueid); + if (r == MAILIMAP_NO_ERROR) { + set_item = mailimap_set_item_new(uniqueid, uniqueid); + if (set_item == NULL) + return MAILIMAP_ERROR_MEMORY; + + * result = set_item; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + } + + return r; +} + +static void uid_set_item_destructor(struct mailimap_set_item * set_item) +{ + mailimap_set_item_free(set_item); +} + +static int mailimap_uid_set_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_set ** result) +{ + int r; + clist * list; + struct mailimap_set * set; + size_t cur_token; + + cur_token = * indx; + + r = mailimap_struct_list_parse(fd, buffer, parser_ctx, &cur_token, &list, + ',', + (mailimap_struct_parser *) uid_set_item_parse, + (mailimap_struct_destructor *) uid_set_item_destructor, + 0, NULL); + if (r != MAILIMAP_NO_ERROR) + return r; + + set = mailimap_set_new(list); + if (set == NULL) { + clistiter * cur; + + for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_set_item * item; + + item = clist_content(cur); + free(item); + } + clist_free(list); + return MAILIMAP_ERROR_MEMORY; + } + + * result = set; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + uid-range = (uniqueid ":" uniqueid) + ; two uniqueid values and all values + ; between these two regards of order. + ; Example: 2:4 and 4:2 are equivalent. +*/ + +static int mailimap_uid_range_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, struct mailimap_set_item ** result) +{ + uint32_t first; + uint32_t last; + int r; + struct mailimap_set_item * item; + size_t cur_token; + + cur_token = * indx; + + r = mailimap_uniqueid_parse(fd, buffer, parser_ctx, &cur_token, &first); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_colon_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uniqueid_parse(fd, buffer, parser_ctx, &cur_token, &last); + if (r != MAILIMAP_NO_ERROR) + return r; + + item = mailimap_set_item_new(first, last); + if (item == NULL) + return MAILIMAP_ERROR_MEMORY; + + * indx = cur_token; + * result = item; + + return MAILIMAP_NO_ERROR; +} + +/* + append-uid = uniqueid + + append-uid =/ uid-set + ; only permitted if client uses [MULTIAPPEND] + ; to append multiple messages. +*/ + +static int mailimap_append_uid_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_set ** result) +{ + return mailimap_uid_set_parse(fd, buffer, parser_ctx, indx, result); +} + +/* + resp-code-apnd = "APPENDUID" SP nz-number SP append-uid +*/ + +static int mailimap_resp_code_apnd_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_uidplus_resp_code_apnd ** result) +{ + int r; + size_t cur_token; + uint32_t uidvalidity; + struct mailimap_set * set; + struct mailimap_uidplus_resp_code_apnd * resp_code_apnd; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "APPENDUID"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_nz_number_parse(fd, buffer, parser_ctx, &cur_token, &uidvalidity); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_append_uid_parse(fd, buffer, parser_ctx, &cur_token, &set); + if (r != MAILIMAP_NO_ERROR) + return r; + + resp_code_apnd = mailimap_uidplus_resp_code_apnd_new(uidvalidity, set); + if (resp_code_apnd == NULL) { + mailimap_set_free(set); + return MAILIMAP_ERROR_MEMORY; + } + + * indx = cur_token; + * result = resp_code_apnd; + + return MAILIMAP_NO_ERROR; +} + +/* + resp-code-copy = "COPYUID" SP nz-number SP uid-set SP uid-set +*/ + +static int mailimap_resp_code_copy_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_uidplus_resp_code_copy ** result) +{ + int r; + size_t cur_token; + uint32_t uidvalidity; + struct mailimap_set * source_set; + struct mailimap_set * dest_set; + struct mailimap_uidplus_resp_code_copy * resp_code_copy; + int res; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "COPYUID"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_nz_number_parse(fd, buffer, parser_ctx, &cur_token, &uidvalidity); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_uid_set_parse(fd, buffer, parser_ctx, &cur_token, &source_set); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_source_set; + } + + r = mailimap_uid_set_parse(fd, buffer, parser_ctx, &cur_token, &dest_set); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_source_set; + } + + resp_code_copy = mailimap_uidplus_resp_code_copy_new(uidvalidity, + source_set, dest_set); + if (resp_code_copy == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_dest_set; + } + + * indx = cur_token; + * result = resp_code_copy; + + return MAILIMAP_NO_ERROR; + + free_dest_set: + mailimap_set_free(dest_set); + free_source_set: + mailimap_set_free(source_set); + err: + return res; +} + +/* + "UIDNOTSTICKY" +*/ + +static int mailimap_uidplus_uidnotsticky_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx) +{ + return mailimap_token_case_insensitive_parse(fd, buffer, indx, + "UIDNOTSTICKY"); +} + +/* + resp-text-code =/ resp-code-apnd / resp-code-copy / "UIDNOTSTICKY" + ; incorporated before the expansion rule of + ; atom [SP 1*] + ; that appears in [IMAP] +*/ + +static int mailimap_uidplus_resp_code_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_extension_data ** result) +{ + struct mailimap_uidplus_resp_code_apnd * resp_code_apnd; + struct mailimap_uidplus_resp_code_copy * resp_code_copy; + size_t cur_token; + struct mailimap_extension_data * ext; + int r; + + cur_token = * indx; + + resp_code_apnd = NULL; + r = mailimap_resp_code_apnd_parse(fd, buffer, parser_ctx, &cur_token, &resp_code_apnd); + if (r == MAILIMAP_NO_ERROR) { + ext = mailimap_extension_data_new(&mailimap_extension_uidplus, + MAILIMAP_UIDPLUS_RESP_CODE_APND, resp_code_apnd); + if (ext == NULL) { + mailimap_uidplus_resp_code_apnd_free(resp_code_apnd); + return MAILIMAP_ERROR_MEMORY; + } + + * indx = cur_token; + * result = ext; + + return MAILIMAP_NO_ERROR; + } + + resp_code_copy = NULL; + r = mailimap_resp_code_copy_parse(fd, buffer, parser_ctx, &cur_token, &resp_code_copy); + if (r == MAILIMAP_NO_ERROR) { + ext = mailimap_extension_data_new(&mailimap_extension_uidplus, + MAILIMAP_UIDPLUS_RESP_CODE_COPY, resp_code_copy); + if (ext == NULL) { + mailimap_uidplus_resp_code_copy_free(resp_code_copy); + return MAILIMAP_ERROR_MEMORY; + } + + * indx = cur_token; + * result = ext; + + return MAILIMAP_NO_ERROR; + } + + r = mailimap_uidplus_uidnotsticky_parse(fd, buffer, parser_ctx, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + ext = mailimap_extension_data_new(&mailimap_extension_uidplus, + MAILIMAP_UIDPLUS_RESP_CODE_UIDNOTSTICKY, resp_code_copy); + if (ext == NULL) { + mailimap_uidplus_resp_code_copy_free(resp_code_copy); + return MAILIMAP_ERROR_MEMORY; + } + + * indx = cur_token; + * result = ext; + + return MAILIMAP_NO_ERROR; + } + + return MAILIMAP_ERROR_PARSE; +} + diff --git a/Sources/libetpan/low-level/imap/uidplus_parser.h b/Sources/libetpan/low-level/imap/uidplus_parser.h new file mode 100644 index 00000000..833f0246 --- /dev/null +++ b/Sources/libetpan/low-level/imap/uidplus_parser.h @@ -0,0 +1,55 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef UIDPLUS_PARSER_H + +#define UIDPLUS_PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "mailstream_types.h" +#include "mmapstring.h" +#include "mailimap_types.h" +#include "mailimap_extension_types.h" + +int mailimap_uidplus_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/uidplus_sender.c b/Sources/libetpan/low-level/imap/uidplus_sender.c new file mode 100644 index 00000000..75d0a6f5 --- /dev/null +++ b/Sources/libetpan/low-level/imap/uidplus_sender.c @@ -0,0 +1,58 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "uidplus_sender.h" + +#include "mailimap_sender.h" + +int +mailimap_uid_expunge_send(mailstream * fd, + struct mailimap_set * set) +{ + int r; + + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_expunge_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_set_send(fd, set); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} diff --git a/Sources/libetpan/low-level/imap/uidplus_sender.h b/Sources/libetpan/low-level/imap/uidplus_sender.h new file mode 100644 index 00000000..79bf74dc --- /dev/null +++ b/Sources/libetpan/low-level/imap/uidplus_sender.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef UIDPLUS_SENDER_H + +#define UIDPLUS_SENDER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include "mailimap_types.h" +#include "mailstream_types.h" + +int +mailimap_uid_expunge_send(mailstream * fd, + struct mailimap_set * set); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/uidplus_types.c b/Sources/libetpan/low-level/imap/uidplus_types.c new file mode 100644 index 00000000..ffd270c4 --- /dev/null +++ b/Sources/libetpan/low-level/imap/uidplus_types.c @@ -0,0 +1,104 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "uidplus_types.h" + +#include +#include +#include "mailimap_extension_types.h" + +LIBETPAN_EXPORT +struct mailimap_uidplus_resp_code_apnd * mailimap_uidplus_resp_code_apnd_new(uint32_t uid_uidvalidity, struct mailimap_set * uid_set) +{ + struct mailimap_uidplus_resp_code_apnd * resp_code_apnd; + + resp_code_apnd = malloc(sizeof(* resp_code_apnd)); + if (resp_code_apnd == NULL) + return NULL; + + resp_code_apnd->uid_uidvalidity = uid_uidvalidity; + resp_code_apnd->uid_set = uid_set; + + return resp_code_apnd; +} + +LIBETPAN_EXPORT +void mailimap_uidplus_resp_code_apnd_free(struct mailimap_uidplus_resp_code_apnd * resp_code_apnd) +{ + if (resp_code_apnd->uid_set != NULL) + mailimap_set_free(resp_code_apnd->uid_set); + free(resp_code_apnd); +} + +LIBETPAN_EXPORT +struct mailimap_uidplus_resp_code_copy * +mailimap_uidplus_resp_code_copy_new(uint32_t uid_uidvalidity, struct mailimap_set * uid_source_set, struct mailimap_set * uid_dest_set) +{ + struct mailimap_uidplus_resp_code_copy * resp_code_copy; + + resp_code_copy = malloc(sizeof(* resp_code_copy)); + if (resp_code_copy == NULL) + return NULL; + + resp_code_copy->uid_uidvalidity = uid_uidvalidity; + resp_code_copy->uid_source_set = uid_source_set; + resp_code_copy->uid_dest_set = uid_dest_set; + + return resp_code_copy; +} + +LIBETPAN_EXPORT +void mailimap_uidplus_resp_code_copy_free(struct mailimap_uidplus_resp_code_copy * resp_code_copy) +{ + if (resp_code_copy->uid_dest_set != NULL) + mailimap_set_free(resp_code_copy->uid_dest_set); + if (resp_code_copy->uid_source_set != NULL) + mailimap_set_free(resp_code_copy->uid_source_set); + free(resp_code_copy); +} + +LIBETPAN_EXPORT +void mailimap_uidplus_free(struct mailimap_extension_data * ext_data) +{ + switch (ext_data->ext_type) { + case MAILIMAP_UIDPLUS_RESP_CODE_APND: + mailimap_uidplus_resp_code_apnd_free(ext_data->ext_data); + break; + case MAILIMAP_UIDPLUS_RESP_CODE_COPY: + mailimap_uidplus_resp_code_copy_free(ext_data->ext_data); + break; + case MAILIMAP_UIDPLUS_RESP_CODE_UIDNOTSTICKY: + /* nothing to deallocate */ + break; + } + + free(ext_data); +} + diff --git a/Sources/libetpan/low-level/imap/uidplus_types.h b/Sources/libetpan/low-level/imap/uidplus_types.h new file mode 100644 index 00000000..60ead974 --- /dev/null +++ b/Sources/libetpan/low-level/imap/uidplus_types.h @@ -0,0 +1,83 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef UIDPLUS_TYPES_H + +#define UIDPLUS_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef WIN32 +#include +#endif + +#include "mailimap_types.h" + +enum { + MAILIMAP_UIDPLUS_RESP_CODE_APND, + MAILIMAP_UIDPLUS_RESP_CODE_COPY, + MAILIMAP_UIDPLUS_RESP_CODE_UIDNOTSTICKY +}; + +struct mailimap_uidplus_resp_code_apnd { + uint32_t uid_uidvalidity; + struct mailimap_set * uid_set; +}; + +struct mailimap_uidplus_resp_code_copy { + uint32_t uid_uidvalidity; + struct mailimap_set * uid_source_set; + struct mailimap_set * uid_dest_set; +}; + +LIBETPAN_EXPORT +struct mailimap_uidplus_resp_code_apnd * +mailimap_uidplus_resp_code_apnd_new(uint32_t uid_uidvalidity, struct mailimap_set * uid_set); + +LIBETPAN_EXPORT +void mailimap_uidplus_resp_code_apnd_free(struct mailimap_uidplus_resp_code_apnd * resp_code_apnd); + +LIBETPAN_EXPORT +struct mailimap_uidplus_resp_code_copy * +mailimap_uidplus_resp_code_copy_new(uint32_t uid_uidvalidity, struct mailimap_set * uid_source_set, struct mailimap_set * uid_dest_set); + +LIBETPAN_EXPORT +void mailimap_uidplus_resp_code_copy_free(struct mailimap_uidplus_resp_code_copy * resp_code_copy); + +LIBETPAN_EXPORT +void mailimap_uidplus_free(struct mailimap_extension_data * ext_data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imap/xgmlabels.c b/Sources/libetpan/low-level/imap/xgmlabels.c new file mode 100644 index 00000000..76589d3c --- /dev/null +++ b/Sources/libetpan/low-level/imap/xgmlabels.c @@ -0,0 +1,464 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2011 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "xgmlabels.h" + +#include +#include +#include + +#include "clist.h" +#include "mailimap_types_helper.h" +#include "mailimap_extension.h" +#include "mailimap_keywords.h" +#include "mailimap_parser.h" +#include "mailimap_sender.h" +#include "mailimap.h" + +struct mailimap_fetch_att * mailimap_fetch_att_new_xgmlabels(void) +{ + char * keyword; + struct mailimap_fetch_att * att; + + keyword = strdup("X-GM-LABELS"); + if (keyword == NULL) + return NULL; + + att = mailimap_fetch_att_new_extension(keyword); + if (att == NULL) { + free(keyword); + return NULL; + } + + return att; +} + +int mailimap_has_xgmlabels(mailimap * session) +{ + return mailimap_has_extension(session, "X-GM-EXT-1"); +} + +struct mailimap_msg_att_xgmlabels * mailimap_msg_att_xgmlabels_new(clist * att_labels) +{ + struct mailimap_msg_att_xgmlabels * att; + + att = malloc(sizeof(* att)); + if (att == NULL) + return NULL; + + att->att_labels = att_labels; + + return att; +} + +void mailimap_msg_att_xgmlabels_free(struct mailimap_msg_att_xgmlabels * att) +{ + clist_foreach(att->att_labels, (clist_func) mailimap_astring_free, NULL); + clist_free(att->att_labels); + free(att); +} + +struct mailimap_msg_att_xgmlabels * mailimap_msg_att_xgmlabels_new_empty(void) +{ + clist * list; + struct mailimap_msg_att_xgmlabels * att; + + list = clist_new(); + if (list == NULL) + return NULL; + + att = mailimap_msg_att_xgmlabels_new(list); + if (att == NULL) { + clist_free(list); + return NULL; + } + + return att; +} + +int mailimap_msg_att_xgmlabels_add(struct mailimap_msg_att_xgmlabels * att, char * label) +{ + return clist_append(att->att_labels, label); +} + +enum { + MAILIMAP_XGMLABELS_TYPE_XGMLABELS +}; + +/* extension data structure */ + +static int +mailimap_xgmlabels_extension_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, progress_function * progr_fun); + +static void +mailimap_xgmlabels_extension_data_free(struct mailimap_extension_data * ext_data); + +LIBETPAN_EXPORT +struct mailimap_extension_api mailimap_extension_xgmlabels = { + /* name */ "X-GM-lABELS", + /* extension_id */ MAILIMAP_EXTENSION_XGMLABELS, + /* parser */ mailimap_xgmlabels_extension_parse, + /* free */ mailimap_xgmlabels_extension_data_free +}; + +static int mailimap_xgmlabels_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + clist ** result) +{ + size_t cur_token; + clist * list; + int r; + int res; + + cur_token = * indx; + + r = mailimap_oparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, parser_ctx, + &cur_token, &list, + (mailimap_struct_parser * ) mailimap_astring_parse, + (mailimap_struct_destructor * ) mailimap_astring_free, + 0, NULL); + if (r == MAILIMAP_ERROR_PARSE) { + list = clist_new(); + if (list == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto err; + } + } + else if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, parser_ctx, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list; + } + + * indx = cur_token; + * result = list; + + return MAILIMAP_NO_ERROR; + +free_list: + clist_foreach(list, (clist_func) mailimap_astring_free, NULL); + clist_free(list); +err: + return res; +} + +static int fetch_data_xgmlabels_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_msg_att_xgmlabels ** result) +{ + size_t cur_token; + struct mailimap_msg_att_xgmlabels * att; + clist * label_list; + int r; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "X-GM-LABELS"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_xgmlabels_parse(fd, buffer, parser_ctx, &cur_token, &label_list); + if (r != MAILIMAP_NO_ERROR) + return r; + + att = mailimap_msg_att_xgmlabels_new(label_list); + if (att == NULL) { + clist_foreach(label_list, (clist_func) mailimap_astring_free, NULL); + clist_free(label_list); + return MAILIMAP_ERROR_MEMORY; + } + + * indx = cur_token; + * result = att; + + return MAILIMAP_NO_ERROR; +} + +static int +mailimap_xgmlabels_extension_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, progress_function * progr_fun) +{ + size_t cur_token; + int type; + struct mailimap_msg_att_xgmlabels * att; + void * data; + struct mailimap_extension_data * ext_data; + int r; + + cur_token = * indx; + + switch (calling_parser) + { + case MAILIMAP_EXTENDED_PARSER_FETCH_DATA: + att = NULL; + r = fetch_data_xgmlabels_parse(fd, buffer, parser_ctx, &cur_token, &att); + if (r != MAILIMAP_NO_ERROR) + return r; + + type = MAILIMAP_XGMLABELS_TYPE_XGMLABELS; + data = att; + + ext_data = mailimap_extension_data_new(&mailimap_extension_xgmlabels, + type, data); + if (ext_data == NULL) { + if (att != NULL) + mailimap_msg_att_xgmlabels_free(att); + return MAILIMAP_ERROR_MEMORY; + } + + * result = ext_data; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_PARSE; + } +} + +static void +mailimap_xgmlabels_extension_data_free(struct mailimap_extension_data * ext_data) +{ + if (ext_data->ext_data != NULL) { + if (ext_data->ext_type == MAILIMAP_XGMLABELS_TYPE_XGMLABELS) { + mailimap_msg_att_xgmlabels_free((struct mailimap_msg_att_xgmlabels *) ext_data->ext_data); + } + } + free(ext_data); +} + +static int mailimap_msg_att_xgmlabels_send(mailstream * fd, struct mailimap_msg_att_xgmlabels * labels) +{ + int r; + + r = mailimap_oparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (labels->att_labels != NULL) { + r = mailimap_struct_spaced_list_send(fd, labels->att_labels, + (mailimap_struct_sender *) mailimap_astring_send); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_cparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +static int mailimap_store_xgmlabels_send(mailstream * fd, struct mailimap_set * set, + int fl_sign, int fl_silent, + struct mailimap_msg_att_xgmlabels * labels) +{ + int r; + + r = mailimap_token_send(fd, "STORE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_set_send(fd, set); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + switch (fl_sign) { + case 1: + r = mailimap_char_send(fd, '+'); + if (r != MAILIMAP_NO_ERROR) + return r; + break; + case -1: + r = mailimap_char_send(fd, '-'); + if (r != MAILIMAP_NO_ERROR) + return r; + break; + } + + r = mailimap_token_send(fd, "X-GM-LABELS"); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (fl_silent) { + r = mailimap_token_send(fd, ".SILENT"); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_msg_att_xgmlabels_send(fd, labels); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +static int mailimap_uid_store_xgmlabels_send(mailstream * fd, struct mailimap_set * set, + int fl_sign, int fl_silent, + struct mailimap_msg_att_xgmlabels * labels) +{ + int r; + + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return mailimap_store_xgmlabels_send(fd, set, fl_sign, fl_silent, labels); +} + +int +mailimap_store_xgmlabels(mailimap * session, + struct mailimap_set * set, + int fl_sign, int fl_silent, + struct mailimap_msg_att_xgmlabels * labels) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_store_xgmlabels_send(session->imap_stream, set, fl_sign, fl_silent, labels); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_STORE; + } +} + +int +mailimap_uid_store_xgmlabels(mailimap * session, + struct mailimap_set * set, + int fl_sign, int fl_silent, + struct mailimap_msg_att_xgmlabels * labels) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uid_store_xgmlabels_send(session->imap_stream, set, fl_sign, fl_silent, labels); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_UID_STORE; + } +} diff --git a/Sources/libetpan/low-level/imap/xgmlabels.h b/Sources/libetpan/low-level/imap/xgmlabels.h new file mode 100644 index 00000000..9b8aaee8 --- /dev/null +++ b/Sources/libetpan/low-level/imap/xgmlabels.h @@ -0,0 +1,85 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2011 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef XGMLABELS_H +#define XGMLABELS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + + struct mailimap_msg_att_xgmlabels { + clist * att_labels; /* != NULL */ + }; + + LIBETPAN_EXPORT + extern struct mailimap_extension_api mailimap_extension_xgmlabels; + + LIBETPAN_EXPORT + struct mailimap_fetch_att * mailimap_fetch_att_new_xgmlabels(void); + + LIBETPAN_EXPORT + int mailimap_has_xgmlabels(mailimap * session); + + LIBETPAN_EXPORT + struct mailimap_msg_att_xgmlabels * mailimap_msg_att_xgmlabels_new(clist * att_labels); + + LIBETPAN_EXPORT + struct mailimap_msg_att_xgmlabels * mailimap_msg_att_xgmlabels_new_empty(void); + + LIBETPAN_EXPORT + int mailimap_msg_att_xgmlabels_add(struct mailimap_msg_att_xgmlabels * att, char * label); + + LIBETPAN_EXPORT void mailimap_msg_att_xgmlabels_free(struct mailimap_msg_att_xgmlabels * att); + + LIBETPAN_EXPORT + int + mailimap_store_xgmlabels(mailimap * session, + struct mailimap_set * set, + int fl_sign, int fl_silent, + struct mailimap_msg_att_xgmlabels * labels); + + LIBETPAN_EXPORT + int + mailimap_uid_store_xgmlabels(mailimap * session, + struct mailimap_set * set, + int fl_sign, int fl_silent, + struct mailimap_msg_att_xgmlabels * labels); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/Sources/libetpan/low-level/imap/xgmmsgid.c b/Sources/libetpan/low-level/imap/xgmmsgid.c new file mode 100644 index 00000000..aca8c716 --- /dev/null +++ b/Sources/libetpan/low-level/imap/xgmmsgid.c @@ -0,0 +1,163 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "xgmmsgid.h" + +#include +#include +#include + +#include "clist.h" +#include "mailimap_types_helper.h" +#include "mailimap_extension.h" +#include "mailimap_keywords.h" +#include "mailimap_parser.h" +#include "mailimap_sender.h" +#include "mailimap.h" + +enum { + MAILIMAP_XGMMSGID_TYPE_MSGID +}; + +static int +mailimap_xgmmsgid_extension_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, progress_function * progr_fun); + +static void +mailimap_xgmmsgid_extension_data_free(struct mailimap_extension_data * ext_data); + +LIBETPAN_EXPORT +struct mailimap_extension_api mailimap_extension_xgmmsgid = { + /* name */ "X-GM-MSGID", + /* extension_id */ MAILIMAP_EXTENSION_XGMMSGID, + /* parser */ mailimap_xgmmsgid_extension_parse, + /* free */ mailimap_xgmmsgid_extension_data_free +}; + +static int fetch_data_xgmmsgid_parse(mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + uint64_t * result, size_t progr_rate, progress_function * progr_fun) +{ + size_t cur_token; + uint64_t msgid; + int r; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "X-GM-MSGID"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uint64_parse(fd, buffer, parser_ctx, &cur_token, &msgid); + if (r != MAILIMAP_NO_ERROR) + return r; + + * indx = cur_token; + * result = msgid; + + return MAILIMAP_NO_ERROR; +} + +static int +mailimap_xgmmsgid_extension_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, progress_function * progr_fun) +{ + size_t cur_token; + uint64_t msgid; + uint64_t * data_msgid; + struct mailimap_extension_data * ext_data; + int r; + + cur_token = * indx; + + switch (calling_parser) + { + case MAILIMAP_EXTENDED_PARSER_FETCH_DATA: + + r = fetch_data_xgmmsgid_parse(fd, buffer, parser_ctx, &cur_token, &msgid, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + data_msgid = malloc(sizeof(* data_msgid)); + if (data_msgid == NULL) { + return MAILIMAP_ERROR_MEMORY; + } + * data_msgid = msgid; + + ext_data = mailimap_extension_data_new(&mailimap_extension_xgmmsgid, + MAILIMAP_XGMMSGID_TYPE_MSGID, data_msgid); + if (ext_data == NULL) { + free(data_msgid); + return MAILIMAP_ERROR_MEMORY; + } + + * result = ext_data; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_PARSE; + } +} + +static void +mailimap_xgmmsgid_extension_data_free(struct mailimap_extension_data * ext_data) +{ + free(ext_data->ext_data); + free(ext_data); +} + +struct mailimap_fetch_att * mailimap_fetch_att_new_xgmmsgid(void) +{ + char * keyword; + struct mailimap_fetch_att * att; + + keyword = strdup("X-GM-MSGID"); + if (keyword == NULL) + return NULL; + + att = mailimap_fetch_att_new_extension(keyword); + if (att == NULL) { + free(keyword); + return NULL; + } + + return att; +} diff --git a/Sources/libetpan/low-level/imap/xgmmsgid.h b/Sources/libetpan/low-level/imap/xgmmsgid.h new file mode 100644 index 00000000..9c3f285a --- /dev/null +++ b/Sources/libetpan/low-level/imap/xgmmsgid.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef XGMMSGID_H +#define XGMMSGID_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + + LIBETPAN_EXPORT + extern struct mailimap_extension_api mailimap_extension_xgmmsgid; + + LIBETPAN_EXPORT + struct mailimap_fetch_att * mailimap_fetch_att_new_xgmmsgid(void); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/Sources/libetpan/low-level/imap/xgmthrid.c b/Sources/libetpan/low-level/imap/xgmthrid.c new file mode 100644 index 00000000..f62e4f63 --- /dev/null +++ b/Sources/libetpan/low-level/imap/xgmthrid.c @@ -0,0 +1,163 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "xgmthrid.h" + +#include +#include +#include + +#include "clist.h" +#include "mailimap_types_helper.h" +#include "mailimap_extension.h" +#include "mailimap_keywords.h" +#include "mailimap_parser.h" +#include "mailimap_sender.h" +#include "mailimap.h" + +enum { + MAILIMAP_XGMTHRID_TYPE_THRID +}; + +static int +mailimap_xgmthrid_extension_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, progress_function * progr_fun); + +static void +mailimap_xgmthrid_extension_data_free(struct mailimap_extension_data * ext_data); + +LIBETPAN_EXPORT +struct mailimap_extension_api mailimap_extension_xgmthrid = { + /* name */ "X-GM-THRID", + /* extension_id */ MAILIMAP_EXTENSION_XGMTHRID, + /* parser */ mailimap_xgmthrid_extension_parse, + /* free */ mailimap_xgmthrid_extension_data_free +}; + +static int fetch_data_xgmthrid_parse(mailstream * fd, + MMAPString * buffer, size_t * indx, + uint64_t * result, size_t progr_rate, progress_function * progr_fun) +{ + size_t cur_token; + uint64_t thrid; + int r; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "X-GM-THRID"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uint64_parse(fd, buffer, NULL, &cur_token, &thrid); + if (r != MAILIMAP_NO_ERROR) + return r; + + * indx = cur_token; + * result = thrid; + + return MAILIMAP_NO_ERROR; +} + +static int +mailimap_xgmthrid_extension_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, progress_function * progr_fun) +{ + size_t cur_token; + uint64_t thrid; + uint64_t * data_thrid; + struct mailimap_extension_data * ext_data; + int r; + + cur_token = * indx; + + switch (calling_parser) + { + case MAILIMAP_EXTENDED_PARSER_FETCH_DATA: + + r = fetch_data_xgmthrid_parse(fd, buffer, &cur_token, &thrid, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + data_thrid = malloc(sizeof(* data_thrid)); + if (data_thrid == NULL) { + return MAILIMAP_ERROR_MEMORY; + } + * data_thrid = thrid; + + ext_data = mailimap_extension_data_new(&mailimap_extension_xgmthrid, + MAILIMAP_XGMTHRID_TYPE_THRID, data_thrid); + if (ext_data == NULL) { + free(data_thrid); + return MAILIMAP_ERROR_MEMORY; + } + + * result = ext_data; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_PARSE; + } +} + +static void +mailimap_xgmthrid_extension_data_free(struct mailimap_extension_data * ext_data) +{ + free(ext_data->ext_data); + free(ext_data); +} + +struct mailimap_fetch_att * mailimap_fetch_att_new_xgmthrid(void) +{ + char * keyword; + struct mailimap_fetch_att * att; + + keyword = strdup("X-GM-THRID"); + if (keyword == NULL) + return NULL; + + att = mailimap_fetch_att_new_extension(keyword); + if (att == NULL) { + free(keyword); + return NULL; + } + + return att; +} diff --git a/Sources/libetpan/low-level/imap/xgmthrid.h b/Sources/libetpan/low-level/imap/xgmthrid.h new file mode 100644 index 00000000..4a0ae073 --- /dev/null +++ b/Sources/libetpan/low-level/imap/xgmthrid.h @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef XGMTHRID_H +#define XGMTHRID_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + + LIBETPAN_EXPORT + extern struct mailimap_extension_api mailimap_extension_xgmthrid; + + LIBETPAN_EXPORT + struct mailimap_fetch_att * mailimap_fetch_att_new_xgmthrid(void); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/Sources/libetpan/low-level/imap/xlist.c b/Sources/libetpan/low-level/imap/xlist.c new file mode 100644 index 00000000..0773bcdf --- /dev/null +++ b/Sources/libetpan/low-level/imap/xlist.c @@ -0,0 +1,283 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "xlist.h" + +#include +#include "mailimap.h" +#include "mailimap_extension.h" +#include "mailimap_extension_types.h" +#include "mailimap_sender.h" +#include "mailimap_parser.h" +#include "mailimap_keywords.h" + +enum { + MAILIMAP_XLIST_TYPE_XLIST +}; + +static int +mailimap_xlist_extension_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, progress_function * progr_fun); + +static void +mailimap_xlist_extension_data_free(struct mailimap_extension_data * ext_data); + +LIBETPAN_EXPORT +struct mailimap_extension_api mailimap_extension_xlist = { + /* name */ "XLIST", + /* extension_id */ MAILIMAP_EXTENSION_XLIST, + /* parser */ mailimap_xlist_extension_parse, + /* free */ mailimap_xlist_extension_data_free +}; + +static int mailimap_xlist_send(mailstream * fd, + const char * mb, const char * list_mb) +{ + int r; + + r = mailimap_token_send(fd, "XLIST"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_list_mailbox_send(fd, list_mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailimap_xlist(mailimap * session, const char * mb, + const char * list_mb, clist ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + clistiter * cur; + int res; + clist * result_list; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = mailimap_send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_xlist_send(session->imap_stream, mb, list_mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (mailimap_read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = mailimap_parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + result_list = clist_new(); + if (result_list == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_response; + } + + for(cur = clist_begin(session->imap_response_info->rsp_extension_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_extension_data * ext_data; + struct mailimap_mailbox_list * mailbox_list; + + ext_data = clist_content(cur); + if (ext_data->ext_extension->ext_id != MAILIMAP_EXTENSION_XLIST) { + continue; + } + if (ext_data->ext_type != MAILIMAP_XLIST_TYPE_XLIST) { + continue; + } + + mailbox_list = ext_data->ext_data; + r = clist_append(result_list, mailbox_list); + if (r < 0) { + res = MAILIMAP_ERROR_MEMORY; + goto free_list; + } + ext_data->ext_data = NULL; + } + + if (clist_isempty(result_list) && !clist_isempty(session->imap_response_info->rsp_mailbox_list)) { + // workaround, if server makes LIST-like response, example: cyon.ch + clist_free(result_list); + result_list = session->imap_response_info->rsp_mailbox_list; + session->imap_response_info->rsp_mailbox_list = NULL; + } + + * result = result_list; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_LIST; + } + +free_list: + for(cur = clist_begin(result_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_mailbox_list * mailbox_list; + + mailbox_list = clist_content(cur); + mailimap_mailbox_list_free(mailbox_list); + } + clist_free(result_list); +free_response: + mailimap_response_free(response); + + return res; +} + +static int +mailimap_mailbox_data_xlist_parse(mailstream * fd, MMAPString * buffer, struct mailimap_parser_context * parser_ctx, + size_t * indx, + struct mailimap_mailbox_list ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_mailbox_list * mb_list; + int r; + + cur_token = * indx; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "XLIST"); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + r = mailimap_mailbox_list_parse(fd, buffer, parser_ctx, &cur_token, &mb_list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + * result = mb_list; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; +} + +static int +mailimap_xlist_extension_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, struct mailimap_parser_context * parser_ctx, size_t * indx, + struct mailimap_extension_data ** result, + size_t progr_rate, progress_function * progr_fun) +{ + int r; + struct mailimap_mailbox_list * xlist_data = NULL; + struct mailimap_extension_data * ext_data; + void * data; + int type; + size_t cur_token; + + cur_token = * indx; + + switch (calling_parser) + { + case MAILIMAP_EXTENDED_PARSER_RESPONSE_DATA: + r = mailimap_mailbox_data_xlist_parse(fd, buffer, parser_ctx, &cur_token, + &xlist_data, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + type = MAILIMAP_XLIST_TYPE_XLIST; + data = xlist_data; + + ext_data = mailimap_extension_data_new(&mailimap_extension_xlist, + type, data); + if (ext_data == NULL) { + if (xlist_data != NULL) + mailimap_mailbox_list_free(xlist_data); + return MAILIMAP_ERROR_MEMORY; + } + + * result = ext_data; + * indx = cur_token; + + return MAILIMAP_NO_ERROR; + + default: + /* return a MAILIMAP_ERROR_PARSE if the extension + doesn't extend calling_parser. */ + return MAILIMAP_ERROR_PARSE; + } +} + +LIBETPAN_EXPORT +int mailimap_has_xlist(mailimap * session) +{ + return mailimap_has_extension(session, "XLIST"); +} + +static void +mailimap_xlist_extension_data_free(struct mailimap_extension_data * ext_data) +{ + if (ext_data->ext_data != NULL) { + mailimap_mailbox_list_free((struct mailimap_mailbox_list *) ext_data->ext_data); + } + free(ext_data); +} diff --git a/Sources/libetpan/low-level/imap/xlist.h b/Sources/libetpan/low-level/imap/xlist.h new file mode 100644 index 00000000..9114532d --- /dev/null +++ b/Sources/libetpan/low-level/imap/xlist.h @@ -0,0 +1,63 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2011 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef XLIST_H + +#define XLIST_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +LIBETPAN_EXPORT +extern struct mailimap_extension_api mailimap_extension_xlist; + +/* + mailimap_xlist() + + same as mailimap_list() but with additional flags to indicate identity of mailboxes. +*/ + +LIBETPAN_EXPORT +int mailimap_xlist(mailimap * session, const char * mb, + const char * list_mb, clist ** result); + +LIBETPAN_EXPORT +int mailimap_has_xlist(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imf/Makefile.am b/Sources/libetpan/low-level/imf/Makefile.am new file mode 100644 index 00000000..18b373c1 --- /dev/null +++ b/Sources/libetpan/low-level/imf/Makefile.am @@ -0,0 +1,48 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +EXTRA_DIST = TODO + +etpaninclude_HEADERS = \ + mailimf.h mailimf_types.h mailimf_write_file.h \ + mailimf_types_helper.h \ + mailimf_write_generic.h mailimf_write_mem.h + +AM_CPPFLAGS = -I$(top_builddir)/include \ + -I$(top_srcdir)/src/data-types \ + -I$(top_srcdir)/src/low-level/mime + +noinst_LTLIBRARIES = libimf.la + +libimf_la_SOURCES = \ + mailimf.c mailimf_types.c mailimf_write.h \ + mailimf_write_file.c mailimf_types_helper.c \ + mailimf_write_generic.c mailimf_write_mem.c diff --git a/Sources/libetpan/low-level/imf/TODO b/Sources/libetpan/low-level/imf/TODO new file mode 100644 index 00000000..f36f55fe --- /dev/null +++ b/Sources/libetpan/low-level/imf/TODO @@ -0,0 +1,12 @@ +- define a EP_parserstate_s +- remove clist usage +- add a errorcode to string function +- error codes are EP_errornr_s +- prefix everything with EP_ +- mailimf_dot_atom_text_free +- mailimf_address_XX -> _new(void) _init(&addr, ...) _free(addr) +- in fact that data structure should then also contain a + 'dynamically' allocated flag + +- RFC 822 : test the examples +- RFC 2822 : obsolete syntax diff --git a/Sources/libetpan/low-level/imf/mailimf.c b/Sources/libetpan/low-level/imf/mailimf.c new file mode 100644 index 00000000..b30193a3 --- /dev/null +++ b/Sources/libetpan/low-level/imf/mailimf.c @@ -0,0 +1,7843 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf.c,v 1.50 2011/06/20 23:25:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailimf.h" + +/* + RFC 2822 + + RFC 2821 ... + A message-originating SMTP system SHOULD NOT send a message that + already contains a Return-path header. SMTP servers performing a + relay function MUST NOT inspect the message data, and especially not + to the extent needed to determine if Return-path headers are present. + SMTP servers making final delivery MAY remove Return-path headers + before adding their own. +*/ + +#include +#include "mmapstring.h" +#include +#include +#include "mailmime_decode.h" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + + + + + + + +static inline int is_dtext(char ch); + +static int mailimf_quoted_pair_parse(const char * message, size_t length, + size_t * indx, char * result); + +static int mailimf_ccontent_parse(const char * message, size_t length, + size_t * indx); + +static int +mailimf_comment_fws_ccontent_parse(const char * message, size_t length, + size_t * indx); + +static inline int mailimf_comment_parse(const char * message, size_t length, + size_t * indx); + +static int mailimf_qcontent_parse(const char * message, size_t length, + size_t * indx, char * ch); + +static int mailimf_phrase_parse(const char * message, size_t length, + size_t * indx, char ** result); + +static int mailimf_unstructured_parse(const char * message, size_t length, + size_t * indx, char ** result); + +static int mailimf_ignore_unstructured_parse(const char * message, size_t length, + size_t * indx); + +static int mailimf_day_of_week_parse(const char * message, size_t length, + size_t * indx, int * result); + +static int mailimf_day_name_parse(const char * message, size_t length, + size_t * indx, int * result); + +static int mailimf_date_parse(const char * message, size_t length, + size_t * indx, + int * pday, int * pmonth, int * pyear); + +static int mailimf_broken_date_parse(const char * message, size_t length, + size_t * indx, + int * pday, int * pmonth, int * pyear); + +static int mailimf_year_parse(const char * message, size_t length, + size_t * indx, int * result); + +static int mailimf_month_parse(const char * message, size_t length, + size_t * indx, int * result); + +static int mailimf_month_name_parse(const char * message, size_t length, + size_t * indx, int * result); + +static int mailimf_day_parse(const char * message, size_t length, + size_t * indx, int * result); + +static int mailimf_time_parse(const char * message, size_t length, + size_t * indx, + int * phour, int * pmin, + int * psec, + int * zone); +static int mailimf_time_of_day_parse(const char * message, size_t length, + size_t * indx, + int * phour, int * pmin, + int * psec); + +static int mailimf_hour_parse(const char * message, size_t length, + size_t * indx, int * result); + +static int mailimf_minute_parse(const char * message, size_t length, + size_t * indx, int * result); + +static int mailimf_second_parse(const char * message, size_t length, + size_t * indx, int * result); + +static int mailimf_zone_parse(const char * message, size_t length, + size_t * indx, int * result); + +static int mailimf_name_addr_parse(const char * message, size_t length, + size_t * indx, + char ** pdisplay_name, + char ** pangle_addr); + +static int mailimf_angle_addr_parse(const char * message, size_t length, + size_t * indx, char ** result); + +static int mailimf_group_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_group ** result); + +static int mailimf_display_name_parse(const char * message, size_t length, + size_t * indx, char ** result); + +static int mailimf_addr_spec_parse(const char * message, size_t length, + size_t * indx, + char ** address); + +static int +mailimf_orig_date_parse(const char * message, size_t length, + size_t * indx, struct mailimf_orig_date ** result); + +static int +mailimf_from_parse(const char * message, size_t length, + size_t * indx, struct mailimf_from ** result); + +static int +mailimf_sender_parse(const char * message, size_t length, + size_t * indx, struct mailimf_sender ** result); + +static int +mailimf_reply_to_parse(const char * message, size_t length, + size_t * indx, struct mailimf_reply_to ** result); + +static int +mailimf_to_parse(const char * message, size_t length, + size_t * indx, struct mailimf_to ** result); + +static int +mailimf_cc_parse(const char * message, size_t length, + size_t * indx, struct mailimf_cc ** result); + +static int +mailimf_bcc_parse(const char * message, size_t length, + size_t * indx, struct mailimf_bcc ** result); + +static int mailimf_message_id_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_message_id ** result); + +static int +mailimf_in_reply_to_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_in_reply_to ** result); + +static int mailimf_unstrict_msg_id_parse(const char * message, size_t length, + size_t * indx, + char ** result); + +static int mailimf_subject_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_subject ** result); + +static int mailimf_comments_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_comments ** result); + +static int mailimf_keywords_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_keywords ** result); + +static int +mailimf_resent_date_parse(const char * message, size_t length, + size_t * indx, struct mailimf_orig_date ** result); + +static int +mailimf_resent_from_parse(const char * message, size_t length, + size_t * indx, struct mailimf_from ** result); + +static int +mailimf_resent_sender_parse(const char * message, size_t length, + size_t * indx, struct mailimf_sender ** result); + +static int +mailimf_resent_to_parse(const char * message, size_t length, + size_t * indx, struct mailimf_to ** result); + +static int +mailimf_resent_cc_parse(const char * message, size_t length, + size_t * indx, struct mailimf_cc ** result); + +static int +mailimf_resent_bcc_parse(const char * message, size_t length, + size_t * indx, struct mailimf_bcc ** result); + +static int +mailimf_resent_msg_id_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_message_id ** result); + +static int mailimf_return_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_return ** result); + +static int +mailimf_path_parse(const char * message, size_t length, + size_t * indx, struct mailimf_path ** result); + +static int +mailimf_optional_field_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_optional_field ** result); + +static int mailimf_field_name_parse(const char * message, size_t length, + size_t * indx, char ** result); + + + + + + + + + + + + + + + + + + + + + + + + + +/* *************************************************************** */ + +static inline int is_digit(char ch) +{ + return (ch >= '0') && (ch <= '9'); +} + +static int mailimf_digit_parse(const char * message, size_t length, + size_t * indx, int * result) +{ + size_t cur_token; + + cur_token = * indx; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (is_digit(message[cur_token])) { + * result = message[cur_token] - '0'; + cur_token ++; + * indx = cur_token; + return MAILIMF_NO_ERROR; + } + else + return MAILIMF_ERROR_PARSE; +} + +LIBETPAN_EXPORT +int +mailimf_number_parse(const char * message, size_t length, + size_t * indx, uint32_t * result) +{ + size_t cur_token; + int digit; + uint32_t number; + int parsed; + int r; + + cur_token = * indx; + parsed = FALSE; + + number = 0; + while (1) { + r = mailimf_digit_parse(message, length, &cur_token, &digit); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else + return r; + } + number *= 10; + number += digit; + parsed = TRUE; + } + + if (!parsed) + return MAILIMF_ERROR_PARSE; + + * result = number; + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailimf_char_parse(const char * message, size_t length, + size_t * indx, char token) +{ + size_t cur_token; + + cur_token = * indx; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (message[cur_token] == token) { + cur_token ++; + * indx = cur_token; + return MAILIMF_NO_ERROR; + } + else + return MAILIMF_ERROR_PARSE; +} + +LIBETPAN_EXPORT +int mailimf_unstrict_char_parse(const char * message, size_t length, + size_t * indx, char token) +{ + size_t cur_token; + int r; + + cur_token = * indx; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_char_parse(message, length, &cur_token, token); + if (r != MAILIMF_NO_ERROR) + return r; + + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +LIBETPAN_EXPORT +int +mailimf_token_case_insensitive_len_parse(const char * message, size_t length, + size_t * indx, char * token, + size_t token_length) +{ + size_t cur_token; + + cur_token = * indx; + + if (cur_token + token_length - 1 >= length) + return MAILIMF_ERROR_PARSE; + + if (strncasecmp(message + cur_token, token, token_length) == 0) { + cur_token += token_length; + * indx = cur_token; + return MAILIMF_NO_ERROR; + } + else + return MAILIMF_ERROR_PARSE; +} + +static int mailimf_oparenth_parse(const char * message, size_t length, + size_t * indx) +{ + return mailimf_char_parse(message, length, indx, '('); +} + +static int mailimf_cparenth_parse(const char * message, size_t length, + size_t * indx) +{ + return mailimf_char_parse(message, length, indx, ')'); +} + +static int mailimf_comma_parse(const char * message, size_t length, + size_t * indx) +{ + return mailimf_unstrict_char_parse(message, length, indx, ','); +} + +static int mailimf_dquote_parse(const char * message, size_t length, + size_t * indx) +{ + return mailimf_char_parse(message, length, indx, '\"'); +} + +static int mailimf_colon_parse(const char * message, size_t length, + size_t * indx) +{ + return mailimf_unstrict_char_parse(message, length, indx, ':'); +} + +static int mailimf_semi_colon_parse(const char * message, size_t length, + size_t * indx) +{ + return mailimf_unstrict_char_parse(message, length, indx, ';'); +} + +static int mailimf_plus_parse(const char * message, size_t length, + size_t * indx) +{ + return mailimf_unstrict_char_parse(message, length, indx, '+'); +} + +static int mailimf_minus_parse(const char * message, size_t length, + size_t * indx) +{ + return mailimf_unstrict_char_parse(message, length, indx, '-'); +} + +static int mailimf_lower_parse(const char * message, size_t length, + size_t * indx) +{ + return mailimf_unstrict_char_parse(message, length, indx, '<'); +} + +static int mailimf_greater_parse(const char * message, size_t length, + size_t * indx) +{ + return mailimf_unstrict_char_parse(message, length, indx, '>'); +} + +static int mailimf_at_sign_parse(const char * message, size_t length, + size_t * indx) +{ + return mailimf_unstrict_char_parse(message, length, indx, '@'); +} + +static int mailimf_point_parse(const char * message, size_t length, + size_t * indx) +{ + return mailimf_unstrict_char_parse(message, length, indx, '.'); +} + +LIBETPAN_EXPORT +int +mailimf_custom_string_parse(const char * message, size_t length, + size_t * indx, char ** result, + int (* is_custom_char)(char)) +{ + size_t begin; + size_t end; + char * gstr; + + begin = * indx; + + end = begin; + + if (end >= length) + return MAILIMF_ERROR_PARSE; + + while (is_custom_char(message[end])) { + end ++; + if (end >= length) + break; + } + + if (end != begin) { + /* + gstr = strndup(message + begin, end - begin); + */ + gstr = malloc(end - begin + 1); + if (gstr == NULL) + return MAILIMF_ERROR_MEMORY; + strncpy(gstr, message + begin, end - begin); + gstr[end - begin] = '\0'; + + * indx = end; + * result = gstr; + return MAILIMF_NO_ERROR; + } + else + return MAILIMF_ERROR_PARSE; +} + + + + + + + +typedef int mailimf_struct_parser(const char * message, size_t length, + size_t * indx, void * result); + +typedef int mailimf_struct_destructor(void * result); + + +static int +mailimf_struct_multiple_parse(const char * message, size_t length, + size_t * indx, clist ** result, + mailimf_struct_parser * parser, + mailimf_struct_destructor * destructor) +{ + clist * struct_list; + size_t cur_token; + void * value; + int r; + int res; + + cur_token = * indx; + + r = parser(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + struct_list = clist_new(); + if (struct_list == NULL) { + destructor(value); + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + while (1) { + r = parser(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free; + } + } + r = clist_append(struct_list, value); + if (r < 0) { + (* destructor)(value); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + + * result = struct_list; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free: + clist_foreach(struct_list, (clist_func) destructor, NULL); + clist_free(struct_list); + err: + return res; +} + + + +static int +mailimf_struct_list_parse(const char * message, size_t length, + size_t * indx, clist ** result, + char symbol, + mailimf_struct_parser * parser, + mailimf_struct_destructor * destructor) +{ + clist * struct_list; + size_t cur_token; + void * value; + size_t final_token; + int r; + int res; + + cur_token = * indx; + + r = parser(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + struct_list = clist_new(); + if (struct_list == NULL) { + destructor(value); + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + final_token = cur_token; + + while (1) { + r = mailimf_unstrict_char_parse(message, length, &cur_token, symbol); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free; + } + } + + r = parser(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free; + } + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + final_token = cur_token; + } + + * result = struct_list; + * indx = final_token; + + return MAILIMF_NO_ERROR; + + free: + clist_foreach(struct_list, (clist_func) destructor, NULL); + clist_free(struct_list); + err: + return res; +} + +static inline int mailimf_wsp_parse(const char * message, size_t length, + size_t * indx) +{ + size_t cur_token; + + cur_token = * indx; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if ((message[cur_token] != ' ') && (message[cur_token] != '\t')) + return MAILIMF_ERROR_PARSE; + + cur_token ++; + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + + +LIBETPAN_EXPORT +int mailimf_crlf_parse(const char * message, size_t length, size_t * indx) +{ + size_t cur_token; + int r; + + cur_token = * indx; + + r = mailimf_char_parse(message, length, &cur_token, '\r'); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_char_parse(message, length, &cur_token, '\n'); + if (r != MAILIMF_NO_ERROR) + return r; + + * indx = cur_token; + return MAILIMF_NO_ERROR; +} + +static int mailimf_unstrict_crlf_parse(const char * message, + size_t length, size_t * indx) +{ + size_t cur_token; + int r; + + cur_token = * indx; + + mailimf_cfws_parse(message, length, &cur_token); + + r = mailimf_char_parse(message, length, &cur_token, '\r'); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_char_parse(message, length, &cur_token, '\n'); + if (r != MAILIMF_NO_ERROR) + return r; + + * indx = cur_token; + return MAILIMF_NO_ERROR; +} + +/* ************************************************************************ */ + + + +/* RFC 2822 grammar */ + +/* +NO-WS-CTL = %d1-8 / ; US-ASCII control characters + %d11 / ; that do not include the + %d12 / ; carriage return, line feed, + %d14-31 / ; and white space characters + %d127 +*/ + +static inline int is_no_ws_ctl(char ch) +{ + if ((ch == 9) || (ch == 10) || (ch == 13)) + return FALSE; + + if (ch == 127) + return TRUE; + + return (ch >= 1) && (ch <= 31); +} + +/* +text = %d1-9 / ; Characters excluding CR and LF + %d11 / + %d12 / + %d14-127 / + obs-text +*/ + +/* +specials = "(" / ")" / ; Special characters used in + "<" / ">" / ; other parts of the syntax + "[" / "]" / + ":" / ";" / + "@" / "\" / + "," / "." / + DQUOTE +*/ + +/* +quoted-pair = ("\" text) / obs-qp +*/ + +static inline int mailimf_quoted_pair_parse(const char * message, size_t length, + size_t * indx, char * result) +{ + size_t cur_token; + + cur_token = * indx; + + if (cur_token + 1 >= length) + return MAILIMF_ERROR_PARSE; + + if (message[cur_token] != '\\') + return MAILIMF_ERROR_PARSE; + + cur_token ++; + * result = message[cur_token]; + cur_token ++; + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space + obs-FWS +*/ + +LIBETPAN_EXPORT +int mailimf_fws_parse(const char * message, size_t length, size_t * indx) +{ + size_t cur_token; + size_t final_token; + int fws_1; + int fws_2; + int fws_3; + int r; + + cur_token = * indx; + + fws_1 = FALSE; + while (1) { + r = mailimf_wsp_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else + return r; + } + fws_1 = TRUE; + } + final_token = cur_token; + + r = mailimf_crlf_parse(message, length, &cur_token); + switch (r) { + case MAILIMF_NO_ERROR: + fws_2 = TRUE; + break; + case MAILIMF_ERROR_PARSE: + fws_2 = FALSE; + break; + default: + return r; + } + + fws_3 = FALSE; + if (fws_2) { + while (1) { + r = mailimf_wsp_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else + return r; + } + fws_3 = TRUE; + } + } + + if ((!fws_1) && (!fws_3)) + return MAILIMF_ERROR_PARSE; + + if (!fws_3) + cur_token = final_token; + + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + + +/* +ctext = NO-WS-CTL / ; Non white space controls + + %d33-39 / ; The rest of the US-ASCII + %d42-91 / ; characters not including "(", + %d93-126 ; ")", or "\" +*/ + +static inline int is_ctext(char ch) +{ + unsigned char uch = (unsigned char) ch; + + if (is_no_ws_ctl(ch)) + return TRUE; + + if (uch < 33) + return FALSE; + + if ((uch == 40) || (uch == 41)) + return FALSE; + + if (uch == 92) + return FALSE; + + if (uch == 127) + return FALSE; + + return TRUE; +} + +/* +ccontent = ctext / quoted-pair / comment +*/ + +static inline int mailimf_ccontent_parse(const char * message, size_t length, + size_t * indx) +{ + size_t cur_token; + char ch; + int r; + + cur_token = * indx; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (is_ctext(message[cur_token])) { + cur_token ++; + } + else { + r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch); + + if (r == MAILIMF_ERROR_PARSE) + r = mailimf_comment_parse(message, length, &cur_token); + + if (r == MAILIMF_ERROR_PARSE) + return r; + } + + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +[FWS] ccontent +*/ + +static inline int +mailimf_comment_fws_ccontent_parse(const char * message, size_t length, + size_t * indx) +{ + size_t cur_token; + int r; + + cur_token = * indx; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_ccontent_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +comment = "(" *([FWS] ccontent) [FWS] ")" +*/ + +static inline int mailimf_comment_parse(const char * message, size_t length, + size_t * indx) +{ + size_t cur_token; + int r; + + cur_token = * indx; + + r = mailimf_oparenth_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + while (1) { + r = mailimf_comment_fws_ccontent_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else + return r; + } + } + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_cparenth_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +[FWS] comment +*/ + +static inline int mailimf_cfws_fws_comment_parse(const char * message, size_t length, + size_t * indx) +{ + size_t cur_token; + int r; + + cur_token = * indx; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_comment_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +CFWS = *([FWS] comment) (([FWS] comment) / FWS) +*/ + +LIBETPAN_EXPORT +int mailimf_cfws_parse(const char * message, size_t length, + size_t * indx) +{ + size_t cur_token; + int has_comment; + int r; + + cur_token = * indx; + + has_comment = FALSE; + while (1) { + r = mailimf_cfws_fws_comment_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else + return r; + } + has_comment = TRUE; + } + + if (!has_comment) { + r = mailimf_fws_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + } + + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +atext = ALPHA / DIGIT / ; Any character except controls, + "!" / "#" / ; SP, and specials. + "$" / "%" / ; Used for atoms + "&" / "'" / + "*" / "+" / + "-" / "/" / + "=" / "?" / + "^" / "_" / + "`" / "{" / + "|" / "}" / + "~" +*/ + +static inline int is_atext(char ch) +{ + switch (ch) { + case ' ': + case '\t': + case '\n': + case '\r': +#if 0 + case '(': + case ')': +#endif + case '<': + case '>': +#if 0 + case '@': +#endif + case ',': + case '"': + case ':': + case ';': + return FALSE; + default: + return TRUE; + } +} + +/* +atom = [CFWS] 1*atext [CFWS] +*/ + +LIBETPAN_EXPORT +int mailimf_atom_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + size_t cur_token; + int r; + int res; + char * atom; + size_t end; + + cur_token = * indx; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + end = cur_token; + if (end >= length) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + while (is_atext(message[end])) { + end ++; + if (end >= length) + break; + } + if (end == cur_token) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + atom = malloc(end - cur_token + 1); + if (atom == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + strncpy(atom, message + cur_token, end - cur_token); + atom[end - cur_token] = '\0'; + + cur_token = end; + + * indx = cur_token; + * result = atom; + + return MAILIMF_NO_ERROR; + + err: + return res; +} + +static int mailimf_fws_atom_for_word_parse(const char * message, size_t length, + size_t * indx, char ** result, int * p_missing_closing_quote) +{ + size_t end; + size_t cur_token; + int r; + int res; + struct mailmime_encoded_word * word; + int has_fwd; + int missing_closing_quote; + char * atom; + + cur_token = * indx; + missing_closing_quote = 0; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + end = cur_token; + + r = mailmime_encoded_word_parse(message, length, &cur_token, &word, &has_fwd, &missing_closing_quote); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + if (r == MAILIMF_ERROR_PARSE) { + return mailimf_fws_atom_parse(message, length, indx, result); + } + + mailmime_encoded_word_free(word); + + atom = malloc(cur_token - end + 1); + if (atom == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + strncpy(atom, message + end, cur_token - end); + atom[cur_token - end] = '\0'; + + * result = atom; + * indx = cur_token; + * p_missing_closing_quote = missing_closing_quote; + + return MAILIMF_NO_ERROR; + +err: + return res; +} + +LIBETPAN_EXPORT +int mailimf_fws_atom_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + size_t cur_token; + int r; + int res; + char * atom; + size_t end; + + cur_token = * indx; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + end = cur_token; + if (end >= length) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + while (is_atext(message[end])) { + end ++; + if (end >= length) + break; + } + if (end == cur_token) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + atom = malloc(end - cur_token + 1); + if (atom == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + strncpy(atom, message + cur_token, end - cur_token); + atom[end - cur_token] = '\0'; + + cur_token = end; + + * indx = cur_token; + * result = atom; + + return MAILIMF_NO_ERROR; + + err: + return res; +} + +/* +dot-atom = [CFWS] dot-atom-text [CFWS] +*/ + +#if 0 +static int mailimf_dot_atom_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + return mailimf_atom_parse(message, length, indx, result); +} +#endif + +/* +dot-atom-text = 1*atext *("." 1*atext) +*/ + +#if 0 +static int +mailimf_dot_atom_text_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + return mailimf_atom_parse(message, length, indx, result); +} +#endif + +/* +qtext = NO-WS-CTL / ; Non white space controls + + %d33 / ; The rest of the US-ASCII + %d35-91 / ; characters not including "\" + %d93-126 ; or the quote character +*/ + +static inline int is_qtext(char ch) +{ + unsigned char uch = (unsigned char) ch; + + if (is_no_ws_ctl(ch)) + return TRUE; + + if (uch < 33) + return FALSE; + + if (uch == 34) + return FALSE; + + if (uch == 92) + return FALSE; + + if (uch == 127) + return FALSE; + + return TRUE; +} + +/* +qcontent = qtext / quoted-pair +*/ + +static int mailimf_qcontent_parse(const char * message, size_t length, + size_t * indx, char * result) +{ + size_t cur_token; + char ch; + int r; + + cur_token = * indx; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (is_qtext(message[cur_token])) { + ch = message[cur_token]; + cur_token ++; + } + else { + r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch); + + if (r != MAILIMF_NO_ERROR) + return r; + } + + * result = ch; + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +quoted-string = [CFWS] + DQUOTE *([FWS] qcontent) [FWS] DQUOTE + [CFWS] +*/ + +LIBETPAN_EXPORT +int mailimf_quoted_string_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + size_t cur_token; + MMAPString * gstr; + char ch; + char * str; + int r; + int res; + + cur_token = * indx; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_dquote_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + gstr = mmap_string_new(""); + if (gstr == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + +#if 0 + if (mmap_string_append_c(gstr, '\"') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } +#endif + + while (1) { + r = mailimf_fws_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + if (mmap_string_append_c(gstr, ' ') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } + } + else if (r != MAILIMF_ERROR_PARSE) { + res = r; + goto free_gstr; + } + + r = mailimf_qcontent_parse(message, length, &cur_token, &ch); + if (r == MAILIMF_NO_ERROR) { + if (mmap_string_append_c(gstr, ch) == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free_gstr; + } + } + + r = mailimf_dquote_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_gstr; + } + +#if 0 + if (mmap_string_append_c(gstr, '\"') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } +#endif + + str = strdup(gstr->str); + if (str == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } + mmap_string_free(gstr); + + * indx = cur_token; + * result = str; + + return MAILIMF_NO_ERROR; + + free_gstr: + mmap_string_free(gstr); + err: + return res; +} + +LIBETPAN_EXPORT +int mailimf_fws_quoted_string_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + size_t cur_token; + MMAPString * gstr; + char ch; + char * str; + int r; + int res; + + cur_token = * indx; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_dquote_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + gstr = mmap_string_new(""); + if (gstr == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + +#if 0 + if (mmap_string_append_c(gstr, '\"') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } +#endif + + while (1) { + r = mailimf_fws_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + if (mmap_string_append_c(gstr, ' ') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } + } + else if (r != MAILIMF_ERROR_PARSE) { + res = r; + goto free_gstr; + } + + r = mailimf_qcontent_parse(message, length, &cur_token, &ch); + if (r == MAILIMF_NO_ERROR) { + if (mmap_string_append_c(gstr, ch) == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free_gstr; + } + } + + r = mailimf_dquote_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_gstr; + } + +#if 0 + if (mmap_string_append_c(gstr, '\"') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } +#endif + + str = strdup(gstr->str); + if (str == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } + mmap_string_free(gstr); + + * indx = cur_token; + * result = str; + + return MAILIMF_NO_ERROR; + + free_gstr: + mmap_string_free(gstr); + err: + return res; +} + +/* +word = atom / quoted-string +*/ + +LIBETPAN_EXPORT +int mailimf_word_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + size_t cur_token; + char * word; + int r; + + cur_token = * indx; + + r = mailimf_atom_parse(message, length, &cur_token, &word); + + if (r == MAILIMF_ERROR_PARSE) + r = mailimf_quoted_string_parse(message, length, &cur_token, &word); + + if (r != MAILIMF_NO_ERROR) + return r; + + * result = word; + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailimf_fws_word_parse(const char * message, size_t length, + size_t * indx, char ** result, int * p_missing_closing_quote) +{ + size_t cur_token; + char * word; + int r; + int missing_closing_quote; + + cur_token = * indx; + missing_closing_quote = 0; + + r = mailimf_fws_atom_for_word_parse(message, length, &cur_token, &word, &missing_closing_quote); + + if (r == MAILIMF_ERROR_PARSE) + r = mailimf_fws_quoted_string_parse(message, length, &cur_token, &word); + + if (r != MAILIMF_NO_ERROR) + return r; + + * result = word; + * indx = cur_token; + * p_missing_closing_quote = missing_closing_quote; + + return MAILIMF_NO_ERROR; +} + +/* +phrase = 1*word / obs-phrase +*/ + +static int mailimf_phrase_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + MMAPString * gphrase; + char * word; + int first; + size_t cur_token; + int r; + int res; + char * str; + int has_missing_closing_quote; + + cur_token = * indx; + has_missing_closing_quote = 0; + + gphrase = mmap_string_new(""); + if (gphrase == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + first = TRUE; + + while (1) { + int missing_quote = 0; + r = mailimf_fws_word_parse(message, length, &cur_token, &word, &missing_quote); + if (missing_quote) { + has_missing_closing_quote = 1; + } + if (r == MAILIMF_NO_ERROR) { + if (!first) { + if (mmap_string_append_c(gphrase, ' ') == NULL) { + mailimf_word_free(word); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + if (mmap_string_append(gphrase, word) == NULL) { + mailimf_word_free(word); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + mailimf_word_free(word); + first = FALSE; + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free; + } + } + + if (first) { + res = MAILIMF_ERROR_PARSE; + goto free; + } + + if (has_missing_closing_quote) { + r = mailimf_char_parse(message, length, &cur_token, '\"'); + } + + str = strdup(gphrase->str); + if (str == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + mmap_string_free(gphrase); + + * result = str; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free: + mmap_string_free(gphrase); + err: + return res; +} + +/* +utext = NO-WS-CTL / ; Non white space controls + %d33-126 / ; The rest of US-ASCII + obs-utext + +added : WSP +*/ + +enum { + UNSTRUCTURED_START, + UNSTRUCTURED_CR, + UNSTRUCTURED_LF, + UNSTRUCTURED_WSP, + UNSTRUCTURED_OUT +}; + +static int mailimf_unstructured_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + size_t cur_token; + int state; + size_t begin; + size_t terminal; + char * str; + + cur_token = * indx; + + + while (1) { + int r; + + r = mailimf_wsp_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + return r; + } + } + + state = UNSTRUCTURED_START; + begin = cur_token; + terminal = cur_token; + + while (state != UNSTRUCTURED_OUT) { + + switch(state) { + case UNSTRUCTURED_START: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + terminal = cur_token; + switch(message[cur_token]) { + case '\r': + state = UNSTRUCTURED_CR; + break; + case '\n': + state = UNSTRUCTURED_LF; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + case UNSTRUCTURED_CR: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch(message[cur_token]) { + case '\n': + state = UNSTRUCTURED_LF; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + + case UNSTRUCTURED_LF: + if (cur_token >= length) { + state = UNSTRUCTURED_OUT; + break; + } + + switch(message[cur_token]) { + case '\t': + case ' ': + state = UNSTRUCTURED_WSP; + break; + default: + state = UNSTRUCTURED_OUT; + break; + } + break; + case UNSTRUCTURED_WSP: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch(message[cur_token]) { + case '\r': + state = UNSTRUCTURED_CR; + break; + case '\n': + state = UNSTRUCTURED_LF; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + } + + cur_token ++; + } + + str = malloc(terminal - begin + 1); + if (str == NULL) + return MAILIMF_ERROR_MEMORY; + strncpy(str, message + begin, terminal - begin); + str[terminal - begin] = '\0'; + + * indx = terminal; + * result = str; + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_ignore_unstructured_parse(const char * message, size_t length, + size_t * indx) +{ + size_t cur_token; + int state; + size_t terminal; + + cur_token = * indx; + + state = UNSTRUCTURED_START; + terminal = cur_token; + + while (state != UNSTRUCTURED_OUT) { + + switch(state) { + case UNSTRUCTURED_START: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + terminal = cur_token; + switch(message[cur_token]) { + case '\r': + state = UNSTRUCTURED_CR; + break; + case '\n': + state = UNSTRUCTURED_LF; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + case UNSTRUCTURED_CR: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + switch(message[cur_token]) { + case '\n': + state = UNSTRUCTURED_LF; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + case UNSTRUCTURED_LF: + if (cur_token >= length) { + state = UNSTRUCTURED_OUT; + break; + } + switch(message[cur_token]) { + case '\t': + case ' ': + state = UNSTRUCTURED_WSP; + break; + default: + state = UNSTRUCTURED_OUT; + break; + } + break; + case UNSTRUCTURED_WSP: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + switch(message[cur_token]) { + case '\r': + state = UNSTRUCTURED_CR; + break; + case '\n': + state = UNSTRUCTURED_LF; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + } + + cur_token ++; + } + + * indx = terminal; + + return MAILIMF_NO_ERROR; +} + + +LIBETPAN_EXPORT +int mailimf_ignore_field_parse(const char * message, size_t length, + size_t * indx) +{ + int has_field; + size_t cur_token; + int state; + size_t terminal; + + has_field = FALSE; + cur_token = * indx; + + terminal = cur_token; + state = UNSTRUCTURED_START; + + /* check if this is not a beginning CRLF */ + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch (message[cur_token]) { + case '\r': + return MAILIMF_ERROR_PARSE; + case '\n': + return MAILIMF_ERROR_PARSE; + } + + while (state != UNSTRUCTURED_OUT) { + + switch(state) { + case UNSTRUCTURED_START: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch(message[cur_token]) { + case '\r': + state = UNSTRUCTURED_CR; + break; + case '\n': + state = UNSTRUCTURED_LF; + break; + case ':': + has_field = TRUE; + state = UNSTRUCTURED_START; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + case UNSTRUCTURED_CR: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch(message[cur_token]) { + case '\n': + state = UNSTRUCTURED_LF; + break; + case ':': + has_field = TRUE; + state = UNSTRUCTURED_START; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + case UNSTRUCTURED_LF: + if (cur_token >= length) { + terminal = cur_token; + state = UNSTRUCTURED_OUT; + break; + } + + switch(message[cur_token]) { + case '\t': + case ' ': + state = UNSTRUCTURED_WSP; + break; + default: + terminal = cur_token; + state = UNSTRUCTURED_OUT; + break; + } + break; + case UNSTRUCTURED_WSP: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch(message[cur_token]) { + case '\r': + state = UNSTRUCTURED_CR; + break; + case '\n': + state = UNSTRUCTURED_LF; + break; + case ':': + has_field = TRUE; + state = UNSTRUCTURED_START; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + } + + cur_token ++; + } + + if (!has_field) + return MAILIMF_ERROR_PARSE; + + * indx = terminal; + + return MAILIMF_NO_ERROR; +} + + +/* +date-time = [ day-of-week "," ] date FWS time [CFWS] +*/ + +LIBETPAN_EXPORT +int mailimf_date_time_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_date_time ** result) +{ + size_t cur_token; + int day_of_week; + struct mailimf_date_time * date_time; + int day; + int month; + int year; + int hour; + int min; + int sec; + int zone; + int r; + + cur_token = * indx; + + day_of_week = -1; + r = mailimf_day_of_week_parse(message, length, &cur_token, &day_of_week); + if (r == MAILIMF_NO_ERROR) { + r = mailimf_comma_parse(message, length, &cur_token); + if (r == MAILIMF_ERROR_PARSE) { + // ignore parse error. + } + else if (r != MAILIMF_NO_ERROR) { + return r; + } + } + else if (r != MAILIMF_ERROR_PARSE) + return r; + + day = 0; + month = 0; + year = 0; + r = mailimf_date_parse(message, length, &cur_token, &day, &month, &year); + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_broken_date_parse(message, length, &cur_token, &day, &month, &year); + } + if (r != MAILIMF_NO_ERROR) { + return r; + } + + r = mailimf_fws_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + hour = 0; + min = 0; + sec = 0; + zone = 0; + r = mailimf_time_parse(message, length, &cur_token, + &hour, &min, &sec, &zone); + if (r != MAILIMF_NO_ERROR) + return r; + + date_time = mailimf_date_time_new(day, month, year, hour, min, sec, zone); + if (date_time == NULL) + return MAILIMF_ERROR_MEMORY; + + * indx = cur_token; + * result = date_time; + + return MAILIMF_NO_ERROR; +} + +/* +day-of-week = ([FWS] day-name) / obs-day-of-week +*/ + +static int mailimf_day_of_week_parse(const char * message, size_t length, + size_t * indx, int * result) +{ + size_t cur_token; + int day_of_week; + int r; + + cur_token = * indx; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_day_name_parse(message, length, &cur_token, &day_of_week); + if (r != MAILIMF_NO_ERROR) + return r; + + * indx = cur_token; + * result = day_of_week; + + return MAILIMF_NO_ERROR; +} + +/* +day-name = "Mon" / "Tue" / "Wed" / "Thu" / + "Fri" / "Sat" / "Sun" +*/ + +struct mailimf_token_value { + int value; + char * str; +}; + +static struct mailimf_token_value day_names[] = { + {1, "Mon"}, + {2, "Tue"}, + {3, "Wed"}, + {4, "Thu"}, + {5, "Fri"}, + {6, "Sat"}, + {7, "Sun"}, +}; + +enum { + DAY_NAME_START, + DAY_NAME_T, + DAY_NAME_S +}; + +static int guess_day_name(const char * message, size_t length, size_t indx) +{ + int state; + + state = DAY_NAME_START; + + while (1) { + + if (indx >= length) + return -1; + + switch(state) { + case DAY_NAME_START: + switch((char) toupper((unsigned char) message[indx])) { + case 'M': /* Mon */ + return 1; + break; + case 'T': /* Tue Thu */ + state = DAY_NAME_T; + break; + case 'W': /* Wed */ + return 3; + case 'F': + return 5; + case 'S': /* Sat Sun */ + state = DAY_NAME_S; + break; + default: + return -1; + } + break; + case DAY_NAME_T: + switch((char) toupper((unsigned char) message[indx])) { + case 'U': + return 2; + case 'H': + return 4; + default: + return -1; + } + break; + case DAY_NAME_S: + switch((char) toupper((unsigned char) message[indx])) { + case 'A': + return 6; + case 'U': + return 7; + default: + return -1; + } + break; + } + + indx ++; + } +} + +static int mailimf_day_name_parse(const char * message, size_t length, + size_t * indx, int * result) +{ + size_t cur_token; + int day_of_week; + int guessed_day; + int r; + + cur_token = * indx; + + guessed_day = guess_day_name(message, length, cur_token); + if (guessed_day == -1) + return MAILIMF_ERROR_PARSE; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, + day_names[guessed_day - 1].str); + if (r != MAILIMF_NO_ERROR) + return r; + + day_of_week = guessed_day; + + * result = day_of_week; + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +date = day month year +*/ + +static int mailimf_date_parse(const char * message, size_t length, + size_t * indx, + int * pday, int * pmonth, int * pyear) +{ + size_t cur_token; + int day; + int month; + int year; + int r; + + cur_token = * indx; + + day = 1; + r = mailimf_day_parse(message, length, &cur_token, &day); + if (r != MAILIMF_NO_ERROR) + return r; + + month = 1; + r = mailimf_month_parse(message, length, &cur_token, &month); + if (r != MAILIMF_NO_ERROR) + return r; + + year = 2001; + r = mailimf_year_parse(message, length, &cur_token, &year); + if (r != MAILIMF_NO_ERROR) + return r; + + * pday = day; + * pmonth = month; + * pyear = year; + + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +static int mailimf_broken_date_parse(const char * message, size_t length, + size_t * indx, + int * pday, int * pmonth, int * pyear) +{ + size_t cur_token; + int day; + int month; + int year; + int r; + + cur_token = * indx; + + month = 1; + r = mailimf_month_parse(message, length, &cur_token, &month); + if (r != MAILIMF_NO_ERROR) + return r; + + day = 1; + r = mailimf_day_parse(message, length, &cur_token, &day); + if (r != MAILIMF_NO_ERROR) + return r; + + year = 2001; + r = mailimf_year_parse(message, length, &cur_token, &year); + if (r != MAILIMF_NO_ERROR) + return r; + + * pday = day; + * pmonth = month; + * pyear = year; + + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +year = 4*DIGIT / obs-year +*/ + +static int mailimf_year_parse(const char * message, size_t length, + size_t * indx, int * result) +{ + uint32_t number; + size_t cur_token; + int r; + + cur_token = * indx; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_number_parse(message, length, &cur_token, &number); + if (r != MAILIMF_NO_ERROR) + return r; + + * indx = cur_token; + * result = number; + + return MAILIMF_NO_ERROR; +} + +/* +month = (FWS month-name FWS) / obs-month +*/ + +static int mailimf_month_parse(const char * message, size_t length, + size_t * indx, int * result) +{ + size_t cur_token; + int month; + int r; + + cur_token = * indx; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_month_name_parse(message, length, &cur_token, &month); + if (r != MAILIMF_NO_ERROR) + return r; + + * result = month; + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +month-name = "Jan" / "Feb" / "Mar" / "Apr" / + "May" / "Jun" / "Jul" / "Aug" / + "Sep" / "Oct" / "Nov" / "Dec" +*/ + +static struct mailimf_token_value month_names[] = { + {1, "Jan"}, + {2, "Feb"}, + {3, "Mar"}, + {4, "Apr"}, + {5, "May"}, + {6, "Jun"}, + {7, "Jul"}, + {8, "Aug"}, + {9, "Sep"}, + {10, "Oct"}, + {11, "Nov"}, + {12, "Dec"}, +}; + +enum { + MONTH_START, + MONTH_J, + MONTH_JU, + MONTH_M, + MONTH_MA, + MONTH_A +}; + +static int guess_month(const char * message, size_t length, size_t indx) +{ + int state; + + state = MONTH_START; + + while (1) { + + if (indx >= length) + return -1; + + switch(state) { + case MONTH_START: + switch((char) toupper((unsigned char) message[indx])) { + case 'J': /* Jan Jun Jul */ + state = MONTH_J; + break; + case 'F': /* Feb */ + return 2; + case 'M': /* Mar May */ + state = MONTH_M; + break; + case 'A': /* Apr Aug */ + state = MONTH_A; + break; + case 'S': /* Sep */ + return 9; + case 'O': /* Oct */ + return 10; + case 'N': /* Nov */ + return 11; + case 'D': /* Dec */ + return 12; + default: + return -1; + } + break; + case MONTH_J: + switch((char) toupper((unsigned char) message[indx])) { + case 'A': + return 1; + case 'U': + state = MONTH_JU; + break; + default: + return -1; + } + break; + case MONTH_JU: + switch((char) toupper((unsigned char) message[indx])) { + case 'N': + return 6; + case 'L': + return 7; + default: + return -1; + } + break; + case MONTH_M: + switch((char) toupper((unsigned char) message[indx])) { + case 'A': + state = MONTH_MA; + break; + default: + return -1; + } + break; + case MONTH_MA: + switch((char) toupper((unsigned char) message[indx])) { + case 'Y': + return 5; + case 'R': + return 3; + default: + return -1; + } + break; + case MONTH_A: + switch((char) toupper((unsigned char) message[indx])) { + case 'P': + return 4; + case 'U': + return 8; + default: + return -1; + } + break; + } + + indx ++; + } +} + +static int mailimf_month_name_parse(const char * message, size_t length, + size_t * indx, int * result) +{ + size_t cur_token; + int month; + int guessed_month; + int r; + + cur_token = * indx; + + guessed_month = guess_month(message, length, cur_token); + if (guessed_month == -1) + return MAILIMF_ERROR_PARSE; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, + month_names[guessed_month - 1].str); + if (r != MAILIMF_NO_ERROR) + return r; + + month = guessed_month; + + * result = month; + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +day = ([FWS] 1*2DIGIT) / obs-day +*/ + +static int mailimf_day_parse(const char * message, size_t length, + size_t * indx, int * result) +{ + size_t cur_token; + uint32_t day; + int r; + + cur_token = * indx; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_number_parse(message, length, &cur_token, &day); + if (r != MAILIMF_NO_ERROR) + return r; + + * result = day; + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +time = time-of-day FWS zone +*/ + +static int mailimf_time_parse(const char * message, size_t length, + size_t * indx, + int * phour, int * pmin, + int * psec, + int * pzone) +{ + size_t cur_token; + int hour; + int min; + int sec; + int zone; + int r; + + cur_token = * indx; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_time_of_day_parse(message, length, &cur_token, + &hour, &min, &sec); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_zone_parse(message, length, &cur_token, &zone); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + zone = 0; + } + else { + return r; + } + + * phour = hour; + * pmin = min; + * psec = sec; + * pzone = zone; + + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +time-of-day = hour ":" minute [ ":" second ] +*/ + +static int mailimf_time_of_day_parse(const char * message, size_t length, + size_t * indx, + int * phour, int * pmin, + int * psec) +{ + int hour; + int min; + int sec; + size_t cur_token; + int r; + + cur_token = * indx; + + r = mailimf_hour_parse(message, length, &cur_token, &hour); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_minute_parse(message, length, &cur_token, &min); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_colon_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + r = mailimf_second_parse(message, length, &cur_token, &sec); + if (r != MAILIMF_NO_ERROR) + return r; + } + else if (r == MAILIMF_ERROR_PARSE) + sec = 0; + else + return r; + + * phour = hour; + * pmin = min; + * psec = sec; + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +hour = 2DIGIT / obs-hour +*/ + +static int mailimf_hour_parse(const char * message, size_t length, + size_t * indx, int * result) +{ + uint32_t hour; + int r; + + r = mailimf_number_parse(message, length, indx, &hour); + if (r != MAILIMF_NO_ERROR) + return r; + + * result = hour; + + return MAILIMF_NO_ERROR; +} + +/* +minute = 2DIGIT / obs-minute +*/ + +static int mailimf_minute_parse(const char * message, size_t length, + size_t * indx, int * result) +{ + uint32_t minute; + int r; + + r = mailimf_number_parse(message, length, indx, &minute); + if (r != MAILIMF_NO_ERROR) + return r; + + * result = minute; + + return MAILIMF_NO_ERROR; +} + +/* +second = 2DIGIT / obs-second +*/ + +static int mailimf_second_parse(const char * message, size_t length, + size_t * indx, int * result) +{ + uint32_t second; + int r; + + r = mailimf_number_parse(message, length, indx, &second); + if (r != MAILIMF_NO_ERROR) + return r; + + * result = second; + + return MAILIMF_NO_ERROR; +} + +/* +zone = (( "+" / "-" ) 4DIGIT) / obs-zone +*/ + +/* +obs-zone = "UT" / "GMT" / ; Universal Time + ; North American UT + ; offsets + "EST" / "EDT" / ; Eastern: - 5/ - 4 + "CST" / "CDT" / ; Central: - 6/ - 5 + "MST" / "MDT" / ; Mountain: - 7/ - 6 + "PST" / "PDT" / ; Pacific: - 8/ - 7 + + %d65-73 / ; Military zones - "A" + %d75-90 / ; through "I" and "K" + %d97-105 / ; through "Z", both + %d107-122 ; upper and lower case +*/ + +enum { + STATE_ZONE_1 = 0, + STATE_ZONE_2 = 1, + STATE_ZONE_3 = 2, + STATE_ZONE_OK = 3, + STATE_ZONE_ERR = 4, + STATE_ZONE_CONT = 5 +}; + +static int mailimf_zone_parse(const char * message, size_t length, + size_t * indx, int * result) +{ + int zone; + int sign; + size_t cur_token; + int r; + uint32_t value; + + cur_token = * indx; + + if (cur_token + 1 < length) { + if ((message[cur_token] == 'U') && (message[cur_token + 1] == 'T')) { + * result = TRUE; + * indx = cur_token + 2; + + return MAILIMF_NO_ERROR; + } + } + + zone = 0; + if (cur_token + 2 < length) { + int state; + + state = STATE_ZONE_1; + + while (state <= 2) { + switch (state) { + case STATE_ZONE_1: + switch (message[cur_token]) { + case 'G': + if (message[cur_token + 1] == 'M' && message[cur_token + 2] == 'T') { + if ((cur_token + 3 < length) && ((message[cur_token + 3] == '+') || (message[cur_token + 3] == '-'))) { + cur_token += 3; + state = STATE_ZONE_CONT; + } + else { + zone = 0; + state = STATE_ZONE_OK; + } + } + else { + state = STATE_ZONE_ERR; + } + break; + case 'E': + zone = -5; + state = STATE_ZONE_2; + break; + case 'C': + zone = -6; + state = STATE_ZONE_2; + break; + case 'M': + zone = -7; + state = STATE_ZONE_2; + break; + case 'P': + zone = -8; + state = STATE_ZONE_2; + break; + default: + state = STATE_ZONE_CONT; + break; + } + break; + case STATE_ZONE_2: + switch (message[cur_token + 1]) { + case 'S': + state = STATE_ZONE_3; + break; + case 'D': + zone ++; + state = STATE_ZONE_3; + break; + default: + state = STATE_ZONE_ERR; + break; + } + break; + case STATE_ZONE_3: + if (message[cur_token + 2] == 'T') { + zone *= 100; + state = STATE_ZONE_OK; + } + else + state = STATE_ZONE_ERR; + break; + } + } + + switch (state) { + case STATE_ZONE_OK: + * result = zone; + * indx = cur_token + 3; + return MAILIMF_NO_ERROR; + + case STATE_ZONE_ERR: + return MAILIMF_ERROR_PARSE; + } + } + + sign = 1; + r = mailimf_plus_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + sign = 1; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_minus_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + sign = -1; + } + + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) + sign = 1; + else + return r; + + r = mailimf_number_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) + return r; + + zone = value * sign; + + * indx = cur_token; + * result = zone; + + return MAILIMF_NO_ERROR; +} + +/* +address = mailbox / group +*/ + +LIBETPAN_EXPORT +int mailimf_address_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_address ** result) +{ + int type; + size_t cur_token; + struct mailimf_mailbox * mailbox; + struct mailimf_group * group; + struct mailimf_address * address; + int r; + int res; + + cur_token = * indx; + + mailbox = NULL; + group = NULL; + + type = MAILIMF_ADDRESS_ERROR; /* XXX - removes a gcc warning */ + r = mailimf_group_parse(message, length, &cur_token, &group); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_ADDRESS_GROUP; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_mailbox_parse(message, length, &cur_token, &mailbox); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_ADDRESS_MAILBOX; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + address = mailimf_address_new(type, mailbox, group); + if (address == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = address; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (mailbox != NULL) + mailimf_mailbox_free(mailbox); + if (group != NULL) + mailimf_group_free(group); + err: + return res; +} + + +/* +mailbox = name-addr / addr-spec +*/ + + +LIBETPAN_EXPORT +int mailimf_mailbox_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_mailbox ** result) +{ + size_t cur_token; + char * display_name; + struct mailimf_mailbox * mailbox; + char * addr_spec; + int r; + int res; + + cur_token = * indx; + display_name = NULL; + addr_spec = NULL; + + r = mailimf_name_addr_parse(message, length, &cur_token, + &display_name, &addr_spec); + if (r == MAILIMF_ERROR_PARSE) + r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec); + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + mailbox = mailimf_mailbox_new(display_name, addr_spec); + if (mailbox == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = mailbox; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (display_name != NULL) + mailimf_display_name_free(display_name); + if (addr_spec != NULL) + mailimf_addr_spec_free(addr_spec); + err: + return res; +} + +/* +name-addr = [display-name] angle-addr +*/ + +static int mailimf_name_addr_parse(const char * message, size_t length, + size_t * indx, + char ** pdisplay_name, + char ** pangle_addr) +{ + char * display_name; + char * angle_addr; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + display_name = NULL; + angle_addr = NULL; + + r = mailimf_display_name_parse(message, length, &cur_token, &display_name); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_angle_addr_parse(message, length, &cur_token, &angle_addr); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_display_name; + } + + * pdisplay_name = display_name; + * pangle_addr = angle_addr; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_display_name: + if (display_name != NULL) + mailimf_display_name_free(display_name); + err: + return res; +} + +/* +angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr +*/ + +static int mailimf_angle_addr_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + size_t cur_token; + char * addr_spec; + int r; + + cur_token = * indx; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_lower_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_greater_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + free(addr_spec); + return r; + } + + * result = addr_spec; + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +group = display-name ":" [mailbox-list / CFWS] ";" + [CFWS] +*/ + +static int mailimf_group_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_group ** result) +{ + size_t cur_token; + char * display_name; + struct mailimf_mailbox_list * mailbox_list; + struct mailimf_group * group; + int r; + int res; + clist * list; + + cur_token = * indx; + + mailbox_list = NULL; + + r = mailimf_display_name_parse(message, length, &cur_token, &display_name); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_display_name; + } + + r = mailimf_mailbox_list_parse(message, length, &cur_token, &mailbox_list); + switch (r) { + case MAILIMF_NO_ERROR: + break; + case MAILIMF_ERROR_PARSE: + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free_display_name; + } + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_display_name; + } + mailbox_list = mailimf_mailbox_list_new(list); + if (mailbox_list == NULL) { + res = MAILIMF_ERROR_MEMORY; + clist_free(list); + goto free_display_name; + } + break; + default: + res = r; + goto free_display_name; + } + + r = mailimf_semi_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_mailbox_list; + } + + group = mailimf_group_new(display_name, mailbox_list); + if (group == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_mailbox_list; + } + + * indx = cur_token; + * result = group; + + return MAILIMF_NO_ERROR; + + free_mailbox_list: + if (mailbox_list != NULL) { + mailimf_mailbox_list_free(mailbox_list); + } + free_display_name: + mailimf_display_name_free(display_name); + err: + return res; +} + +/* +display-name = phrase +*/ + +static int mailimf_display_name_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + return mailimf_phrase_parse(message, length, indx, result); +} + +/* +mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list +*/ + +LIBETPAN_EXPORT +int +mailimf_mailbox_list_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_mailbox_list ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_mailbox_list * mailbox_list; + int r; + int res; + + cur_token = * indx; + + r = mailimf_struct_list_parse(message, length, + &cur_token, &list, ',', + (mailimf_struct_parser *) + mailimf_mailbox_parse, + (mailimf_struct_destructor *) + mailimf_mailbox_free); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + mailbox_list = mailimf_mailbox_list_new(list); + if (mailbox_list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = mailbox_list; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL); + clist_free(list); + err: + return res; +} + +/* +address-list = (address *("," address)) / obs-addr-list +*/ + + +LIBETPAN_EXPORT +int +mailimf_address_list_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_address_list ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_address_list * address_list; + int r; + int res; + + cur_token = * indx; + + r = mailimf_struct_list_parse(message, length, + &cur_token, &list, ',', + (mailimf_struct_parser *) + mailimf_address_parse, + (mailimf_struct_destructor *) + mailimf_address_free); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + address_list = mailimf_address_list_new(list); + if (address_list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = address_list; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_address_free, NULL); + clist_free(list); + err: + return res; +} + +/* +addr-spec = local-part "@" domain +*/ + + +static int mailimf_addr_spec_parse(const char * message, size_t length, + size_t * indx, + char ** result) +{ + size_t cur_token; +#if 0 + char * local_part; + char * domain; +#endif + char * addr_spec; + int r; + int res; + size_t begin; + size_t end; + int final; + size_t count; + const char * src; + char * dest; + size_t i; + + cur_token = * indx; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + end = cur_token; + if (end >= length) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + begin = cur_token; + + final = FALSE; + while (1) { + switch (message[end]) { + case '>': + case ',': + case '\r': + case '\n': + case '(': + case ')': + case ':': + case ';': + final = TRUE; + break; + } + + if (final) + break; + + end ++; + if (end >= length) + break; + } + + if (end == begin) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + addr_spec = malloc(end - cur_token + 1); + if (addr_spec == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + count = end - cur_token; + src = message + cur_token; + dest = addr_spec; + for(i = 0 ; i < count ; i ++) { + if ((* src != ' ') && (* src != '\t')) { + * dest = * src; + dest ++; + } + src ++; + } + * dest = '\0'; + +#if 0 + strncpy(addr_spec, message + cur_token, end - cur_token); + addr_spec[end - cur_token] = '\0'; +#endif + + cur_token = end; + +#if 0 + r = mailimf_local_part_parse(message, length, &cur_token, &local_part); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_at_sign_parse(message, length, &cur_token); + switch (r) { + case MAILIMF_NO_ERROR: + r = mailimf_domain_parse(message, length, &cur_token, &domain); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_local_part; + } + break; + + case MAILIMF_ERROR_PARSE: + domain = NULL; + break; + + default: + res = r; + goto free_local_part; + } + + if (domain) { + addr_spec = malloc(strlen(local_part) + strlen(domain) + 2); + if (addr_spec == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_domain; + } + + strcpy(addr_spec, local_part); + strcat(addr_spec, "@"); + strcat(addr_spec, domain); + + mailimf_domain_free(domain); + mailimf_local_part_free(local_part); + } + else { + addr_spec = local_part; + } +#endif + + * result = addr_spec; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + +#if 0 + free_domain: + mailimf_domain_free(domain); + free_local_part: + mailimf_local_part_free(local_part); +#endif + err: + return res; +} + + +/* + for msg id + addr-spec = local-part "@" domain + */ + +static int mailimf_addr_spec_msg_id_parse(const char * message, size_t length, + size_t * indx, + char ** result) +{ + size_t cur_token; + char * addr_spec; + int r; + int res; + size_t begin; + size_t end; + int final; + size_t count; + const char * src; + char * dest; + size_t i; + + cur_token = * indx; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + end = cur_token; + if (end >= length) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + begin = cur_token; + + final = FALSE; + while (1) { + switch (message[end]) { + case '>': + case '\r': + case '\n': + final = TRUE; + break; + } + + if (final) + break; + + end ++; + if (end >= length) + break; + } + + if (end == begin) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + addr_spec = malloc(end - cur_token + 1); + if (addr_spec == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + count = end - cur_token; + src = message + cur_token; + dest = addr_spec; + for(i = 0 ; i < count ; i ++) { + if ((* src != ' ') && (* src != '\t')) { + * dest = * src; + dest ++; + } + src ++; + } + * dest = '\0'; + + cur_token = end; + + * result = addr_spec; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + +err: + return res; +} + +/* +local-part = dot-atom / quoted-string / obs-local-part +*/ + +#if 0 +static int mailimf_local_part_parse(const char * message, size_t length, + size_t * indx, + char ** result) +{ + int r; + + r = mailimf_dot_atom_parse(message, length, indx, result); + switch (r) { + case MAILIMF_NO_ERROR: + return r; + case MAILIMF_ERROR_PARSE: + break; + default: + return r; + } + + r = mailimf_quoted_string_parse(message, length, indx, result); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +/* +domain = dot-atom / domain-literal / obs-domain +*/ + +#if 0 +static int mailimf_domain_parse(const char * message, size_t length, + size_t * indx, + char ** result) +{ + int r; + + r = mailimf_dot_atom_parse(message, length, indx, result); + switch (r) { + case MAILIMF_NO_ERROR: + return r; + case MAILIMF_ERROR_PARSE: + break; + default: + return r; + } + + r = mailimf_domain_literal_parse(message, length, indx, result); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +/* +[FWS] dcontent +*/ + +#if 0 +static int +mailimf_domain_literal_fws_dcontent_parse(const char * message, size_t length, + size_t * indx) +{ + size_t cur_token; + char ch; + int r; + + cur_token = * indx; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_dcontent_parse(message, length, &cur_token, &ch); + if (r != MAILIMF_NO_ERROR) + return r; + + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} +#endif + +/* +domain-literal = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS] +*/ + +#if 0 +static int mailimf_domain_literal_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + size_t cur_token; + int len; + int begin; + char * domain_literal; + int r; + + cur_token = * indx; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + begin = cur_token; + r = mailimf_obracket_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + while (1) { + r = mailimf_domain_literal_fws_dcontent_parse(message, length, + &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else + return r; + } + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_cbracket_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + len = cur_token - begin; + + domain_literal = malloc(len + 1); + if (domain_literal == NULL) + return MAILIMF_ERROR_MEMORY; + strncpy(domain_literal, message + begin, len); + domain_literal[len] = '\0'; + + * result = domain_literal; + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} +#endif + +/* +dcontent = dtext / quoted-pair +*/ + +#if 0 +static int mailimf_dcontent_parse(const char * message, size_t length, + size_t * indx, char * result) +{ + size_t cur_token; + char ch; + int r; + + cur_token = * indx; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (is_dtext(message[cur_token])) { + ch = message[cur_token]; + cur_token ++; + } + else { + r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch); + + if (r != MAILIMF_NO_ERROR) + return r; + } + + * indx = cur_token; + * result = ch; + + return MAILIMF_NO_ERROR; +} +#endif + + +/* +dtext = NO-WS-CTL / ; Non white space controls + + %d33-90 / ; The rest of the US-ASCII + %d94-126 ; characters not including "[", + ; "]", or "\" +*/ + +static inline int is_dtext(char ch) +{ + unsigned char uch = (unsigned char) ch; + + if (is_no_ws_ctl(ch)) + return TRUE; + + if (uch < 33) + return FALSE; + + if ((uch >= 91) && (uch <= 93)) + return FALSE; + + if (uch == 127) + return FALSE; + + return TRUE; +} + +/* +message = (fields / obs-fields) + [CRLF body] +*/ + +LIBETPAN_EXPORT +int mailimf_message_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_message ** result) +{ + struct mailimf_fields * fields; + struct mailimf_body * body; + struct mailimf_message * msg; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + r = mailimf_fields_parse(message, length, &cur_token, &fields); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_crlf_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_body_parse(message, length, &cur_token, &body); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_fields; + } + + msg = mailimf_message_new(fields, body); + if (msg == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_body; + } + + * indx = cur_token; + * result = msg; + + return MAILIMF_NO_ERROR; + + free_body: + mailimf_body_free(body); + free_fields: + mailimf_fields_free(fields); + err: + return res; +} + +/* +body = *(*998text CRLF) *998text +*/ + +LIBETPAN_EXPORT +int mailimf_body_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_body ** result) +{ + size_t cur_token; + struct mailimf_body * body; + + cur_token = * indx; + + body = mailimf_body_new(message + cur_token, length - cur_token); + if (body == NULL) + return MAILIMF_ERROR_MEMORY; + + cur_token = length; + + * result = body; + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +CHANGE TO THE RFC 2822 + +original : + +fields = *(trace + *(resent-date / + resent-from / + resent-sender / + resent-to / + resent-cc / + resent-bcc / + resent-msg-id)) + *(orig-date / + from / + sender / + reply-to / + to / + cc / + bcc / + message-id / + in-reply-to / + references / + subject / + comments / + keywords / + optional-field) + +INTO THE FOLLOWING : +*/ + +/* +resent-fields-list = *(resent-date / + resent-from / + resent-sender / + resent-to / + resent-cc / + resent-bcc / + resent-msg-id)) +*/ + +#if 0 +enum { + RESENT_HEADER_START, +}; + +static int guess_resent_header_type(char * message, + size_t length, size_t indx) +{ + int r; + + r = mailimf_token_case_insensitive_parse(message, + length, &indx, "Resent-"); + if (r != MAILIMF_NO_ERROR) + return MAILIMF_RESENT_FIELD_NONE; + + if (indx >= length) + return MAILIMF_RESENT_FIELD_NONE; + + switch(toupper(message[indx])) { + case 'D': + return MAILIMF_RESENT_FIELD_DATE; + case 'F': + return MAILIMF_RESENT_FIELD_FROM; + case 'S': + return MAILIMF_RESENT_FIELD_SENDER; + case 'T': + return MAILIMF_RESENT_FIELD_TO; + case 'C': + return MAILIMF_RESENT_FIELD_CC; + case 'B': + return MAILIMF_RESENT_FIELD_BCC; + case 'M': + return MAILIMF_RESENT_FIELD_MSG_ID; + default: + return MAILIMF_RESENT_FIELD_NONE; + } +} +#endif + +#if 0 +static int +mailimf_resent_field_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_resent_field ** result) +{ + struct mailimf_orig_date * resent_date; + struct mailimf_from * resent_from; + struct mailimf_sender * resent_sender; + struct mailimf_to* resent_to; + struct mailimf_cc * resent_cc; + struct mailimf_bcc * resent_bcc; + struct mailimf_message_id * resent_msg_id; + size_t cur_token; + int type; + struct mailimf_resent_field * resent_field; + int r; + int res; + + cur_token = * indx; + + resent_date = NULL; + resent_from = NULL; + resent_sender = NULL; + resent_to = NULL; + resent_cc = NULL; + resent_bcc = NULL; + resent_msg_id = NULL; + + type = guess_resent_header_type(message, length, cur_token); + + switch(type) { + case MAILIMF_RESENT_FIELD_DATE: + r = mailimf_resent_date_parse(message, length, &cur_token, + &resent_date); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMF_RESENT_FIELD_FROM: + r = mailimf_resent_from_parse(message, length, &cur_token, + &resent_from); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMF_RESENT_FIELD_SENDER: + r = mailimf_resent_sender_parse(message, length, &cur_token, + &resent_sender); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMF_RESENT_FIELD_TO: + r = mailimf_resent_to_parse(message, length, &cur_token, + &resent_to); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMF_RESENT_FIELD_CC: + r= mailimf_resent_cc_parse(message, length, &cur_token, + &resent_cc); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMF_RESENT_FIELD_BCC: + r = mailimf_resent_bcc_parse(message, length, &cur_token, + &resent_bcc); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMF_RESENT_FIELD_MSG_ID: + r = mailimf_resent_msg_id_parse(message, length, &cur_token, + &resent_msg_id); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + default: + res = MAILIMF_ERROR_PARSE; + goto err; + } + + resent_field = mailimf_resent_field_new(type, resent_date, + resent_from, resent_sender, + resent_to, resent_cc, + resent_bcc, resent_msg_id); + if (resent_field == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_resent; + } + + * result = resent_field; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_resent: + if (resent_msg_id != NULL) + mailimf_message_id_free(resent_msg_id); + if (resent_bcc != NULL) + mailimf_bcc_free(resent_bcc); + if (resent_cc != NULL) + mailimf_cc_free(resent_cc); + if (resent_to != NULL) + mailimf_to_free(resent_to); + if (resent_sender != NULL) + mailimf_sender_free(resent_sender); + if (resent_from != NULL) + mailimf_from_free(resent_from); + if (resent_date != NULL) + mailimf_orig_date_free(resent_date); + err: + return res; +} +#endif + +#if 0 +static int +mailimf_resent_fields_list_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_resent_fields_list ** result) +{ + clist * list; + size_t cur_token; + struct mailimf_resent_fields_list * resent_fields_list; + int r; + int res; + + cur_token = * indx; + list = NULL; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, &list, + (mailimf_struct_parser *) + mailimf_resent_field_parse, + (mailimf_struct_destructor *) + mailimf_resent_field_free); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + resent_fields_list = mailimf_resent_fields_list_new(list); + if (resent_fields_list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = resent_fields_list; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_resent_field_free, NULL); + clist_free(list); + err: + return res; +} +#endif + +/* + ([trace] + [resent-fields-list]) +*/ + +#if 0 +static int +mailimf_trace_resent_fields_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_trace_resent_fields ** result) +{ + size_t cur_token; + struct mailimf_return * return_path; + struct mailimf_resent_fields_list * resent_fields; + struct mailimf_trace_resent_fields * trace_resent_fields; + int res; + int r; + + cur_token = * indx; + + return_path = NULL; + resent_fields = NULL; + + r = mailimf_return_parse(message, length, &cur_token, + &return_path); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_resent_fields_list_parse(message, length, &cur_token, + &resent_fields); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + if ((return_path == NULL) && (resent_fields == NULL)) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + trace_resent_fields = mailimf_trace_resent_fields_new(return_path, + resent_fields); + if (trace_resent_fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_resent_fields; + } + + * result = trace_resent_fields; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_resent_fields: + if (resent_fields != NULL) + mailimf_resent_fields_list_free(resent_fields); + if (return_path != NULL) + mailimf_return_free(return_path); + err: + return res; +} +#endif + +/* +delivering-info = *([trace] + [resent-fields-list]) +*/ + +#if 0 +static int +mailimf_delivering_info_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_delivering_info ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_delivering_info * delivering_info; + int r; + int res; + + cur_token = * indx; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &list, + (mailimf_struct_parser *) + mailimf_trace_resent_fields_parse, + (mailimf_struct_destructor *) + mailimf_trace_resent_fields_free); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + delivering_info = mailimf_delivering_info_new(list); + if (delivering_info == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = delivering_info; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_trace_resent_fields_free, NULL); + clist_free(list); + err: + return res; +} +#endif + +/* +field = delivering-info / + orig-date / + from / + sender / + reply-to / + to / + cc / + bcc / + message-id / + in-reply-to / + references / + subject / + comments / + keywords / + optional-field +*/ + +enum { + HEADER_START, + HEADER_C, + HEADER_R, + HEADER_RE, + HEADER_S, + HEADER_RES +}; + +static int guess_header_type(const char * message, size_t length, size_t indx) +{ + int state; + int r; + + state = HEADER_START; + + while (1) { + + if (indx >= length) + return MAILIMF_FIELD_NONE; + + switch(state) { + case HEADER_START: + switch((char) toupper((unsigned char) message[indx])) { + case 'B': + return MAILIMF_FIELD_BCC; + case 'C': + state = HEADER_C; + break; + case 'D': + return MAILIMF_FIELD_ORIG_DATE; + case 'F': + return MAILIMF_FIELD_FROM; + case 'I': + return MAILIMF_FIELD_IN_REPLY_TO; + case 'K': + return MAILIMF_FIELD_KEYWORDS; + case 'M': + return MAILIMF_FIELD_MESSAGE_ID; + case 'R': + state = HEADER_R; + break; + case 'T': + return MAILIMF_FIELD_TO; + break; + case 'S': + state = HEADER_S; + break; + default: + return MAILIMF_FIELD_NONE; + } + break; + case HEADER_C: + switch((char) toupper((unsigned char) message[indx])) { + case 'O': + return MAILIMF_FIELD_COMMENTS; + case 'C': + return MAILIMF_FIELD_CC; + default: + return MAILIMF_FIELD_NONE; + } + break; + case HEADER_R: + switch((char) toupper((unsigned char) message[indx])) { + case 'E': + state = HEADER_RE; + break; + default: + return MAILIMF_FIELD_NONE; + } + break; + case HEADER_RE: + switch((char) toupper((unsigned char) message[indx])) { + case 'F': + return MAILIMF_FIELD_REFERENCES; + case 'P': + return MAILIMF_FIELD_REPLY_TO; + case 'S': + state = HEADER_RES; + break; + case 'T': + return MAILIMF_FIELD_RETURN_PATH; + default: + return MAILIMF_FIELD_NONE; + } + break; + case HEADER_S: + switch((char) toupper((unsigned char) message[indx])) { + case 'E': + return MAILIMF_FIELD_SENDER; + case 'U': + return MAILIMF_FIELD_SUBJECT; + default: + return MAILIMF_FIELD_NONE; + } + break; + + case HEADER_RES: + r = mailimf_token_case_insensitive_parse(message, + length, &indx, "ent-"); + if (r != MAILIMF_NO_ERROR) + return MAILIMF_FIELD_NONE; + + if (indx >= length) + return MAILIMF_FIELD_NONE; + + switch((char) toupper((unsigned char) message[indx])) { + case 'D': + return MAILIMF_FIELD_RESENT_DATE; + case 'F': + return MAILIMF_FIELD_RESENT_FROM; + case 'S': + return MAILIMF_FIELD_RESENT_SENDER; + case 'T': + return MAILIMF_FIELD_RESENT_TO; + case 'C': + return MAILIMF_FIELD_RESENT_CC; + case 'B': + return MAILIMF_FIELD_RESENT_BCC; + case 'M': + return MAILIMF_FIELD_RESENT_MSG_ID; + default: + return MAILIMF_FIELD_NONE; + } + break; + } + indx ++; + } +} + +static int mailimf_field_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_field ** result) +{ + size_t cur_token; + int type; + struct mailimf_return * return_path; + struct mailimf_orig_date * resent_date; + struct mailimf_from * resent_from; + struct mailimf_sender * resent_sender; + struct mailimf_to* resent_to; + struct mailimf_cc * resent_cc; + struct mailimf_bcc * resent_bcc; + struct mailimf_message_id * resent_msg_id; + struct mailimf_orig_date * orig_date; + struct mailimf_from * from; + struct mailimf_sender * sender; + struct mailimf_reply_to * reply_to; + struct mailimf_to * to; + struct mailimf_cc * cc; + struct mailimf_bcc * bcc; + struct mailimf_message_id * message_id; + struct mailimf_in_reply_to * in_reply_to; + struct mailimf_references * references; + struct mailimf_subject * subject; + struct mailimf_comments * comments; + struct mailimf_keywords * keywords; + struct mailimf_optional_field * optional_field; + struct mailimf_field * field; + int guessed_type; + int r; + int res; + + cur_token = * indx; + + return_path = NULL; + resent_date = NULL; + resent_from = NULL; + resent_sender = NULL; + resent_to = NULL; + resent_cc = NULL; + resent_bcc = NULL; + resent_msg_id = NULL; + orig_date = NULL; + from = NULL; + sender = NULL; + reply_to = NULL; + to = NULL; + cc = NULL; + bcc = NULL; + message_id = NULL; + in_reply_to = NULL; + references = NULL; + subject = NULL; + comments = NULL; + keywords = NULL; + optional_field = NULL; + + guessed_type = guess_header_type(message, length, cur_token); + type = MAILIMF_FIELD_NONE; + + switch (guessed_type) { + case MAILIMF_FIELD_ORIG_DATE: + r = mailimf_orig_date_parse(message, length, &cur_token, + &orig_date); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_FIELD_ORIG_DATE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_FROM: + r = mailimf_from_parse(message, length, &cur_token, + &from); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_SENDER: + r = mailimf_sender_parse(message, length, &cur_token, + &sender); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_REPLY_TO: + r = mailimf_reply_to_parse(message, length, &cur_token, + &reply_to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_TO: + r = mailimf_to_parse(message, length, &cur_token, + &to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_CC: + r = mailimf_cc_parse(message, length, &cur_token, + &cc); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_BCC: + r = mailimf_bcc_parse(message, length, &cur_token, + &bcc); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_MESSAGE_ID: + r = mailimf_message_id_parse(message, length, &cur_token, + &message_id); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_IN_REPLY_TO: + r = mailimf_in_reply_to_parse(message, length, &cur_token, + &in_reply_to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_REFERENCES: + r = mailimf_references_parse(message, length, &cur_token, + &references); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_SUBJECT: + r = mailimf_subject_parse(message, length, &cur_token, + &subject); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_COMMENTS: + r = mailimf_comments_parse(message, length, &cur_token, + &comments); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_KEYWORDS: + r = mailimf_keywords_parse(message, length, &cur_token, + &keywords); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RETURN_PATH: + r = mailimf_return_parse(message, length, &cur_token, + &return_path); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_DATE: + r = mailimf_resent_date_parse(message, length, &cur_token, + &resent_date); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_FROM: + r = mailimf_resent_from_parse(message, length, &cur_token, + &resent_from); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_SENDER: + r = mailimf_resent_sender_parse(message, length, &cur_token, + &resent_sender); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_TO: + r = mailimf_resent_to_parse(message, length, &cur_token, + &resent_to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_CC: + r= mailimf_resent_cc_parse(message, length, &cur_token, + &resent_cc); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_BCC: + r = mailimf_resent_bcc_parse(message, length, &cur_token, + &resent_bcc); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_MSG_ID: + r = mailimf_resent_msg_id_parse(message, length, &cur_token, + &resent_msg_id); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + } + + if (type == MAILIMF_FIELD_NONE) { + r = mailimf_optional_field_parse(message, length, &cur_token, + &optional_field); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + type = MAILIMF_FIELD_OPTIONAL_FIELD; + } + + field = mailimf_field_new(type, return_path, resent_date, + resent_from, resent_sender, resent_to, resent_cc, resent_bcc, + resent_msg_id, orig_date, from, sender, reply_to, to, + cc, bcc, message_id, in_reply_to, references, + subject, comments, keywords, optional_field); + if (field == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_field; + } + + * result = field; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_field: + if (return_path != NULL) + mailimf_return_free(return_path); + if (resent_date != NULL) + mailimf_orig_date_free(resent_date); + if (resent_from != NULL) + mailimf_from_free(resent_from); + if (resent_sender != NULL) + mailimf_sender_free(resent_sender); + if (resent_to != NULL) + mailimf_to_free(resent_to); + if (resent_cc != NULL) + mailimf_cc_free(resent_cc); + if (resent_bcc != NULL) + mailimf_bcc_free(resent_bcc); + if (resent_msg_id != NULL) + mailimf_message_id_free(resent_msg_id); + if (orig_date != NULL) + mailimf_orig_date_free(orig_date); + if (from != NULL) + mailimf_from_free(from); + if (sender != NULL) + mailimf_sender_free(sender); + if (reply_to != NULL) + mailimf_reply_to_free(reply_to); + if (to != NULL) + mailimf_to_free(to); + if (cc != NULL) + mailimf_cc_free(cc); + if (bcc != NULL) + mailimf_bcc_free(bcc); + if (message_id != NULL) + mailimf_message_id_free(message_id); + if (in_reply_to != NULL) + mailimf_in_reply_to_free(in_reply_to); + if (references != NULL) + mailimf_references_free(references); + if (subject != NULL) + mailimf_subject_free(subject); + if (comments != NULL) + mailimf_comments_free(comments); + if (keywords != NULL) + mailimf_keywords_free(keywords); + if (optional_field != NULL) + mailimf_optional_field_free(optional_field); + err: + return res; +} + + +/* +fields = *(delivering-info / + orig-date / + from / + sender / + reply-to / + to / + cc / + bcc / + message-id / + in-reply-to / + references / + subject / + comments / + keywords / + optional-field) +*/ + +#if 0 +int +mailimf_unparsed_fields_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_unparsed_fields ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_unparsed_fields * fields; + int r; + int res; + + cur_token = * indx; + + list = NULL; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &list, + (mailimf_struct_parser *) + mailimf_optional_field_parse, + (mailimf_struct_destructor *) + mailimf_optional_field_free); + /* + if ((r = MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + */ + + switch (r) { + case MAILIMF_NO_ERROR: + /* do nothing */ + break; + + case MAILIMF_ERROR_PARSE: + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + break; + + default: + res = r; + goto err; + } + + fields = mailimf_unparsed_fields_new(list); + if (fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = fields; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimf_optional_field_free, NULL); + clist_free(list); + } + err: + return res; +} +#endif + +LIBETPAN_EXPORT +int mailimf_fields_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_fields ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_fields * fields; + int r; + int res; + + cur_token = * indx; + + list = NULL; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &list, + (mailimf_struct_parser *) + mailimf_field_parse, + (mailimf_struct_destructor *) + mailimf_field_free); + /* + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + */ + + switch (r) { + case MAILIMF_NO_ERROR: + /* do nothing */ + break; + + case MAILIMF_ERROR_PARSE: + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + break; + + default: + res = r; + goto err; + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = fields; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + } + err: + return res; +} + +/* +orig-date = "Date:" date-time CRLF +*/ + + +static int +mailimf_orig_date_parse(const char * message, size_t length, + size_t * indx, struct mailimf_orig_date ** result) +{ + struct mailimf_date_time * date_time; + struct mailimf_orig_date * orig_date; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Date:"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_date_time_parse(message, length, &cur_token, &date_time); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_ignore_unstructured_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_date_time; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_date_time; + } + + orig_date = mailimf_orig_date_new(date_time); + if (orig_date == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_date_time; + } + + * result = orig_date; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_date_time: + mailimf_date_time_free(date_time); + err: + return res; +} + +/* +from = "From:" mailbox-list CRLF +*/ + +static int +mailimf_from_parse(const char * message, size_t length, + size_t * indx, struct mailimf_from ** result) +{ + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "From"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list); + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_mb_list; + } + + from = mailimf_from_new(mb_list); + if (from == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_mb_list; + } + + * result = from; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_mb_list: + mailimf_mailbox_list_free(mb_list); + err: + return res; +} + +/* +sender = "Sender:" mailbox CRLF +*/ + +static int +mailimf_sender_parse(const char * message, size_t length, + size_t * indx, struct mailimf_sender ** result) +{ + struct mailimf_mailbox * mb; + struct mailimf_sender * sender; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Sender"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_mailbox_parse(message, length, &cur_token, &mb); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_mb; + } + + sender = mailimf_sender_new(mb); + if (sender == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_mb; + } + + * result = sender; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_mb: + mailimf_mailbox_free(mb); + err: + return res; +} + +/* +reply-to = "Reply-To:" address-list CRLF +*/ + + +static int +mailimf_reply_to_parse(const char * message, size_t length, + size_t * indx, struct mailimf_reply_to ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_reply_to * reply_to; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Reply-To"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + reply_to = mailimf_reply_to_new(addr_list); + if (reply_to == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = reply_to; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +to = "To:" address-list CRLF +*/ + +static int +mailimf_to_parse(const char * message, size_t length, + size_t * indx, struct mailimf_to ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_to * to; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "To"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + to = mailimf_to_new(addr_list); + if (to == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = to; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +cc = "Cc:" address-list CRLF +*/ + + +static int +mailimf_cc_parse(const char * message, size_t length, + size_t * indx, struct mailimf_cc ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_cc * cc; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Cc"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + cc = mailimf_cc_new(addr_list); + if (cc == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = cc; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +bcc = "Bcc:" (address-list / [CFWS]) CRLF +*/ + + +static int +mailimf_bcc_parse(const char * message, size_t length, + size_t * indx, struct mailimf_bcc ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_bcc * bcc; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + addr_list = NULL; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Bcc"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + switch (r) { + case MAILIMF_NO_ERROR: + /* do nothing */ + break; + case MAILIMF_ERROR_PARSE: + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + break; + default: + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + bcc = mailimf_bcc_new(addr_list); + if (bcc == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + * result = bcc; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + err: + if (addr_list != NULL) + mailimf_address_list_free(addr_list); + return res; +} + +/* +message-id = "Message-ID:" msg-id CRLF +*/ + +static int mailimf_message_id_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_message_id ** result) +{ + char * value; + size_t cur_token; + struct mailimf_message_id * message_id; + int r; + int res; + + cur_token = * indx; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Message-ID"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_msg_id_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_value; + } + + message_id = mailimf_message_id_new(value); + if (message_id == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_value; + } + + * result = message_id; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_value: + mailimf_msg_id_free(value); + err: + return res; +} + +/* +in-reply-to = "In-Reply-To:" 1*msg-id CRLF +*/ + +LIBETPAN_EXPORT +int mailimf_msg_id_list_parse(const char * message, size_t length, + size_t * indx, clist ** result) +{ + return mailimf_struct_multiple_parse(message, length, indx, + result, + (mailimf_struct_parser *) + mailimf_unstrict_msg_id_parse, + (mailimf_struct_destructor *) + mailimf_msg_id_free); +} + +static int mailimf_in_reply_to_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_in_reply_to ** result) +{ + struct mailimf_in_reply_to * in_reply_to; + size_t cur_token; + clist * msg_id_list; + int res; + int r; + + cur_token = * indx; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "In-Reply-To"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_list; + } + + in_reply_to = mailimf_in_reply_to_new(msg_id_list); + if (in_reply_to == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = in_reply_to; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL); + clist_free(msg_id_list); + err: + return res; +} + +/* +references = "References:" 1*msg-id CRLF +*/ + +LIBETPAN_EXPORT +int mailimf_references_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_references ** result) +{ + struct mailimf_references * references; + size_t cur_token; + clist * msg_id_list; + int r; + int res; + + cur_token = * indx; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "References"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_list; + } + + references = mailimf_references_new(msg_id_list); + if (references == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = references; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL); + clist_free(msg_id_list); + err: + return res; +} + +/* +msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS] +*/ + +LIBETPAN_EXPORT +int mailimf_msg_id_parse(const char * message, size_t length, + size_t * indx, + char ** result) +{ + size_t cur_token; +#if 0 + char * id_left; + char * id_right; +#endif + char * msg_id; + int r; + int res; + + cur_token = * indx; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_lower_parse(message, length, &cur_token); + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_addr_spec_msg_id_parse(message, length, &cur_token, &msg_id); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + * result = msg_id; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + } + else if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + // workaround for mbox mail + r = mailimf_lower_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + // ok + } + else if (r == MAILIMF_ERROR_PARSE) { + // ok + } + else { + res = r; + goto err; + } + r = mailimf_addr_spec_msg_id_parse(message, length, &cur_token, &msg_id); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_greater_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + free(msg_id); + res = r; + goto err; + } + r = mailimf_greater_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + // ok + } + else if (r == MAILIMF_ERROR_PARSE) { + // ok + } + else { + free(msg_id); + res = r; + goto err; + } + +#if 0 + r = mailimf_id_left_parse(message, length, &cur_token, &id_left); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_at_sign_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_id_left; + } + + r = mailimf_id_right_parse(message, length, &cur_token, &id_right); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_id_left; + } + + r = mailimf_greater_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_id_right; + } + + msg_id = malloc(strlen(id_left) + strlen(id_right) + 2); + if (msg_id == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_id_right; + } + strcpy(msg_id, id_left); + strcat(msg_id, "@"); + strcat(msg_id, id_right); + + mailimf_id_left_free(id_left); + mailimf_id_right_free(id_right); +#endif + + * result = msg_id; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + +#if 0 + free_id_right: + mailimf_id_right_free(id_right); + free_id_left: + mailimf_id_left_free(id_left); +#endif + /* + free: + mailimf_atom_free(msg_id); + */ + err: + return res; +} + +static int mailimf_parse_unwanted_msg_id(const char * message, size_t length, + size_t * indx) +{ + size_t cur_token; + int r; + char * word; + int token_parsed; + + cur_token = * indx; + + token_parsed = TRUE; + while (token_parsed) { + token_parsed = FALSE; + r = mailimf_word_parse(message, length, &cur_token, &word); + if (r == MAILIMF_NO_ERROR) { + mailimf_word_free(word); + token_parsed = TRUE; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + r = mailimf_semi_colon_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + token_parsed = TRUE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + r = mailimf_comma_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + token_parsed = TRUE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + r = mailimf_plus_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + token_parsed = TRUE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + r = mailimf_colon_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + token_parsed = TRUE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + r = mailimf_point_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + token_parsed = TRUE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + r = mailimf_at_sign_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + token_parsed = TRUE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + } + + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +static int mailimf_unstrict_msg_id_parse(const char * message, size_t length, + size_t * indx, + char ** result) +{ + char * msgid; + size_t cur_token; + int r; + + cur_token = * indx; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_parse_unwanted_msg_id(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_msg_id_parse(message, length, &cur_token, &msgid); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_parse_unwanted_msg_id(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + free(msgid); + return r; + } + + * result = msgid; + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +id-left = dot-atom-text / no-fold-quote / obs-id-left +*/ + +#if 0 +static int mailimf_id_left_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + int r; + + r = mailimf_dot_atom_text_parse(message, length, indx, result); + switch (r) { + case MAILIMF_NO_ERROR: + return MAILIMF_NO_ERROR; + case MAILIMF_ERROR_PARSE: + break; + default: + return r; + } + + r = mailimf_no_fold_quote_parse(message, length, indx, result); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +/* +id-right = dot-atom-text / no-fold-literal / obs-id-right +*/ + +#if 0 +static int mailimf_id_right_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + int r; + + r = mailimf_dot_atom_text_parse(message, length, indx, result); + switch (r) { + case MAILIMF_NO_ERROR: + return MAILIMF_NO_ERROR; + case MAILIMF_ERROR_PARSE: + break; + default: + return r; + } + + r = mailimf_no_fold_literal_parse(message, length, indx, result); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +/* +no-fold-quote = DQUOTE *(qtext / quoted-pair) DQUOTE +*/ + +#if 0 +static int mailimf_no_fold_quote_char_parse(const char * message, size_t length, + size_t * indx, char * result) +{ + char ch; + size_t cur_token; + int r; + + cur_token = * indx; + +#if 0 + r = mailimf_qtext_parse(message, length, &cur_token, &ch); +#endif + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (is_qtext(message[cur_token])) { + ch = message[cur_token]; + cur_token ++; + } + else { + r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch); + + if (r != MAILIMF_NO_ERROR) + return r; + } + + * indx = cur_token; + * result = ch; + + return MAILIMF_NO_ERROR; +} +#endif + +#if 0 +static int mailimf_no_fold_quote_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + size_t cur_token; + size_t begin; + char ch; + char * no_fold_quote; + int r; + int res; + + begin = cur_token; + r = mailimf_dquote_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + while (1) { + r = mailimf_no_fold_quote_char_parse(message, length, &cur_token, &ch); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto err; + } + } + + r = mailimf_dquote_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + /* no_fold_quote = strndup(message + begin, cur_token - begin); */ + no_fold_quote = malloc(cur_token - begin + 1); + if (no_fold_quote == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + strncpy(no_fold_quote, message + begin, cur_token - begin); + no_fold_quote[cur_token - begin] = '\0'; + + * result = no_fold_quote; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + err: + return res; +} +#endif + +/* +no-fold-literal = "[" *(dtext / quoted-pair) "]" +*/ + +#if 0 +static inline int +mailimf_no_fold_literal_char_parse(const char * message, size_t length, + size_t * indx, char * result) +{ + char ch; + size_t cur_token; + int r; + + cur_token = * indx; + +#if 0 + r = mailimf_dtext_parse(message, length, &cur_token, &ch); +#endif + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (is_dtext(message[cur_token])) { + ch = message[cur_token]; + cur_token ++; + } + else { + r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch); + + if (r != MAILIMF_NO_ERROR) + return r; + } + + * indx = cur_token; + * result = ch; + + return MAILIMF_NO_ERROR; +} +#endif + +#if 0 +static int mailimf_no_fold_literal_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + size_t cur_token; + size_t begin; + char ch; + char * no_fold_literal; + int r; + int res; + + begin = cur_token; + r = mailimf_obracket_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + while (1) { + r = mailimf_no_fold_literal_char_parse(message, length, + &cur_token, &ch); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto err; + } + } + + r = mailimf_cbracket_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + /* + no_fold_literal = strndup(message + begin, cur_token - begin); + */ + no_fold_literal = malloc(cur_token - begin + 1); + if (no_fold_literal == NULL) { + res = MAILIMF_NO_ERROR; + goto err; + } + strncpy(no_fold_literal, message + begin, cur_token - begin); + no_fold_literal[cur_token - begin] = '\0'; + + * result = no_fold_literal; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + err: + return res; +} +#endif + +/* +subject = "Subject:" unstructured CRLF +*/ + +static int mailimf_subject_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_subject ** result) +{ + struct mailimf_subject * subject; + char * value; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Subject"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstructured_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_value; + } + + subject = mailimf_subject_new(value); + if (subject == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_value; + } + + * result = subject; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_value: + mailimf_unstructured_free(value); + err: + return res; +} + +/* +comments = "Comments:" unstructured CRLF +*/ + +static int mailimf_comments_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_comments ** result) +{ + struct mailimf_comments * comments; + char * value; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Comments"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstructured_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_value; + } + + comments = mailimf_comments_new(value); + if (comments == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_value; + } + + * result = comments; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_value: + mailimf_unstructured_free(value); + err: + return res; +} + +/* +keywords = "Keywords:" phrase *("," phrase) CRLF +*/ + +static int mailimf_keywords_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_keywords ** result) +{ + struct mailimf_keywords * keywords; + clist * list; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Keywords"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_struct_list_parse(message, length, &cur_token, + &list, ',', + (mailimf_struct_parser *) + mailimf_phrase_parse, + (mailimf_struct_destructor *) + mailimf_phrase_free); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_list; + } + + keywords = mailimf_keywords_new(list); + if (keywords == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = keywords; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_phrase_free, NULL); + clist_free(list); + err: + return res; +} + +/* +resent-date = "Resent-Date:" date-time CRLF +*/ + +static int +mailimf_resent_date_parse(const char * message, size_t length, + size_t * indx, struct mailimf_orig_date ** result) +{ + struct mailimf_orig_date * orig_date; + struct mailimf_date_time * date_time; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-Date"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_date_time_parse(message, length, &cur_token, &date_time); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_date_time; + } + + orig_date = mailimf_orig_date_new(date_time); + if (orig_date == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_date_time; + } + + * result = orig_date; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_date_time: + mailimf_date_time_free(date_time); + err: + return res; +} + +/* +resent-from = "Resent-From:" mailbox-list CRLF +*/ + +static int +mailimf_resent_from_parse(const char * message, size_t length, + size_t * indx, struct mailimf_from ** result) +{ + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-From"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_mb_list; + } + + from = mailimf_from_new(mb_list); + if (from == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_mb_list; + } + + * result = from; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_mb_list: + mailimf_mailbox_list_free(mb_list); + err: + return res; +} + +/* +resent-sender = "Resent-Sender:" mailbox CRLF +*/ + +static int +mailimf_resent_sender_parse(const char * message, size_t length, + size_t * indx, struct mailimf_sender ** result) +{ + struct mailimf_mailbox * mb; + struct mailimf_sender * sender; + size_t cur_token; + int r; + int res; + + cur_token = length; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-Sender"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_mailbox_parse(message, length, &cur_token, &mb); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_mb; + } + + sender = mailimf_sender_new(mb); + if (sender == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_mb; + } + + * result = sender; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_mb: + mailimf_mailbox_free(mb); + err: + return res; +} + +/* +resent-to = "Resent-To:" address-list CRLF +*/ + +static int +mailimf_resent_to_parse(const char * message, size_t length, + size_t * indx, struct mailimf_to ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_to * to; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-To"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + to = mailimf_to_new(addr_list); + if (to == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = to; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +resent-cc = "Resent-Cc:" address-list CRLF +*/ + +static int +mailimf_resent_cc_parse(const char * message, size_t length, + size_t * indx, struct mailimf_cc ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_cc * cc; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-Cc"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + cc = mailimf_cc_new(addr_list); + if (cc == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = cc; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +resent-bcc = "Resent-Bcc:" (address-list / [CFWS]) CRLF +*/ + +static int +mailimf_resent_bcc_parse(const char * message, size_t length, + size_t * indx, struct mailimf_bcc ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_bcc * bcc; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + bcc = NULL; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-Bcc"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + addr_list = NULL; + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + bcc = mailimf_bcc_new(addr_list); + if (bcc == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = bcc; + * indx = cur_token; + + return TRUE; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +resent-msg-id = "Resent-Message-ID:" msg-id CRLF +*/ + +static int +mailimf_resent_msg_id_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_message_id ** result) +{ + char * value; + size_t cur_token; + struct mailimf_message_id * message_id; + int r; + int res; + + cur_token = * indx; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-Message-ID"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_msg_id_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_value; + } + + message_id = mailimf_message_id_new(value); + if (message_id == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_value; + } + + * result = message_id; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_value: + mailimf_msg_id_free(value); + err: + return res; +} + +/* +trace = [return] + 1*received +*/ + +#if 0 +static int mailimf_trace_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_trace ** result) +{ + size_t cur_token; + struct mailimf_return * return_path; + clist * received_list; + struct mailimf_trace * trace; + int r; + int res; + + cur_token = * indx; + return_path = NULL; + received_list = NULL; + + r = mailimf_return_parse(message, length, &cur_token, &return_path); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &received_list, + (mailimf_struct_parser *) + mailimf_received_parse, + (mailimf_struct_destructor *) + mailimf_received_free); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + if ((received_list == NULL) && (return_path == NULL)) { + res = MAILIMF_ERROR_PARSE; + goto free_return; + } + + trace = mailimf_trace_new(return_path, received_list); + if (trace == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = trace; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(received_list, (clist_func) mailimf_received_free, NULL); + clist_free(received_list); + free_return: + if (return_path != NULL) + mailimf_return_free(return_path); + err: + return res; +} +#endif + +/* +return = "Return-Path:" path CRLF +*/ + +static int mailimf_return_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_return ** result) +{ + struct mailimf_path * path; + struct mailimf_return * return_path; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Return-Path"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + path = NULL; + r = mailimf_path_parse(message, length, &cur_token, &path); + if ( r!= MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_path; + } + + return_path = mailimf_return_new(path); + if (return_path == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_path; + } + + * result = return_path; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_path: + mailimf_path_free(path); + err: + return res; +} + +/* +path = ([CFWS] "<" ([CFWS] / addr-spec) ">" [CFWS]) / + obs-path +*/ + +static int mailimf_path_parse(const char * message, size_t length, + size_t * indx, struct mailimf_path ** result) +{ + size_t cur_token; + char * addr_spec; + struct mailimf_path * path; + int res; + int r; + + cur_token = * indx; + addr_spec = NULL; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_lower_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec); + switch (r) { + case MAILIMF_NO_ERROR: + break; + case MAILIMF_ERROR_PARSE: + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + break; + default: + return r; + } + + r = mailimf_greater_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + path = mailimf_path_new(addr_spec); + if (path == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_spec; + } + + * indx = cur_token; + * result = path; + + return MAILIMF_NO_ERROR; + + free_addr_spec: + if (addr_spec == NULL) + mailimf_addr_spec_free(addr_spec); + err: + return res; +} + +/* +received = "Received:" name-val-list ";" date-time CRLF +*/ + +#if 0 +static int mailimf_received_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_received ** result) +{ + size_t cur_token; + struct mailimf_received * received; + struct mailimf_name_val_list * name_val_list; + struct mailimf_date_time * date_time; + int r; + int res; + + cur_token = * indx; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Received"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_name_val_list_parse(message, length, + &cur_token, &name_val_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_semi_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_name_val_list; + } + + r = mailimf_date_time_parse(message, length, &cur_token, &date_time); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_name_val_list; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_date_time; + } + + received = mailimf_received_new(name_val_list, date_time); + if (received == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_date_time; + } + + * indx = cur_token; + * result = received; + + return MAILIMF_NO_ERROR; + + free_date_time: + mailimf_date_time_free(date_time); + free_name_val_list: + mailimf_name_val_list_free(name_val_list); + err: + return res; +} +#endif + +/* +name-val-list = [CFWS] [name-val-pair *(CFWS name-val-pair)] +*/ + +#if 0 +static int +mailimf_name_val_list_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_name_val_list ** result) +{ + size_t cur_token; + struct mailimf_name_val_pair * pair; + struct mailimf_name_val_list * name_val_list; + clist* list; + int res; + int r; + + cur_token = * indx; + list = NULL; + + r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair); + + if (r == MAILIMF_NO_ERROR){ + size_t final_token; + + list = clist_new(); + if (list == NULL) { + mailimf_name_val_pair_free(pair); + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + r = clist_append(list, pair); + if (r < 0) { + mailimf_name_val_pair_free(pair); + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + final_token = cur_token; + + while (1) { + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free_list; + } + + r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free_list; + } + + r = clist_append(list, pair); + if (r < 0) { + mailimf_name_val_pair_free(pair); + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + final_token = cur_token; + } + cur_token = final_token; + } + + name_val_list = mailimf_name_val_list_new(list); + if (name_val_list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * indx = cur_token; + * result = name_val_list; + + return MAILIMF_NO_ERROR; + + free_list: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimf_name_val_pair_free, NULL); + clist_free(list); + } + err: + return res; +} +#endif + +/* +name-val-pair = item-name CFWS item-value +*/ + +#if 0 +static int +mailimf_name_val_pair_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_name_val_pair ** result) +{ + size_t cur_token; + char * item_name; + struct mailimf_item_value * item_value; + struct mailimf_name_val_pair * name_val_pair; + int r; + int res; + + cur_token = * indx; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_item_name_parse(message, length, &cur_token, &item_name); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_cfws_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_item_name; + } + + r = mailimf_item_value_parse(message, length, &cur_token, &item_value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_item_name; + } + + name_val_pair = mailimf_name_val_pair_new(item_name, item_value); + if (name_val_pair == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_item_value; + } + + * result = name_val_pair; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_item_value: + mailimf_item_value_free(item_value); + free_item_name: + mailimf_item_name_free(item_name); + err: + return res; +} +#endif + +/* +item-name = ALPHA *(["-"] (ALPHA / DIGIT)) +*/ + +#if 0 +static int mailimf_item_name_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + size_t cur_token; + size_t begin; + char * item_name; + char ch; + int digit; + int r; + int res; + + cur_token = * indx; + + begin = cur_token; + + r = mailimf_alpha_parse(message, length, &cur_token, &ch); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + while (1) { + int minus_sign; + + minus_sign = mailimf_minus_parse(message, length, &cur_token); + + r = mailimf_alpha_parse(message, length, &cur_token, &ch); + if (r == MAILIMF_ERROR_PARSE) + r = mailimf_digit_parse(message, length, &cur_token, &digit); + + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + if (r == MAILIMF_ERROR_PARSE) + break; + else if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + } + + item_name = strndup(message + begin, cur_token - begin); + if (item_name == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + * indx = cur_token; + * result = item_name; + + return MAILIMF_NO_ERROR; + + err: + return res; +} +#endif + +/* +item-value = 1*angle-addr / addr-spec / + atom / domain / msg-id +*/ + +#if 0 +static int is_item_value_atext(char ch) +{ + switch (ch) { + case '\t': + case ' ': + case '\r': + case '\n': + case ';': + return FALSE; + default: + return TRUE; + } +} + +static int mailimf_item_value_atom_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + char * atom; + size_t cur_token; + int r; + + cur_token = * indx; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_custom_string_parse(message, length, &cur_token, + &atom, is_item_value_atext); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + * indx = cur_token; + * result = atom; + + return MAILIMF_NO_ERROR; +} + +static int mailimf_item_value_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_item_value ** result) +{ + size_t cur_token; + clist * angle_addr_list; + char * addr_spec; + char * atom; + char * domain; + char * msg_id; + int type; + struct mailimf_item_value * item_value; + int r; + int res; + + cur_token = * indx; + + angle_addr_list = NULL; + addr_spec = NULL; + atom = NULL; + domain = NULL; + msg_id = NULL; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &angle_addr_list, + (mailimf_struct_parser *) + mailimf_angle_addr_parse, + (mailimf_struct_destructor *) + mailimf_angle_addr_free); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_ITEM_VALUE_ANGLE_ADDR_LIST; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_addr_spec_parse(message, length, &cur_token, + &addr_spec); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_ITEM_VALUE_ADDR_SPEC; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_msg_id_parse(message, length, &cur_token, + &msg_id); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_ITEM_VALUE_MSG_ID; + } + + /* + else if (mailimf_domain_parse(message, length, &cur_token, + &domain)) + type = MAILIMF_ITEM_VALUE_DOMAIN; + */ + /* + else if (mailimf_atom_parse(message, length, &cur_token, + &atom)) + type = MAILIMF_ITEM_VALUE_ATOM; + */ + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_item_value_atom_parse(message, length, &cur_token, + &atom); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_ITEM_VALUE_ATOM; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + item_value = mailimf_item_value_new(type, angle_addr_list, addr_spec, + atom, domain, msg_id); + if (item_value == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = item_value; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (angle_addr_list != NULL) { + clist_foreach(angle_addr_list, (clist_func) mailimf_angle_addr_free, NULL); + clist_free(angle_addr_list); + } + if (addr_spec != NULL) + mailimf_addr_spec_free(addr_spec); + if (atom != NULL) + mailimf_atom_free(atom); + if (domain != NULL) + mailimf_domain_free(domain); + if (msg_id != NULL) + mailimf_msg_id_free(msg_id); + err: + return res; +} +#endif + +/* +optional-field = field-name ":" unstructured CRLF +*/ + +static int +mailimf_optional_field_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_optional_field ** result) +{ + char * name; + char * value; + struct mailimf_optional_field * optional_field; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + r = mailimf_field_name_parse(message, length, &cur_token, &name); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_name; + } + + r = mailimf_unstructured_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_name; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_value; + } + + optional_field = mailimf_optional_field_new(name, value); + if (optional_field == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_value; + } + + * result = optional_field; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_value: + mailimf_unstructured_free(value); + free_name: + mailimf_field_name_free(name); + err: + return res; +} + +/* +field-name = 1*ftext +*/ + +static inline int is_ftext(char ch); + +static int mailimf_field_name_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + char * field_name; + size_t cur_token; + size_t end; + + cur_token = * indx; + + end = cur_token; + if (end >= length) { + return MAILIMF_ERROR_PARSE; + } + + while (is_ftext(message[end])) { + end ++; + if (end >= length) + break; + } + if (end == cur_token) { + return MAILIMF_ERROR_PARSE; + } + + /* field_name = strndup(message + cur_token, end - cur_token); */ + field_name = malloc(end - cur_token + 1); + if (field_name == NULL) { + return MAILIMF_ERROR_MEMORY; + } + strncpy(field_name, message + cur_token, end - cur_token); + field_name[end - cur_token] = '\0'; + + cur_token = end; + + * indx = cur_token; + * result = field_name; + + return MAILIMF_NO_ERROR; +} + +/* +ftext = %d33-57 / ; Any character except + %d59-126 ; controls, SP, and + ; ":". +*/ + +static inline int is_ftext(char ch) +{ + unsigned char uch = (unsigned char) ch; + + if (uch < 33) + return FALSE; + + if (uch == 58) + return FALSE; + + return TRUE; +} + +/* +static int mailimf_ftext_parse(const char * message, size_t length, + size_t * indx, gchar * result) +{ + return mailimf_typed_text_parse(message, length, indx, result, is_ftext); +} +*/ + + + + +static int mailimf_envelope_field_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_field ** result) +{ + size_t cur_token; + int type; + struct mailimf_orig_date * orig_date; + struct mailimf_from * from; + struct mailimf_sender * sender; + struct mailimf_reply_to * reply_to; + struct mailimf_to * to; + struct mailimf_cc * cc; + struct mailimf_bcc * bcc; + struct mailimf_message_id * message_id; + struct mailimf_in_reply_to * in_reply_to; + struct mailimf_references * references; + struct mailimf_subject * subject; + struct mailimf_optional_field * optional_field; + struct mailimf_field * field; + int guessed_type; + int r; + int res; + + cur_token = * indx; + + orig_date = NULL; + from = NULL; + sender = NULL; + reply_to = NULL; + to = NULL; + cc = NULL; + bcc = NULL; + message_id = NULL; + in_reply_to = NULL; + references = NULL; + subject = NULL; + optional_field = NULL; + + guessed_type = guess_header_type(message, length, cur_token); + type = MAILIMF_FIELD_NONE; + + switch (guessed_type) { + case MAILIMF_FIELD_ORIG_DATE: + r = mailimf_orig_date_parse(message, length, &cur_token, + &orig_date); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_FROM: + r = mailimf_from_parse(message, length, &cur_token, + &from); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_SENDER: + r = mailimf_sender_parse(message, length, &cur_token, + &sender); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_REPLY_TO: + r = mailimf_reply_to_parse(message, length, &cur_token, + &reply_to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_TO: + r = mailimf_to_parse(message, length, &cur_token, + &to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_CC: + r = mailimf_cc_parse(message, length, &cur_token, + &cc); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_BCC: + r = mailimf_bcc_parse(message, length, &cur_token, + &bcc); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_MESSAGE_ID: + r = mailimf_message_id_parse(message, length, &cur_token, + &message_id); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_IN_REPLY_TO: + r = mailimf_in_reply_to_parse(message, length, &cur_token, + &in_reply_to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_REFERENCES: + r = mailimf_references_parse(message, length, &cur_token, + &references); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_SUBJECT: + r = mailimf_subject_parse(message, length, &cur_token, + &subject); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + } + + if (type == MAILIMF_FIELD_NONE) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + field = mailimf_field_new(type, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + orig_date, from, sender, reply_to, to, + cc, bcc, message_id, in_reply_to, references, + subject, NULL, NULL, optional_field); + if (field == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_field; + } + + * result = field; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_field: + if (orig_date != NULL) + mailimf_orig_date_free(orig_date); + if (from != NULL) + mailimf_from_free(from); + if (sender != NULL) + mailimf_sender_free(sender); + if (reply_to != NULL) + mailimf_reply_to_free(reply_to); + if (to != NULL) + mailimf_to_free(to); + if (cc != NULL) + mailimf_cc_free(cc); + if (bcc != NULL) + mailimf_bcc_free(bcc); + if (message_id != NULL) + mailimf_message_id_free(message_id); + if (in_reply_to != NULL) + mailimf_in_reply_to_free(in_reply_to); + if (references != NULL) + mailimf_references_free(references); + if (subject != NULL) + mailimf_subject_free(subject); + if (optional_field != NULL) + mailimf_optional_field_free(optional_field); + err: + return res; +} + +LIBETPAN_EXPORT +int mailimf_envelope_fields_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_fields ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_fields * fields; + int r; + int res; + + cur_token = * indx; + + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + while (1) { + struct mailimf_field * elt; + + r = mailimf_envelope_field_parse(message, length, &cur_token, &elt); + if (r == MAILIMF_NO_ERROR) { + r = clist_append(list, elt); + if (r < 0) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + else if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_ignore_field_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + res = r; + goto free; + } + } + else { + res = r; + goto free; + } + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = fields; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + } + err: + return res; +} + + +static int +mailimf_envelope_or_optional_field_parse(const char * message, + size_t length, + size_t * indx, + struct mailimf_field ** result) +{ + int r; + size_t cur_token; + struct mailimf_optional_field * optional_field; + struct mailimf_field * field; + + r = mailimf_envelope_field_parse(message, length, indx, result); + if (r == MAILIMF_NO_ERROR) + return MAILIMF_NO_ERROR; + + cur_token = * indx; + + r = mailimf_optional_field_parse(message, length, &cur_token, + &optional_field); + if (r != MAILIMF_NO_ERROR) + return r; + + field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, optional_field); + if (field == NULL) { + mailimf_optional_field_free(optional_field); + return MAILIMF_ERROR_MEMORY; + } + + * result = field; + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + + +LIBETPAN_EXPORT +int +mailimf_envelope_and_optional_fields_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_fields ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_fields * fields; + int r; + int res; + + cur_token = * indx; + + list = NULL; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &list, + (mailimf_struct_parser *) + mailimf_envelope_or_optional_field_parse, + (mailimf_struct_destructor *) + mailimf_field_free); + switch (r) { + case MAILIMF_NO_ERROR: + /* do nothing */ + break; + + case MAILIMF_ERROR_PARSE: + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + break; + + default: + res = r; + goto err; + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = fields; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + } + err: + return res; +} + + + +static int +mailimf_only_optional_field_parse(const char * message, + size_t length, + size_t * indx, + struct mailimf_field ** result) +{ + int r; + size_t cur_token; + struct mailimf_optional_field * optional_field; + struct mailimf_field * field; + + cur_token = * indx; + + r = mailimf_optional_field_parse(message, length, &cur_token, + &optional_field); + if (r != MAILIMF_NO_ERROR) + return r; + + field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, optional_field); + if (field == NULL) { + mailimf_optional_field_free(optional_field); + return MAILIMF_ERROR_MEMORY; + } + + * result = field; + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + + +LIBETPAN_EXPORT +int +mailimf_optional_fields_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_fields ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_fields * fields; + int r; + int res; + + cur_token = * indx; + + list = NULL; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &list, + (mailimf_struct_parser *) + mailimf_only_optional_field_parse, + (mailimf_struct_destructor *) + mailimf_field_free); + switch (r) { + case MAILIMF_NO_ERROR: + /* do nothing */ + break; + + case MAILIMF_ERROR_PARSE: + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + break; + + default: + res = r; + goto err; + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = fields; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + } + err: + return res; +} diff --git a/Sources/libetpan/low-level/imf/mailimf.h b/Sources/libetpan/low-level/imf/mailimf.h new file mode 100644 index 00000000..9ce6b976 --- /dev/null +++ b/Sources/libetpan/low-level/imf/mailimf.h @@ -0,0 +1,368 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf.h,v 1.28 2008/05/27 10:07:55 hoa Exp $ + */ + +#ifndef MAILIMF_H + +#define MAILIMF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include + +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +/* + mailimf_message_parse will parse the given message + + @param message this is a string containing the message content + @param length this is the size of the given string + @param indx this is a pointer to the start of the message in + the given string, (* indx) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int mailimf_message_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_message ** result); + +/* + mailimf_body_parse will parse the given text part of a message + + @param message this is a string containing the message text part + @param length this is the size of the given string + @param indx this is a pointer to the start of the message text part in + the given string, (* indx) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int mailimf_body_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_body ** result); + +/* + mailimf_fields_parse will parse the given header fields + + @param message this is a string containing the header fields + @param length this is the size of the given string + @param indx this is a pointer to the start of the header fields in + the given string, (* indx) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int mailimf_fields_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_fields ** result); + +/* + mailimf_mailbox_list_parse will parse the given mailbox list + + @param message this is a string containing the mailbox list + @param length this is the size of the given string + @param indx this is a pointer to the start of the mailbox list in + the given string, (* indx) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int +mailimf_mailbox_list_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_mailbox_list ** result); + +/* + mailimf_address_list_parse will parse the given address list + + @param message this is a string containing the address list + @param length this is the size of the given string + @param indx this is a pointer to the start of the address list in + the given string, (* indx) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int +mailimf_address_list_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_address_list ** result); + +/* + mailimf_address_parse will parse the given address + + @param message this is a string containing the address + @param length this is the size of the given string + @param indx this is a pointer to the start of the address in + the given string, (* indx) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int mailimf_address_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_address ** result); + +/* + mailimf_mailbox_parse will parse the given address + + @param message this is a string containing the mailbox + @param length this is the size of the given string + @param indx this is a pointer to the start of the mailbox in + the given string, (* indx) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int mailimf_mailbox_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_mailbox ** result); + +/* + mailimf_date_time_parse will parse the given RFC 2822 date + + @param message this is a string containing the date + @param length this is the size of the given string + @param indx this is a pointer to the start of the date in + the given string, (* indx) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int mailimf_date_time_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_date_time ** result); + +/* + mailimf_envelope_fields_parse will parse the given fields (Date, + From, Sender, Reply-To, To, Cc, Bcc, Message-ID, In-Reply-To, + References and Subject) + + @param message this is a string containing the header fields + @param length this is the size of the given string + @param indx this is a pointer to the start of the header fields in + the given string, (* indx) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int mailimf_envelope_fields_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_fields ** result); + +/* + mailimf_ignore_field_parse will skip the given field + + @param message this is a string containing the header field + @param length this is the size of the given string + @param indx this is a pointer to the start of the header field in + the given string, (* indx) is modified to point at the end + of the parsed data + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +LIBETPAN_EXPORT +int mailimf_ignore_field_parse(const char * message, size_t length, + size_t * indx); + +/* + mailimf_envelope_fields will parse the given fields (Date, + From, Sender, Reply-To, To, Cc, Bcc, Message-ID, In-Reply-To, + References and Subject), other fields will be added as optional + fields. + + @param message this is a string containing the header fields + @param length this is the size of the given string + @param indx this is a pointer to the start of the header fields in + the given string, (* indx) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +LIBETPAN_EXPORT +int +mailimf_envelope_and_optional_fields_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_fields ** result); + +/* + mailimf_envelope_fields will parse the given fields as optional + fields. + + @param message this is a string containing the header fields + @param length this is the size of the given string + @param indx this is a pointer to the start of the header fields in + the given string, (* indx) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int +mailimf_optional_fields_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_fields ** result); + + +/* internal use, exported for MIME */ + +LIBETPAN_EXPORT +int mailimf_fws_parse(const char * message, size_t length, size_t * indx); + +LIBETPAN_EXPORT +int mailimf_cfws_parse(const char * message, size_t length, + size_t * indx); + +LIBETPAN_EXPORT +int mailimf_char_parse(const char * message, size_t length, + size_t * indx, char token); + +LIBETPAN_EXPORT +int mailimf_unstrict_char_parse(const char * message, size_t length, + size_t * indx, char token); + +LIBETPAN_EXPORT +int mailimf_crlf_parse(const char * message, size_t length, size_t * indx); + +LIBETPAN_EXPORT +int +mailimf_custom_string_parse(const char * message, size_t length, + size_t * indx, char ** result, + int (* is_custom_char)(char)); + +LIBETPAN_EXPORT +int +mailimf_token_case_insensitive_len_parse(const char * message, size_t length, + size_t * indx, char * token, + size_t token_length); + +#define mailimf_token_case_insensitive_parse(message, length, indx, token) \ + mailimf_token_case_insensitive_len_parse(message, length, indx, token, \ + strlen(token)) + +LIBETPAN_EXPORT +int mailimf_quoted_string_parse(const char * message, size_t length, + size_t * indx, char ** result); + +LIBETPAN_EXPORT +int +mailimf_number_parse(const char * message, size_t length, + size_t * indx, uint32_t * result); + +LIBETPAN_EXPORT +int mailimf_msg_id_parse(const char * message, size_t length, + size_t * indx, + char ** result); + +LIBETPAN_EXPORT +int mailimf_msg_id_list_parse(const char * message, size_t length, + size_t * indx, clist ** result); + +LIBETPAN_EXPORT +int mailimf_word_parse(const char * message, size_t length, + size_t * indx, char ** result); + +LIBETPAN_EXPORT +int mailimf_atom_parse(const char * message, size_t length, + size_t * indx, char ** result); + +LIBETPAN_EXPORT +int mailimf_fws_atom_parse(const char * message, size_t length, + size_t * indx, char ** result); + +LIBETPAN_EXPORT +int mailimf_fws_word_parse(const char * message, size_t length, + size_t * indx, char ** result, int * p_missing_closing_quote); + +LIBETPAN_EXPORT +int mailimf_fws_quoted_string_parse(const char * message, size_t length, + size_t * indx, char ** result); + +/* exported for IMAP */ + +LIBETPAN_EXPORT +int mailimf_references_parse(const char * message, size_t length, + size_t * indx, + struct mailimf_references ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imf/mailimf_types.c b/Sources/libetpan/low-level/imf/mailimf_types.c new file mode 100644 index 00000000..c0b359fc --- /dev/null +++ b/Sources/libetpan/low-level/imf/mailimf_types.c @@ -0,0 +1,925 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf_types.c,v 1.18 2005/06/01 12:22:01 smarinier Exp $ + */ + +#include "mailimf_types.h" +#include "mmapstring.h" +#include + +LIBETPAN_EXPORT +void mailimf_atom_free(char * atom) +{ + free(atom); +} + +LIBETPAN_EXPORT +void mailimf_dot_atom_free(char * dot_atom) +{ + free(dot_atom); +} + +LIBETPAN_EXPORT +void mailimf_dot_atom_text_free(char * dot_atom) +{ + free(dot_atom); +} + +LIBETPAN_EXPORT +void mailimf_quoted_string_free(char * quoted_string) +{ + free(quoted_string); +} + +LIBETPAN_EXPORT +void mailimf_word_free(char * word) +{ + free(word); +} + +LIBETPAN_EXPORT +void mailimf_phrase_free(char * phrase) +{ + free(phrase); +} + +LIBETPAN_EXPORT +void mailimf_unstructured_free(char * unstructured) +{ + free(unstructured); +} + + +LIBETPAN_EXPORT +struct mailimf_date_time * +mailimf_date_time_new(int dt_day, int dt_month, int dt_year, + int dt_hour, int dt_min, int dt_sec, int dt_zone) +{ + struct mailimf_date_time * date_time; + + date_time = malloc(sizeof(* date_time)); + if (date_time == NULL) + return NULL; + + date_time->dt_day = dt_day; + date_time->dt_month = dt_month; + date_time->dt_year = dt_year; + date_time->dt_hour = dt_hour; + date_time->dt_min = dt_min; + date_time->dt_sec = dt_sec; + date_time->dt_zone = dt_zone; + + return date_time; +} + +LIBETPAN_EXPORT +void mailimf_date_time_free(struct mailimf_date_time * date_time) +{ + free(date_time); +} + + + +LIBETPAN_EXPORT +struct mailimf_address * +mailimf_address_new(int ad_type, struct mailimf_mailbox * ad_mailbox, + struct mailimf_group * ad_group) +{ + struct mailimf_address * address; + + address = malloc(sizeof(* address)); + if (address == NULL) + return NULL; + + address->ad_type = ad_type; + switch (ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + address->ad_data.ad_mailbox = ad_mailbox; + break; + case MAILIMF_ADDRESS_GROUP: + address->ad_data.ad_group = ad_group; + break; + } + + return address; +} + +LIBETPAN_EXPORT +void mailimf_address_free(struct mailimf_address * address) +{ + switch (address->ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + mailimf_mailbox_free(address->ad_data.ad_mailbox); + break; + case MAILIMF_ADDRESS_GROUP: + mailimf_group_free(address->ad_data.ad_group); + } + free(address); +} + +LIBETPAN_EXPORT +struct mailimf_mailbox * +mailimf_mailbox_new(char * mb_display_name, char * mb_addr_spec) +{ + struct mailimf_mailbox * mb; + + mb = malloc(sizeof(* mb)); + if (mb == NULL) + return NULL; + + mb->mb_display_name = mb_display_name; + mb->mb_addr_spec = mb_addr_spec; + + return mb; +} + +LIBETPAN_EXPORT +void mailimf_mailbox_free(struct mailimf_mailbox * mailbox) +{ + if (mailbox->mb_display_name != NULL) + mailimf_display_name_free(mailbox->mb_display_name); + mailimf_addr_spec_free(mailbox->mb_addr_spec); + free(mailbox); +} + +void mailimf_angle_addr_free(char * angle_addr) +{ + free(angle_addr); +} + +LIBETPAN_EXPORT +struct mailimf_group * +mailimf_group_new(char * grp_display_name, + struct mailimf_mailbox_list * grp_mb_list) +{ + struct mailimf_group * group; + + group = malloc(sizeof(* group)); + if (group == NULL) + return NULL; + + group->grp_display_name = grp_display_name; + group->grp_mb_list = grp_mb_list; + + return group; +} + +LIBETPAN_EXPORT +void mailimf_group_free(struct mailimf_group * group) +{ + if (group->grp_mb_list) + mailimf_mailbox_list_free(group->grp_mb_list); + mailimf_display_name_free(group->grp_display_name); + free(group); +} + +void mailimf_display_name_free(char * display_name) +{ + mailimf_phrase_free(display_name); +} + +LIBETPAN_EXPORT +struct mailimf_mailbox_list * +mailimf_mailbox_list_new(clist * mb_list) +{ + struct mailimf_mailbox_list * mbl; + + mbl = malloc(sizeof(* mbl)); + if (mbl == NULL) + return NULL; + + mbl->mb_list = mb_list; + + return mbl; +} + +LIBETPAN_EXPORT +void mailimf_mailbox_list_free(struct mailimf_mailbox_list * mb_list) +{ + clist_foreach(mb_list->mb_list, (clist_func) mailimf_mailbox_free, NULL); + clist_free(mb_list->mb_list); + free(mb_list); +} + + +LIBETPAN_EXPORT +struct mailimf_address_list * +mailimf_address_list_new(clist * ad_list) +{ + struct mailimf_address_list * addr_list; + + addr_list = malloc(sizeof(* addr_list)); + if (addr_list == NULL) + return NULL; + + addr_list->ad_list = ad_list; + + return addr_list; +} + +LIBETPAN_EXPORT +void mailimf_address_list_free(struct mailimf_address_list * addr_list) +{ + clist_foreach(addr_list->ad_list, (clist_func) mailimf_address_free, NULL); + clist_free(addr_list->ad_list); + free(addr_list); +} + + +LIBETPAN_EXPORT +void mailimf_addr_spec_free(char * addr_spec) +{ + free(addr_spec); +} + +LIBETPAN_EXPORT +void mailimf_local_part_free(char * local_part) +{ + free(local_part); +} + +LIBETPAN_EXPORT +void mailimf_domain_free(char * domain) +{ + free(domain); +} + +LIBETPAN_EXPORT +void mailimf_domain_literal_free(char * domain_literal) +{ + free(domain_literal); +} + +LIBETPAN_EXPORT +struct mailimf_message * +mailimf_message_new(struct mailimf_fields * msg_fields, + struct mailimf_body * msg_body) +{ + struct mailimf_message * message; + + message = malloc(sizeof(* message)); + if (message == NULL) + return NULL; + + message->msg_fields = msg_fields; + message->msg_body = msg_body; + + return message; +} + +LIBETPAN_EXPORT +void mailimf_message_free(struct mailimf_message * message) +{ + mailimf_body_free(message->msg_body); + mailimf_fields_free(message->msg_fields); + free(message); +} + +LIBETPAN_EXPORT +struct mailimf_body * mailimf_body_new(const char * bd_text, size_t bd_size) +{ + struct mailimf_body * body; + + body = malloc(sizeof(* body)); + if (body == NULL) + return NULL; + body->bd_text = bd_text; + body->bd_size = bd_size; + + return body; +} + +LIBETPAN_EXPORT +void mailimf_body_free(struct mailimf_body * body) +{ + free(body); +} + + +LIBETPAN_EXPORT +struct mailimf_field * +mailimf_field_new(int fld_type, + struct mailimf_return * fld_return_path, + struct mailimf_orig_date * fld_resent_date, + struct mailimf_from * fld_resent_from, + struct mailimf_sender * fld_resent_sender, + struct mailimf_to * fld_resent_to, + struct mailimf_cc * fld_resent_cc, + struct mailimf_bcc * fld_resent_bcc, + struct mailimf_message_id * fld_resent_msg_id, + struct mailimf_orig_date * fld_orig_date, + struct mailimf_from * fld_from, + struct mailimf_sender * fld_sender, + struct mailimf_reply_to * fld_reply_to, + struct mailimf_to * fld_to, + struct mailimf_cc * fld_cc, + struct mailimf_bcc * fld_bcc, + struct mailimf_message_id * fld_message_id, + struct mailimf_in_reply_to * fld_in_reply_to, + struct mailimf_references * fld_references, + struct mailimf_subject * fld_subject, + struct mailimf_comments * fld_comments, + struct mailimf_keywords * fld_keywords, + struct mailimf_optional_field * fld_optional_field) +{ + struct mailimf_field * field; + + field = malloc(sizeof(* field)); + if (field == NULL) + return NULL; + + field->fld_type = fld_type; + switch (fld_type) { + case MAILIMF_FIELD_RETURN_PATH: + field->fld_data.fld_return_path = fld_return_path; + break; + case MAILIMF_FIELD_RESENT_DATE: + field->fld_data.fld_resent_date = fld_resent_date; + break; + case MAILIMF_FIELD_RESENT_FROM: + field->fld_data.fld_resent_from = fld_resent_from; + break; + case MAILIMF_FIELD_RESENT_SENDER: + field->fld_data.fld_resent_sender = fld_resent_sender; + break; + case MAILIMF_FIELD_RESENT_TO: + field->fld_data.fld_resent_to = fld_resent_to; + break; + case MAILIMF_FIELD_RESENT_CC: + field->fld_data.fld_resent_cc = fld_resent_cc; + break; + case MAILIMF_FIELD_RESENT_BCC: + field->fld_data.fld_resent_bcc = fld_resent_bcc; + break; + case MAILIMF_FIELD_RESENT_MSG_ID: + field->fld_data.fld_resent_msg_id = fld_resent_msg_id; + break; + case MAILIMF_FIELD_ORIG_DATE: + field->fld_data.fld_orig_date = fld_orig_date; + break; + case MAILIMF_FIELD_FROM: + field->fld_data.fld_from = fld_from; + break; + case MAILIMF_FIELD_SENDER: + field->fld_data.fld_sender = fld_sender; + break; + case MAILIMF_FIELD_REPLY_TO: + field->fld_data.fld_reply_to = fld_reply_to; + break; + case MAILIMF_FIELD_TO: + field->fld_data.fld_to = fld_to; + break; + case MAILIMF_FIELD_CC: + field->fld_data.fld_cc = fld_cc; + break; + case MAILIMF_FIELD_BCC: + field->fld_data.fld_bcc = fld_bcc; + break; + case MAILIMF_FIELD_MESSAGE_ID: + field->fld_data.fld_message_id = fld_message_id; + break; + case MAILIMF_FIELD_IN_REPLY_TO: + field->fld_data.fld_in_reply_to = fld_in_reply_to; + break; + case MAILIMF_FIELD_REFERENCES: + field->fld_data.fld_references = fld_references; + break; + case MAILIMF_FIELD_SUBJECT: + field->fld_data.fld_subject = fld_subject; + break; + case MAILIMF_FIELD_COMMENTS: + field->fld_data.fld_comments = fld_comments; + break; + case MAILIMF_FIELD_KEYWORDS: + field->fld_data.fld_keywords = fld_keywords; + break; + case MAILIMF_FIELD_OPTIONAL_FIELD: + field->fld_data.fld_optional_field = fld_optional_field; + break; + } + + return field; +} + +LIBETPAN_EXPORT +void mailimf_field_free(struct mailimf_field * field) +{ + switch (field->fld_type) { + case MAILIMF_FIELD_RETURN_PATH: + mailimf_return_free(field->fld_data.fld_return_path); + break; + case MAILIMF_FIELD_RESENT_DATE: + mailimf_orig_date_free(field->fld_data.fld_resent_date); + break; + case MAILIMF_FIELD_RESENT_FROM: + mailimf_from_free(field->fld_data.fld_resent_from); + break; + case MAILIMF_FIELD_RESENT_SENDER: + mailimf_sender_free(field->fld_data.fld_resent_sender); + break; + case MAILIMF_FIELD_RESENT_TO: + mailimf_to_free(field->fld_data.fld_resent_to); + break; + case MAILIMF_FIELD_RESENT_CC: + mailimf_cc_free(field->fld_data.fld_resent_cc); + break; + case MAILIMF_FIELD_RESENT_BCC: + mailimf_bcc_free(field->fld_data.fld_resent_bcc); + break; + case MAILIMF_FIELD_RESENT_MSG_ID: + mailimf_message_id_free(field->fld_data.fld_resent_msg_id); + break; + case MAILIMF_FIELD_ORIG_DATE: + mailimf_orig_date_free(field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_FROM: + mailimf_from_free(field->fld_data.fld_from); + break; + case MAILIMF_FIELD_SENDER: + mailimf_sender_free(field->fld_data.fld_sender); + break; + case MAILIMF_FIELD_REPLY_TO: + mailimf_reply_to_free(field->fld_data.fld_reply_to); + break; + case MAILIMF_FIELD_TO: + mailimf_to_free(field->fld_data.fld_to); + break; + case MAILIMF_FIELD_CC: + mailimf_cc_free(field->fld_data.fld_cc); + break; + case MAILIMF_FIELD_BCC: + mailimf_bcc_free(field->fld_data.fld_bcc); + break; + case MAILIMF_FIELD_MESSAGE_ID: + mailimf_message_id_free(field->fld_data.fld_message_id); + break; + case MAILIMF_FIELD_IN_REPLY_TO: + mailimf_in_reply_to_free(field->fld_data.fld_in_reply_to); + break; + case MAILIMF_FIELD_REFERENCES: + mailimf_references_free(field->fld_data.fld_references); + break; + case MAILIMF_FIELD_SUBJECT: + mailimf_subject_free(field->fld_data.fld_subject); + break; + case MAILIMF_FIELD_COMMENTS: + mailimf_comments_free(field->fld_data.fld_comments); + break; + case MAILIMF_FIELD_KEYWORDS: + mailimf_keywords_free(field->fld_data.fld_keywords); + break; + case MAILIMF_FIELD_OPTIONAL_FIELD: + mailimf_optional_field_free(field->fld_data.fld_optional_field); + break; + } + + free(field); +} + +LIBETPAN_EXPORT +struct mailimf_fields * mailimf_fields_new(clist * fld_list) +{ + struct mailimf_fields * fields; + + fields = malloc(sizeof(* fields)); + if (fields == NULL) + return NULL; + + fields->fld_list = fld_list; + + return fields; +} + +LIBETPAN_EXPORT +void mailimf_fields_free(struct mailimf_fields * fields) +{ + if (fields->fld_list != NULL) { + clist_foreach(fields->fld_list, (clist_func) mailimf_field_free, NULL); + clist_free(fields->fld_list); + } + free(fields); +} + +LIBETPAN_EXPORT +struct mailimf_orig_date * mailimf_orig_date_new(struct mailimf_date_time * + dt_date_time) +{ + struct mailimf_orig_date * orig_date; + + orig_date = malloc(sizeof(* orig_date)); + if (orig_date == NULL) + return NULL; + + orig_date->dt_date_time = dt_date_time; + + return orig_date; +} + +LIBETPAN_EXPORT +void mailimf_orig_date_free(struct mailimf_orig_date * orig_date) +{ + if (orig_date->dt_date_time != NULL) + mailimf_date_time_free(orig_date->dt_date_time); + free(orig_date); +} + +LIBETPAN_EXPORT +struct mailimf_from * +mailimf_from_new(struct mailimf_mailbox_list * frm_mb_list) +{ + struct mailimf_from * from; + + from = malloc(sizeof(* from)); + if (from == NULL) + return NULL; + + from->frm_mb_list = frm_mb_list; + + return from; +} + +LIBETPAN_EXPORT +void mailimf_from_free(struct mailimf_from * from) +{ + if (from->frm_mb_list != NULL) + mailimf_mailbox_list_free(from->frm_mb_list); + free(from); +} + +LIBETPAN_EXPORT +struct mailimf_sender * mailimf_sender_new(struct mailimf_mailbox * snd_mb) +{ + struct mailimf_sender * sender; + + sender = malloc(sizeof(* sender)); + if (sender == NULL) + return NULL; + + sender->snd_mb = snd_mb; + + return sender; +} + +LIBETPAN_EXPORT +void mailimf_sender_free(struct mailimf_sender * sender) +{ + if (sender->snd_mb != NULL) + mailimf_mailbox_free(sender->snd_mb); + free(sender); +} + +LIBETPAN_EXPORT +struct mailimf_reply_to * +mailimf_reply_to_new(struct mailimf_address_list * rt_addr_list) +{ + struct mailimf_reply_to * reply_to; + + reply_to = malloc(sizeof(* reply_to)); + if (reply_to == NULL) + return NULL; + + reply_to->rt_addr_list = rt_addr_list; + + return reply_to; +} + +LIBETPAN_EXPORT +void mailimf_reply_to_free(struct mailimf_reply_to * reply_to) +{ + if (reply_to->rt_addr_list != NULL) + mailimf_address_list_free(reply_to->rt_addr_list); + free(reply_to); +} + +LIBETPAN_EXPORT +struct mailimf_to * mailimf_to_new(struct mailimf_address_list * to_addr_list) +{ + struct mailimf_to * to; + + to = malloc(sizeof(* to)); + if (to == NULL) + return NULL; + + to->to_addr_list = to_addr_list; + + return to; +} + +LIBETPAN_EXPORT +void mailimf_to_free(struct mailimf_to * to) +{ + if (to->to_addr_list != NULL) + mailimf_address_list_free(to->to_addr_list); + free(to); +} + +LIBETPAN_EXPORT +struct mailimf_cc * mailimf_cc_new(struct mailimf_address_list * cc_addr_list) +{ + struct mailimf_cc * cc; + + cc = malloc(sizeof(* cc)); + if (cc == NULL) + return NULL; + + cc->cc_addr_list = cc_addr_list; + + return cc; +} + +LIBETPAN_EXPORT +void mailimf_cc_free(struct mailimf_cc * cc) +{ + if (cc->cc_addr_list != NULL) + mailimf_address_list_free(cc->cc_addr_list); + free(cc); +} + +LIBETPAN_EXPORT +struct mailimf_bcc * +mailimf_bcc_new(struct mailimf_address_list * bcc_addr_list) +{ + struct mailimf_bcc * bcc; + + bcc = malloc(sizeof(* bcc)); + if (bcc == NULL) + return NULL; + + bcc->bcc_addr_list = bcc_addr_list; + + return bcc; +} + +LIBETPAN_EXPORT +void mailimf_bcc_free(struct mailimf_bcc * bcc) +{ + if (bcc->bcc_addr_list != NULL) + mailimf_address_list_free(bcc->bcc_addr_list); + free(bcc); +} + +LIBETPAN_EXPORT +struct mailimf_message_id * mailimf_message_id_new(char * mid_value) +{ + struct mailimf_message_id * message_id; + + message_id = malloc(sizeof(* message_id)); + if (message_id == NULL) + return NULL; + + message_id->mid_value = mid_value; + + return message_id; +} + +LIBETPAN_EXPORT +void mailimf_message_id_free(struct mailimf_message_id * message_id) +{ + if (message_id->mid_value != NULL) + mailimf_msg_id_free(message_id->mid_value); + free(message_id); +} + +LIBETPAN_EXPORT +struct mailimf_in_reply_to * mailimf_in_reply_to_new(clist * mid_list) +{ + struct mailimf_in_reply_to * in_reply_to; + + in_reply_to = malloc(sizeof(* in_reply_to)); + if (in_reply_to == NULL) + return NULL; + + in_reply_to->mid_list = mid_list; + + return in_reply_to; +} + +LIBETPAN_EXPORT +void mailimf_in_reply_to_free(struct mailimf_in_reply_to * in_reply_to) +{ + clist_foreach(in_reply_to->mid_list, + (clist_func) mailimf_msg_id_free, NULL); + clist_free(in_reply_to->mid_list); + free(in_reply_to); +} + +LIBETPAN_EXPORT +struct mailimf_references * mailimf_references_new(clist * mid_list) +{ + struct mailimf_references * ref; + + ref = malloc(sizeof(* ref)); + if (ref == NULL) + return NULL; + + ref->mid_list = mid_list; + + return ref; +} + +LIBETPAN_EXPORT +void mailimf_references_free(struct mailimf_references * references) +{ + clist_foreach(references->mid_list, + (clist_func) mailimf_msg_id_free, NULL); + clist_free(references->mid_list); + free(references); +} + +LIBETPAN_EXPORT +void mailimf_msg_id_free(char * msg_id) +{ + free(msg_id); +} + +LIBETPAN_EXPORT +void mailimf_id_left_free(char * id_left) +{ + free(id_left); +} + +LIBETPAN_EXPORT +void mailimf_id_right_free(char * id_right) +{ + free(id_right); +} + +LIBETPAN_EXPORT +void mailimf_no_fold_quote_free(char * nfq) +{ + free(nfq); +} + +LIBETPAN_EXPORT +void mailimf_no_fold_literal_free(char * nfl) +{ + free(nfl); +} + +LIBETPAN_EXPORT +struct mailimf_subject * mailimf_subject_new(char * sbj_value) +{ + struct mailimf_subject * subject; + + subject = malloc(sizeof(* subject)); + if (subject == NULL) + return NULL; + + subject->sbj_value = sbj_value; + + return subject; +} + +LIBETPAN_EXPORT +void mailimf_subject_free(struct mailimf_subject * subject) +{ + mailimf_unstructured_free(subject->sbj_value); + free(subject); +} + +LIBETPAN_EXPORT +struct mailimf_comments * mailimf_comments_new(char * cm_value) +{ + struct mailimf_comments * comments; + + comments = malloc(sizeof(* comments)); + if (comments == NULL) + return NULL; + + comments->cm_value = cm_value; + + return comments; +} + +LIBETPAN_EXPORT +void mailimf_comments_free(struct mailimf_comments * comments) +{ + mailimf_unstructured_free(comments->cm_value); + free(comments); +} + +LIBETPAN_EXPORT +struct mailimf_keywords * mailimf_keywords_new(clist * kw_list) +{ + struct mailimf_keywords * keywords; + + keywords = malloc(sizeof(* keywords)); + if (keywords == NULL) + return NULL; + + keywords->kw_list = kw_list; + + return keywords; +} + +LIBETPAN_EXPORT +void mailimf_keywords_free(struct mailimf_keywords * keywords) +{ + clist_foreach(keywords->kw_list, (clist_func) mailimf_phrase_free, NULL); + clist_free(keywords->kw_list); + free(keywords); +} + +LIBETPAN_EXPORT +struct mailimf_return * +mailimf_return_new(struct mailimf_path * ret_path) +{ + struct mailimf_return * return_path; + + return_path = malloc(sizeof(* return_path)); + if (return_path == NULL) + return NULL; + + return_path->ret_path = ret_path; + + return return_path; +} + +LIBETPAN_EXPORT +void mailimf_return_free(struct mailimf_return * return_path) +{ + mailimf_path_free(return_path->ret_path); + free(return_path); +} + +LIBETPAN_EXPORT +struct mailimf_path * mailimf_path_new(char * pt_addr_spec) +{ + struct mailimf_path * path; + + path = malloc(sizeof(* path)); + if (path == NULL) + return NULL; + + path->pt_addr_spec = pt_addr_spec; + + return path; +} + +LIBETPAN_EXPORT +void mailimf_path_free(struct mailimf_path * path) +{ + if (path->pt_addr_spec != NULL) + mailimf_addr_spec_free(path->pt_addr_spec); + free(path); +} + +LIBETPAN_EXPORT +struct mailimf_optional_field * +mailimf_optional_field_new(char * fld_name, char * fld_value) +{ + struct mailimf_optional_field * opt_field; + + opt_field = malloc(sizeof(* opt_field)); + if (opt_field == NULL) + return NULL; + + opt_field->fld_name = fld_name; + opt_field->fld_value = fld_value; + + return opt_field; +} + +LIBETPAN_EXPORT +void mailimf_optional_field_free(struct mailimf_optional_field * opt_field) +{ + mailimf_field_name_free(opt_field->fld_name); + mailimf_unstructured_free(opt_field->fld_value); + free(opt_field); +} + +LIBETPAN_EXPORT +void mailimf_field_name_free(char * field_name) +{ + free(field_name); +} diff --git a/Sources/libetpan/low-level/imf/mailimf_types.h b/Sources/libetpan/low-level/imf/mailimf_types.h new file mode 100644 index 00000000..a9978acb --- /dev/null +++ b/Sources/libetpan/low-level/imf/mailimf_types.h @@ -0,0 +1,864 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +/* + * $Id: mailimf_types.h,v 1.34 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifndef MAILIMF_TYPES_H + +#define MAILIMF_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +/* + IMPORTANT NOTE: + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + allocation functions will return NULL on failure +*/ + +/* + mailimf_date_time is a date + + - day is the day of month (1 to 31) + + - month (1 to 12) + + - year (4 digits) + + - hour (0 to 23) + + - min (0 to 59) + + - sec (0 to 59) + + - zone (this is the decimal value that we can read, for example: + for "-0200", the value is -200) +*/ + +struct mailimf_date_time { + int dt_day; + int dt_month; + int dt_year; + int dt_hour; + int dt_min; + int dt_sec; + int dt_zone; +}; + +LIBETPAN_EXPORT +struct mailimf_date_time * +mailimf_date_time_new(int dt_day, int dt_month, int dt_year, + int dt_hour, int dt_min, int dt_sec, int dt_zone); + +LIBETPAN_EXPORT +void mailimf_date_time_free(struct mailimf_date_time * date_time); + + + +/* this is the type of address */ + +enum { + MAILIMF_ADDRESS_ERROR, /* on parse error */ + MAILIMF_ADDRESS_MAILBOX, /* if this is a mailbox (mailbox@domain) */ + MAILIMF_ADDRESS_GROUP /* if this is a group + (group_name: address1@domain1, + address2@domain2; ) */ +}; + +/* + mailimf_address is an address + + - type can be MAILIMF_ADDRESS_MAILBOX or MAILIMF_ADDRESS_GROUP + + - mailbox is a mailbox if type is MAILIMF_ADDRESS_MAILBOX + + - group is a group if type is MAILIMF_ADDRESS_GROUP +*/ + +struct mailimf_address { + int ad_type; + union { + struct mailimf_mailbox * ad_mailbox; /* can be NULL */ + struct mailimf_group * ad_group; /* can be NULL */ + } ad_data; +}; + +LIBETPAN_EXPORT +struct mailimf_address * +mailimf_address_new(int ad_type, struct mailimf_mailbox * ad_mailbox, + struct mailimf_group * ad_group); + +LIBETPAN_EXPORT +void mailimf_address_free(struct mailimf_address * address); + + + +/* + mailimf_mailbox is a mailbox + + - display_name is the name that will be displayed for this mailbox, + for example 'name' in '"name" , + should be allocated with malloc() + + - addr_spec is the mailbox, for example 'mailbox@domain' + in '"name" , should be allocated with malloc() +*/ + +struct mailimf_mailbox { + char * mb_display_name; /* can be NULL */ + char * mb_addr_spec; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_mailbox * +mailimf_mailbox_new(char * mb_display_name, char * mb_addr_spec); + +LIBETPAN_EXPORT +void mailimf_mailbox_free(struct mailimf_mailbox * mailbox); + + + +/* + mailimf_group is a group + + - display_name is the name that will be displayed for this group, + for example 'group_name' in + 'group_name: address1@domain1, address2@domain2;', should be allocated + with malloc() + + - mb_list is a list of mailboxes +*/ + +struct mailimf_group { + char * grp_display_name; /* != NULL */ + struct mailimf_mailbox_list * grp_mb_list; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_group * +mailimf_group_new(char * grp_display_name, + struct mailimf_mailbox_list * grp_mb_list); + +LIBETPAN_EXPORT +void mailimf_group_free(struct mailimf_group * group); + + + +/* + mailimf_mailbox_list is a list of mailboxes + + - list is a list of mailboxes +*/ + +struct mailimf_mailbox_list { + clist * mb_list; /* list of (struct mailimf_mailbox *), != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_mailbox_list * +mailimf_mailbox_list_new(clist * mb_list); + +LIBETPAN_EXPORT +void mailimf_mailbox_list_free(struct mailimf_mailbox_list * mb_list); + + + +/* + mailimf_address_list is a list of addresses + + - list is a list of addresses +*/ + +struct mailimf_address_list { + clist * ad_list; /* list of (struct mailimf_address *), != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_address_list * +mailimf_address_list_new(clist * ad_list); + +LIBETPAN_EXPORT +void mailimf_address_list_free(struct mailimf_address_list * addr_list); + + + + + +/* + mailimf_body is the text part of a message + + - text is the beginning of the text part, it is a substring + of an other string + + - size is the size of the text part +*/ + +struct mailimf_body { + const char * bd_text; /* != NULL */ + size_t bd_size; +}; + +LIBETPAN_EXPORT +struct mailimf_body * mailimf_body_new(const char * bd_text, size_t bd_size); + +LIBETPAN_EXPORT +void mailimf_body_free(struct mailimf_body * body); + + + + +/* + mailimf_message is the content of the message + + - msg_fields is the header fields of the message + + - msg_body is the text part of the message +*/ + +struct mailimf_message { + struct mailimf_fields * msg_fields; /* != NULL */ + struct mailimf_body * msg_body; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_message * +mailimf_message_new(struct mailimf_fields * msg_fields, + struct mailimf_body * msg_body); + +LIBETPAN_EXPORT +void mailimf_message_free(struct mailimf_message * message); + + + + +/* + mailimf_fields is a list of header fields + + - fld_list is a list of header fields +*/ + +struct mailimf_fields { + clist * fld_list; /* list of (struct mailimf_field *), != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_fields * mailimf_fields_new(clist * fld_list); + +LIBETPAN_EXPORT +void mailimf_fields_free(struct mailimf_fields * fields); + + + +/* this is a type of field */ + +enum { + MAILIMF_FIELD_NONE, /* on parse error */ + MAILIMF_FIELD_RETURN_PATH, /* Return-Path */ + MAILIMF_FIELD_RESENT_DATE, /* Resent-Date */ + MAILIMF_FIELD_RESENT_FROM, /* Resent-From */ + MAILIMF_FIELD_RESENT_SENDER, /* Resent-Sender */ + MAILIMF_FIELD_RESENT_TO, /* Resent-To */ + MAILIMF_FIELD_RESENT_CC, /* Resent-Cc */ + MAILIMF_FIELD_RESENT_BCC, /* Resent-Bcc */ + MAILIMF_FIELD_RESENT_MSG_ID, /* Resent-Message-ID */ + MAILIMF_FIELD_ORIG_DATE, /* Date */ + MAILIMF_FIELD_FROM, /* From */ + MAILIMF_FIELD_SENDER, /* Sender */ + MAILIMF_FIELD_REPLY_TO, /* Reply-To */ + MAILIMF_FIELD_TO, /* To */ + MAILIMF_FIELD_CC, /* Cc */ + MAILIMF_FIELD_BCC, /* Bcc */ + MAILIMF_FIELD_MESSAGE_ID, /* Message-ID */ + MAILIMF_FIELD_IN_REPLY_TO, /* In-Reply-To */ + MAILIMF_FIELD_REFERENCES, /* References */ + MAILIMF_FIELD_SUBJECT, /* Subject */ + MAILIMF_FIELD_COMMENTS, /* Comments */ + MAILIMF_FIELD_KEYWORDS, /* Keywords */ + MAILIMF_FIELD_OPTIONAL_FIELD /* other field */ +}; + +/* + mailimf_field is a field + + - fld_type is the type of the field + + - fld_data.fld_return_path is the parsed content of the Return-Path + field if type is MAILIMF_FIELD_RETURN_PATH + + - fld_data.fld_resent_date is the parsed content of the Resent-Date field + if type is MAILIMF_FIELD_RESENT_DATE + + - fld_data.fld_resent_from is the parsed content of the Resent-From field + + - fld_data.fld_resent_sender is the parsed content of the Resent-Sender field + + - fld_data.fld_resent_to is the parsed content of the Resent-To field + + - fld_data.fld_resent_cc is the parsed content of the Resent-Cc field + + - fld_data.fld_resent_bcc is the parsed content of the Resent-Bcc field + + - fld_data.fld_resent_msg_id is the parsed content of the Resent-Message-ID + field + + - fld_data.fld_orig_date is the parsed content of the Date field + + - fld_data.fld_from is the parsed content of the From field + + - fld_data.fld_sender is the parsed content of the Sender field + + - fld_data.fld_reply_to is the parsed content of the Reply-To field + + - fld_data.fld_to is the parsed content of the To field + + - fld_data.fld_cc is the parsed content of the Cc field + + - fld_data.fld_bcc is the parsed content of the Bcc field + + - fld_data.fld_message_id is the parsed content of the Message-ID field + + - fld_data.fld_in_reply_to is the parsed content of the In-Reply-To field + + - fld_data.fld_references is the parsed content of the References field + + - fld_data.fld_subject is the content of the Subject field + + - fld_data.fld_comments is the content of the Comments field + + - fld_data.fld_keywords is the parsed content of the Keywords field + + - fld_data.fld_optional_field is an other field and is not parsed +*/ + +#define LIBETPAN_MAILIMF_FIELD_UNION + +struct mailimf_field { + int fld_type; + union { + struct mailimf_return * fld_return_path; /* can be NULL */ + struct mailimf_orig_date * fld_resent_date; /* can be NULL */ + struct mailimf_from * fld_resent_from; /* can be NULL */ + struct mailimf_sender * fld_resent_sender; /* can be NULL */ + struct mailimf_to * fld_resent_to; /* can be NULL */ + struct mailimf_cc * fld_resent_cc; /* can be NULL */ + struct mailimf_bcc * fld_resent_bcc; /* can be NULL */ + struct mailimf_message_id * fld_resent_msg_id; /* can be NULL */ + struct mailimf_orig_date * fld_orig_date; /* can be NULL */ + struct mailimf_from * fld_from; /* can be NULL */ + struct mailimf_sender * fld_sender; /* can be NULL */ + struct mailimf_reply_to * fld_reply_to; /* can be NULL */ + struct mailimf_to * fld_to; /* can be NULL */ + struct mailimf_cc * fld_cc; /* can be NULL */ + struct mailimf_bcc * fld_bcc; /* can be NULL */ + struct mailimf_message_id * fld_message_id; /* can be NULL */ + struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */ + struct mailimf_references * fld_references; /* can be NULL */ + struct mailimf_subject * fld_subject; /* can be NULL */ + struct mailimf_comments * fld_comments; /* can be NULL */ + struct mailimf_keywords * fld_keywords; /* can be NULL */ + struct mailimf_optional_field * fld_optional_field; /* can be NULL */ + } fld_data; +}; + +LIBETPAN_EXPORT +struct mailimf_field * +mailimf_field_new(int fld_type, + struct mailimf_return * fld_return_path, + struct mailimf_orig_date * fld_resent_date, + struct mailimf_from * fld_resent_from, + struct mailimf_sender * fld_resent_sender, + struct mailimf_to * fld_resent_to, + struct mailimf_cc * fld_resent_cc, + struct mailimf_bcc * fld_resent_bcc, + struct mailimf_message_id * fld_resent_msg_id, + struct mailimf_orig_date * fld_orig_date, + struct mailimf_from * fld_from, + struct mailimf_sender * fld_sender, + struct mailimf_reply_to * fld_reply_to, + struct mailimf_to * fld_to, + struct mailimf_cc * fld_cc, + struct mailimf_bcc * fld_bcc, + struct mailimf_message_id * fld_message_id, + struct mailimf_in_reply_to * fld_in_reply_to, + struct mailimf_references * fld_references, + struct mailimf_subject * fld_subject, + struct mailimf_comments * fld_comments, + struct mailimf_keywords * fld_keywords, + struct mailimf_optional_field * fld_optional_field); + +LIBETPAN_EXPORT +void mailimf_field_free(struct mailimf_field * field); + + + +/* + mailimf_orig_date is the parsed Date field + + - date_time is the parsed date +*/ + +struct mailimf_orig_date { + struct mailimf_date_time * dt_date_time; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_orig_date * mailimf_orig_date_new(struct mailimf_date_time * + dt_date_time); + +LIBETPAN_EXPORT +void mailimf_orig_date_free(struct mailimf_orig_date * orig_date); + + + + +/* + mailimf_from is the parsed From field + + - mb_list is the parsed mailbox list +*/ + +struct mailimf_from { + struct mailimf_mailbox_list * frm_mb_list; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_from * +mailimf_from_new(struct mailimf_mailbox_list * frm_mb_list); + +LIBETPAN_EXPORT +void mailimf_from_free(struct mailimf_from * from); + + + +/* + mailimf_sender is the parsed Sender field + + - snd_mb is the parsed mailbox +*/ + +struct mailimf_sender { + struct mailimf_mailbox * snd_mb; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_sender * mailimf_sender_new(struct mailimf_mailbox * snd_mb); + +LIBETPAN_EXPORT +void mailimf_sender_free(struct mailimf_sender * sender); + + + + +/* + mailimf_reply_to is the parsed Reply-To field + + - rt_addr_list is the parsed address list + */ + +struct mailimf_reply_to { + struct mailimf_address_list * rt_addr_list; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_reply_to * +mailimf_reply_to_new(struct mailimf_address_list * rt_addr_list); + +LIBETPAN_EXPORT +void mailimf_reply_to_free(struct mailimf_reply_to * reply_to); + + + + +/* + mailimf_to is the parsed To field + + - to_addr_list is the parsed address list +*/ + +struct mailimf_to { + struct mailimf_address_list * to_addr_list; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_to * mailimf_to_new(struct mailimf_address_list * to_addr_list); + +LIBETPAN_EXPORT +void mailimf_to_free(struct mailimf_to * to); + + + + +/* + mailimf_cc is the parsed Cc field + + - cc_addr_list is the parsed addres list +*/ + +struct mailimf_cc { + struct mailimf_address_list * cc_addr_list; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_cc * mailimf_cc_new(struct mailimf_address_list * cc_addr_list); + +LIBETPAN_EXPORT +void mailimf_cc_free(struct mailimf_cc * cc); + + + + +/* + mailimf_bcc is the parsed Bcc field + + - bcc_addr_list is the parsed addres list +*/ + +struct mailimf_bcc { + struct mailimf_address_list * bcc_addr_list; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_bcc * +mailimf_bcc_new(struct mailimf_address_list * bcc_addr_list); + +LIBETPAN_EXPORT +void mailimf_bcc_free(struct mailimf_bcc * bcc); + + + +/* + mailimf_message_id is the parsed Message-ID field + + - mid_value is the message identifier +*/ + +struct mailimf_message_id { + char * mid_value; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_message_id * mailimf_message_id_new(char * mid_value); + +LIBETPAN_EXPORT +void mailimf_message_id_free(struct mailimf_message_id * message_id); + + + + +/* + mailimf_in_reply_to is the parsed In-Reply-To field + + - mid_list is the list of message identifers +*/ + +struct mailimf_in_reply_to { + clist * mid_list; /* list of (char *), != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_in_reply_to * mailimf_in_reply_to_new(clist * mid_list); + +LIBETPAN_EXPORT +void mailimf_in_reply_to_free(struct mailimf_in_reply_to * in_reply_to); + + + +/* + mailimf_references is the parsed References field + + - msg_id_list is the list of message identifiers + */ + +struct mailimf_references { + clist * mid_list; /* list of (char *) */ + /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_references * mailimf_references_new(clist * mid_list); + +LIBETPAN_EXPORT +void mailimf_references_free(struct mailimf_references * references); + + + +/* + mailimf_subject is the parsed Subject field + + - sbj_value is the value of the field +*/ + +struct mailimf_subject { + char * sbj_value; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_subject * mailimf_subject_new(char * sbj_value); + +LIBETPAN_EXPORT +void mailimf_subject_free(struct mailimf_subject * subject); + + +/* + mailimf_comments is the parsed Comments field + + - cm_value is the value of the field +*/ + +struct mailimf_comments { + char * cm_value; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_comments * mailimf_comments_new(char * cm_value); + +LIBETPAN_EXPORT +void mailimf_comments_free(struct mailimf_comments * comments); + + +/* + mailimf_keywords is the parsed Keywords field + + - kw_list is the list of keywords +*/ + +struct mailimf_keywords { + clist * kw_list; /* list of (char *), != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_keywords * mailimf_keywords_new(clist * kw_list); + +LIBETPAN_EXPORT +void mailimf_keywords_free(struct mailimf_keywords * keywords); + + +/* + mailimf_return is the parsed Return-Path field + + - ret_path is the parsed value of Return-Path +*/ + +struct mailimf_return { + struct mailimf_path * ret_path; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_return * +mailimf_return_new(struct mailimf_path * ret_path); + +LIBETPAN_EXPORT +void mailimf_return_free(struct mailimf_return * return_path); + + +/* + mailimf_path is the parsed value of Return-Path + + - pt_addr_spec is a mailbox +*/ + +struct mailimf_path { + char * pt_addr_spec; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_path * mailimf_path_new(char * pt_addr_spec); + +LIBETPAN_EXPORT +void mailimf_path_free(struct mailimf_path * path); + + +/* + mailimf_optional_field is a non-parsed field + + - fld_name is the name of the field + + - fld_value is the value of the field +*/ + +struct mailimf_optional_field { + char * fld_name; /* != NULL */ + char * fld_value; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_optional_field * +mailimf_optional_field_new(char * fld_name, char * fld_value); + +LIBETPAN_EXPORT +void mailimf_optional_field_free(struct mailimf_optional_field * opt_field); + + +/* + mailimf_fields is the native structure that IMF module will use, + this module will provide an easier structure to use when parsing fields. + + mailimf_single_fields is an easier structure to get parsed fields, + rather than iteration over the list of fields + + - fld_orig_date is the parsed "Date" field + + - fld_from is the parsed "From" field + + - fld_sender is the parsed "Sender "field + + - fld_reply_to is the parsed "Reply-To" field + + - fld_to is the parsed "To" field + + - fld_cc is the parsed "Cc" field + + - fld_bcc is the parsed "Bcc" field + + - fld_message_id is the parsed "Message-ID" field + + - fld_in_reply_to is the parsed "In-Reply-To" field + + - fld_references is the parsed "References" field + + - fld_subject is the parsed "Subject" field + + - fld_comments is the parsed "Comments" field + + - fld_keywords is the parsed "Keywords" field +*/ + +struct mailimf_single_fields { + struct mailimf_orig_date * fld_orig_date; /* can be NULL */ + struct mailimf_from * fld_from; /* can be NULL */ + struct mailimf_sender * fld_sender; /* can be NULL */ + struct mailimf_reply_to * fld_reply_to; /* can be NULL */ + struct mailimf_to * fld_to; /* can be NULL */ + struct mailimf_cc * fld_cc; /* can be NULL */ + struct mailimf_bcc * fld_bcc; /* can be NULL */ + struct mailimf_message_id * fld_message_id; /* can be NULL */ + struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */ + struct mailimf_references * fld_references; /* can be NULL */ + struct mailimf_subject * fld_subject; /* can be NULL */ + struct mailimf_comments * fld_comments; /* can be NULL */ + struct mailimf_keywords * fld_keywords; /* can be NULL */ +}; + + + + + + +/* internal use */ + +LIBETPAN_EXPORT +void mailimf_atom_free(char * atom); + +LIBETPAN_EXPORT +void mailimf_dot_atom_free(char * dot_atom); + +LIBETPAN_EXPORT +void mailimf_dot_atom_text_free(char * dot_atom); + +LIBETPAN_EXPORT +void mailimf_quoted_string_free(char * quoted_string); + +LIBETPAN_EXPORT +void mailimf_word_free(char * word); + +LIBETPAN_EXPORT +void mailimf_phrase_free(char * phrase); + +LIBETPAN_EXPORT +void mailimf_unstructured_free(char * unstructured); + +LIBETPAN_EXPORT +void mailimf_angle_addr_free(char * angle_addr); + +LIBETPAN_EXPORT +void mailimf_display_name_free(char * display_name); + +LIBETPAN_EXPORT +void mailimf_addr_spec_free(char * addr_spec); + +LIBETPAN_EXPORT +void mailimf_local_part_free(char * local_part); + +LIBETPAN_EXPORT +void mailimf_domain_free(char * domain); + +LIBETPAN_EXPORT +void mailimf_domain_literal_free(char * domain); + +LIBETPAN_EXPORT +void mailimf_msg_id_free(char * msg_id); + +LIBETPAN_EXPORT +void mailimf_id_left_free(char * id_left); + +LIBETPAN_EXPORT +void mailimf_id_right_free(char * id_right); + +LIBETPAN_EXPORT +void mailimf_no_fold_quote_free(char * nfq); + +LIBETPAN_EXPORT +void mailimf_no_fold_literal_free(char * nfl); + +LIBETPAN_EXPORT +void mailimf_field_name_free(char * field_name); + + + +/* these are the possible returned error codes */ + +enum { + MAILIMF_NO_ERROR = 0, + MAILIMF_ERROR_PARSE, + MAILIMF_ERROR_MEMORY, + MAILIMF_ERROR_INVAL, + MAILIMF_ERROR_FILE +}; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imf/mailimf_types_helper.c b/Sources/libetpan/low-level/imf/mailimf_types_helper.c new file mode 100644 index 00000000..a7e01c98 --- /dev/null +++ b/Sources/libetpan/low-level/imf/mailimf_types_helper.c @@ -0,0 +1,1503 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#define HAVE_CONFIG_H 1 + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailimf_types_helper.h" + +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef WIN32 +# include "win_etpan.h" +#endif + +#include "mailimf.h" +#include "timeutils.h" + +struct mailimf_mailbox_list * +mailimf_mailbox_list_new_empty(void) +{ + clist * list; + struct mailimf_mailbox_list * mb_list; + + list = clist_new(); + if (list == NULL) + return NULL; + + mb_list = mailimf_mailbox_list_new(list); + if (mb_list == NULL) + return NULL; + + return mb_list; +} + +int mailimf_mailbox_list_add(struct mailimf_mailbox_list * mailbox_list, + struct mailimf_mailbox * mb) +{ + int r; + + r = clist_append(mailbox_list->mb_list, mb); + if (r < 0) + return MAILIMF_ERROR_MEMORY; + + return MAILIMF_NO_ERROR; +} + +int mailimf_mailbox_list_add_parse(struct mailimf_mailbox_list * mailbox_list, + char * mb_str) +{ + int r; + size_t cur_token; + struct mailimf_mailbox * mb; + int res; + + cur_token = 0; + r = mailimf_mailbox_parse(mb_str, strlen(mb_str), &cur_token, &mb); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_mailbox_list_add(mailbox_list, mb); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + + return MAILIMF_NO_ERROR; + + free: + mailimf_mailbox_free(mb); + err: + return res; +} + +int mailimf_mailbox_list_add_mb(struct mailimf_mailbox_list * mailbox_list, + char * display_name, char * address) +{ + int r; + struct mailimf_mailbox * mb; + int res; + + mb = mailimf_mailbox_new(display_name, address); + if (mb == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + r = mailimf_mailbox_list_add(mailbox_list, mb); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + + return MAILIMF_NO_ERROR; + + free: + mailimf_mailbox_free(mb); + err: + return res; +} + + + +struct mailimf_address_list * +mailimf_address_list_new_empty(void) +{ + clist * list; + struct mailimf_address_list * addr_list; + + list = clist_new(); + if (list == NULL) + return NULL; + + addr_list = mailimf_address_list_new(list); + if (addr_list == NULL) + return NULL; + + return addr_list; +} + +int mailimf_address_list_add(struct mailimf_address_list * address_list, + struct mailimf_address * addr) +{ + int r; + + r = clist_append(address_list->ad_list, addr); + if (r < 0) + return MAILIMF_ERROR_MEMORY; + + return MAILIMF_NO_ERROR; +} + +int mailimf_address_list_add_parse(struct mailimf_address_list * address_list, + char * addr_str) +{ + int r; + size_t cur_token; + struct mailimf_address * addr; + int res; + + cur_token = 0; + r = mailimf_address_parse(addr_str, strlen(addr_str), &cur_token, &addr); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_add(address_list, addr); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + + return MAILIMF_NO_ERROR; + + free: + mailimf_address_free(addr); + err: + return res; +} + +int mailimf_address_list_add_mb(struct mailimf_address_list * address_list, + char * display_name, char * address) +{ + int r; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + int res; + + mb = mailimf_mailbox_new(display_name, address); + if (mb == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + if (addr == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_mb; + } + + r = mailimf_address_list_add(address_list, addr); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr; + } + + return MAILIMF_NO_ERROR; + + free_addr: + mailimf_address_free(addr); + free_mb: + mailimf_mailbox_free(mb); + err: + return res; +} + + +#if 0 +struct mailimf_resent_fields_list * +mailimf_resent_fields_list_new_empty(void) +{ + clist * list; + struct mailimf_resent_fields_list * rf_list; + + list = clist_new(); + if (list == NULL) + return NULL; + + rf_list = mailimf_resent_fields_list_new(list); + if (rf_list == NULL) + return NULL; + + return rf_list; +} + +int mailimf_resent_fields_add(struct mailimf_resent_fields_list * fields, + struct mailimf_resent_field * field) +{ + int r; + + r = clist_append(fields->list, field); + if (r < 0) + return MAILIMF_ERROR_MEMORY; + + return MAILIMF_NO_ERROR; +} +#endif + + +static void detach_free_common_fields(struct mailimf_orig_date * imf_date, + struct mailimf_from * imf_from, + struct mailimf_sender * imf_sender, + struct mailimf_to * imf_to, + struct mailimf_cc * imf_cc, + struct mailimf_bcc * imf_bcc, + struct mailimf_message_id * imf_msg_id) +{ + if (imf_date != NULL) { + imf_date->dt_date_time = NULL; + mailimf_orig_date_free(imf_date); + } + if (imf_from != NULL) { + imf_from->frm_mb_list = NULL; + mailimf_from_free(imf_from); + } + if (imf_sender != NULL) { + imf_sender->snd_mb = NULL; + mailimf_sender_free(imf_sender); + } + if (imf_to != NULL) { + imf_to->to_addr_list = NULL; + mailimf_to_free(imf_to); + } + if (imf_cc != NULL) { + imf_cc->cc_addr_list = NULL; + mailimf_cc_free(imf_cc); + } + if (imf_bcc != NULL) { + imf_bcc->bcc_addr_list = NULL; + mailimf_bcc_free(imf_bcc); + } + if (imf_msg_id != NULL) { + imf_msg_id->mid_value = NULL; + mailimf_message_id_free(imf_msg_id); + } +} + +static void detach_resent_field(struct mailimf_field * field) +{ + field->fld_type = MAILIMF_FIELD_NONE; + mailimf_field_free(field); +} + +int +mailimf_resent_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * resent_date, + struct mailimf_mailbox_list * resent_from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc, + char * resent_msg_id) +{ + struct mailimf_orig_date * imf_resent_date; + struct mailimf_from * imf_resent_from; + struct mailimf_sender * imf_resent_sender; + struct mailimf_to * imf_resent_to; + struct mailimf_cc * imf_resent_cc; + struct mailimf_bcc * imf_resent_bcc; + struct mailimf_message_id * imf_resent_msg_id; + struct mailimf_field * field; + int r; + + imf_resent_date = NULL; + imf_resent_from = NULL; + imf_resent_sender = NULL; + imf_resent_to = NULL; + imf_resent_cc = NULL; + imf_resent_bcc = NULL; + imf_resent_msg_id = NULL; + field = NULL; + + if (resent_date != NULL) { + imf_resent_date = mailimf_orig_date_new(resent_date); + if (imf_resent_date == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_DATE, + NULL /* return-path */, + imf_resent_date /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (resent_from != NULL) { + imf_resent_from = mailimf_from_new(resent_from); + if (imf_resent_from == NULL) + goto free_field; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_FROM, + NULL /* return-path */, + NULL /* resent date */, + imf_resent_from /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (resent_sender != NULL) { + imf_resent_sender = mailimf_sender_new(resent_sender); + if (imf_resent_sender == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_SENDER, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + imf_resent_sender /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (resent_to != NULL) { + imf_resent_to = mailimf_to_new(resent_to); + if (imf_resent_to == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_TO, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + imf_resent_to /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (resent_cc != NULL) { + imf_resent_cc = mailimf_cc_new(resent_cc); + if (imf_resent_cc == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_CC, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + imf_resent_cc /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (resent_bcc != NULL) { + imf_resent_bcc = mailimf_bcc_new(resent_bcc); + if (imf_resent_bcc == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_BCC, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + imf_resent_bcc /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (resent_msg_id != NULL) { + imf_resent_msg_id = mailimf_message_id_new(resent_msg_id); + if (imf_resent_msg_id == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_MSG_ID, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + imf_resent_msg_id /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + return MAILIMF_NO_ERROR; + + free_field: + if (field != NULL) { + detach_resent_field(field); + mailimf_field_free(field); + } + free: + detach_free_common_fields(imf_resent_date, + imf_resent_from, + imf_resent_sender, + imf_resent_to, + imf_resent_cc, + imf_resent_bcc, + imf_resent_msg_id); + return MAILIMF_ERROR_MEMORY; +} + +struct mailimf_fields * +mailimf_resent_fields_new_with_data_all(struct mailimf_date_time * + resent_date, + struct mailimf_mailbox_list * + resent_from, + struct mailimf_mailbox * + resent_sender, + struct mailimf_address_list * + resent_to, + struct mailimf_address_list * + resent_cc, + struct mailimf_address_list * + resent_bcc, + char * resent_msg_id) +{ + struct mailimf_fields * resent_fields; + int r; + + resent_fields = mailimf_fields_new_empty(); + if (resent_fields == NULL) + goto err; + + r = mailimf_resent_fields_add_data(resent_fields, + resent_date, resent_from, + resent_sender, resent_to, + resent_cc, resent_bcc, + resent_msg_id); + if (r != MAILIMF_NO_ERROR) + goto free; + + return resent_fields; + + free: + mailimf_fields_free(resent_fields); + err: + return NULL; +} + + +struct mailimf_fields * +mailimf_resent_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc) +{ + struct mailimf_date_time * date; + char * msg_id; + struct mailimf_fields * fields; + + date = mailimf_get_current_date(); + if (date == NULL) + goto err; + + msg_id = mailimf_get_message_id(); + if (msg_id == NULL) + goto free_date; + + fields = mailimf_resent_fields_new_with_data_all(date, + from, sender, to, cc, bcc, msg_id); + if (fields == NULL) + goto free_msg_id; + + return fields; + + free_msg_id: + free(msg_id); + free_date: + mailimf_date_time_free(date); + err: + return NULL; +} + + +struct mailimf_fields * +mailimf_fields_new_empty(void) +{ + clist * list; + struct mailimf_fields * fields_list; + + list = clist_new(); + if (list == NULL) + return NULL; + + fields_list = mailimf_fields_new(list); + if (fields_list == NULL) + return NULL; + + return fields_list; +} + +int mailimf_fields_add(struct mailimf_fields * fields, + struct mailimf_field * field) +{ + int r; + + r = clist_append(fields->fld_list, field); + if (r < 0) + return MAILIMF_ERROR_MEMORY; + + return MAILIMF_NO_ERROR; +} + +static void detach_free_fields(struct mailimf_orig_date * date, + struct mailimf_from * from, + struct mailimf_sender * sender, + struct mailimf_reply_to * reply_to, + struct mailimf_to * to, + struct mailimf_cc * cc, + struct mailimf_bcc * bcc, + struct mailimf_message_id * msg_id, + struct mailimf_in_reply_to * in_reply_to, + struct mailimf_references * references, + struct mailimf_subject * subject) +{ + detach_free_common_fields(date, + from, + sender, + to, + cc, + bcc, + msg_id); + + if (reply_to != NULL) { + reply_to->rt_addr_list = NULL; + mailimf_reply_to_free(reply_to); + } + + if (in_reply_to != NULL) { + in_reply_to->mid_list = NULL; + mailimf_in_reply_to_free(in_reply_to); + } + + if (references != NULL) { + references->mid_list = NULL; + mailimf_references_free(references); + } + + if (subject != NULL) { + subject->sbj_value = NULL; + mailimf_subject_free(subject); + } +} + + +static void detach_field(struct mailimf_field * field) +{ + field->fld_type = MAILIMF_FIELD_NONE; + mailimf_field_free(field); +} + +int mailimf_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * msg_id, + clist * in_reply_to, + clist * references, + char * subject) +{ + struct mailimf_orig_date * imf_date; + struct mailimf_from * imf_from; + struct mailimf_sender * imf_sender; + struct mailimf_reply_to * imf_reply_to; + struct mailimf_to * imf_to; + struct mailimf_cc * imf_cc; + struct mailimf_bcc * imf_bcc; + struct mailimf_message_id * imf_msg_id; + struct mailimf_references * imf_references; + struct mailimf_in_reply_to * imf_in_reply_to; + struct mailimf_subject * imf_subject; + struct mailimf_field * field; + int r; + + imf_date = NULL; + imf_from = NULL; + imf_sender = NULL; + imf_reply_to = NULL; + imf_to = NULL; + imf_cc = NULL; + imf_bcc = NULL; + imf_msg_id = NULL; + imf_references = NULL; + imf_in_reply_to = NULL; + imf_subject =NULL; + field = NULL; + + if (date != NULL) { + imf_date = mailimf_orig_date_new(date); + if (imf_date == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_ORIG_DATE, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + imf_date /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (from != NULL) { + imf_from = mailimf_from_new(from); + if (imf_from == NULL) + goto free_field; + field = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + imf_from /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (sender != NULL) { + imf_sender = mailimf_sender_new(sender); + if (imf_sender == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_SENDER, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + imf_sender /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (reply_to != NULL) { + imf_reply_to = mailimf_reply_to_new(reply_to); + if (imf_reply_to == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_REPLY_TO, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + imf_reply_to /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (to != NULL) { + imf_to = mailimf_to_new(to); + if (imf_to == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_TO, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + imf_to /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (cc != NULL) { + imf_cc = mailimf_cc_new(cc); + if (imf_cc == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_CC, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + imf_cc /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (bcc != NULL) { + imf_bcc = mailimf_bcc_new(bcc); + if (imf_bcc == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_BCC, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + imf_bcc /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (msg_id != NULL) { + imf_msg_id = mailimf_message_id_new(msg_id); + if (imf_msg_id == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + imf_msg_id /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (in_reply_to != NULL) { + imf_in_reply_to = mailimf_in_reply_to_new(in_reply_to); + if (imf_in_reply_to == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_IN_REPLY_TO, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + imf_in_reply_to /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (references != NULL) { + imf_references = mailimf_references_new(references); + if (imf_references == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_REFERENCES, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + imf_references /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (subject != NULL) { + imf_subject = mailimf_subject_new(subject); + if (imf_subject == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_SUBJECT, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + imf_subject /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + return MAILIMF_NO_ERROR; + + free_field: + if (field != NULL) { + detach_field(field); + mailimf_field_free(field); + } + free: + detach_free_fields(imf_date, + imf_from, + imf_sender, + imf_reply_to, + imf_to, + imf_cc, + imf_bcc, + imf_msg_id, + imf_in_reply_to, + imf_references, + imf_subject); + + return MAILIMF_ERROR_MEMORY; +} + +struct mailimf_fields * +mailimf_fields_new_with_data_all(struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * message_id, + clist * in_reply_to, + clist * references, + char * subject) +{ + struct mailimf_fields * fields; + int r; + + fields = mailimf_fields_new_empty(); + if (fields == NULL) + goto err; + + r = mailimf_fields_add_data(fields, + date, + from, + sender, + reply_to, + to, + cc, + bcc, + message_id, + in_reply_to, + references, + subject); + if (r != MAILIMF_NO_ERROR) + goto free; + + return fields; + + free: + mailimf_fields_free(fields); + err: + return NULL; +} + +struct mailimf_fields * +mailimf_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + clist * in_reply_to, + clist * references, + char * subject) +{ + struct mailimf_date_time * date; + char * msg_id; + struct mailimf_fields * fields; + + date = mailimf_get_current_date(); + if (date == NULL) + goto err; + + msg_id = mailimf_get_message_id(); + if (msg_id == NULL) + goto free_date; + + fields = mailimf_fields_new_with_data_all(date, + from, sender, reply_to, + to, cc, bcc, + msg_id, + in_reply_to, references, + subject); + if (fields == NULL) + goto free_msg_id; + + return fields; + + free_msg_id: + free(msg_id); + free_date: + mailimf_date_time_free(date); + err: + return NULL; +} + + + +#define MAX_MESSAGE_ID 512 + +char * mailimf_get_message_id(void) +{ + char id[MAX_MESSAGE_ID]; + time_t now; + char name[MAX_MESSAGE_ID]; + long value; + + now = time(NULL); + value = random(); + + gethostname(name, MAX_MESSAGE_ID); + snprintf(id, MAX_MESSAGE_ID, "etPan.%lx.%lx.%x@%s", + (long) now, value, getpid(), name); + + return strdup(id); +} + +struct mailimf_date_time * mailimf_get_current_date(void) +{ + time_t now; + + now = time(NULL); + return mailimf_get_date(now); +} + +struct mailimf_date_time * mailimf_get_date(time_t t) +{ + struct tm gmt; + struct tm lt; + int off; + struct mailimf_date_time * date_time; + + if (gmtime_r(&t, &gmt) == NULL) + return NULL; + + if (localtime_r(&t, <) == NULL) + return NULL; + + off = (int) ((mail_mkgmtime(<) - mail_mkgmtime(&gmt)) * 100 / (60 * 60)); + + date_time = mailimf_date_time_new(lt.tm_mday, lt.tm_mon + 1, lt.tm_year + 1900, + lt.tm_hour, lt.tm_min, lt.tm_sec, + off); + + return date_time; +} + +void mailimf_single_fields_init(struct mailimf_single_fields * single_fields, + struct mailimf_fields * fields) +{ + clistiter * cur; + + memset(single_fields, 0, sizeof(struct mailimf_single_fields)); + + if (fields == NULL) { + return; + } + + cur = clist_begin(fields->fld_list); + while (cur != NULL) { + struct mailimf_field * field; + + field = clist_content(cur); + + switch (field->fld_type) { + case MAILIMF_FIELD_ORIG_DATE: + if (single_fields->fld_orig_date == NULL) + single_fields->fld_orig_date = field->fld_data.fld_orig_date; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_FROM: + if (single_fields->fld_from == NULL) { + single_fields->fld_from = field->fld_data.fld_from; + cur = clist_next(cur); + } + else { + clist_concat(single_fields->fld_from->frm_mb_list->mb_list, + field->fld_data.fld_from->frm_mb_list->mb_list); + mailimf_field_free(field); + cur = clist_delete(fields->fld_list, cur); + } + break; + case MAILIMF_FIELD_SENDER: + if (single_fields->fld_sender == NULL) + single_fields->fld_sender = field->fld_data.fld_sender; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_REPLY_TO: + if (single_fields->fld_reply_to == NULL) { + single_fields->fld_reply_to = field->fld_data.fld_reply_to; + cur = clist_next(cur); + } + else { + clist_concat(single_fields->fld_reply_to->rt_addr_list->ad_list, + field->fld_data.fld_reply_to->rt_addr_list->ad_list); + mailimf_field_free(field); + cur = clist_delete(fields->fld_list, cur); + } + break; + case MAILIMF_FIELD_TO: + if (single_fields->fld_to == NULL) { + single_fields->fld_to = field->fld_data.fld_to; + cur = clist_next(cur); + } + else { + clist_concat(single_fields->fld_to->to_addr_list->ad_list, + field->fld_data.fld_to->to_addr_list->ad_list); + mailimf_field_free(field); + cur = clist_delete(fields->fld_list, cur); + } + break; + case MAILIMF_FIELD_CC: + if (single_fields->fld_cc == NULL) { + single_fields->fld_cc = field->fld_data.fld_cc; + cur = clist_next(cur); + } + else { + clist_concat(single_fields->fld_cc->cc_addr_list->ad_list, + field->fld_data.fld_cc->cc_addr_list->ad_list); + mailimf_field_free(field); + cur = clist_delete(fields->fld_list, cur); + } + break; + case MAILIMF_FIELD_BCC: + if (single_fields->fld_bcc == NULL) { + single_fields->fld_bcc = field->fld_data.fld_bcc; + cur = clist_next(cur); + } + else { + if (field->fld_data.fld_bcc->bcc_addr_list != NULL) { + if (single_fields->fld_bcc->bcc_addr_list == NULL) { + single_fields->fld_bcc->bcc_addr_list = field->fld_data.fld_bcc->bcc_addr_list; + field->fld_data.fld_bcc->bcc_addr_list = NULL; + } + else { + clist_concat(single_fields->fld_bcc->bcc_addr_list->ad_list, + field->fld_data.fld_bcc->bcc_addr_list->ad_list); + } + mailimf_field_free(field); + cur = clist_delete(fields->fld_list, cur); + } + else { + cur = clist_next(cur); + } + } + break; + case MAILIMF_FIELD_MESSAGE_ID: + if (single_fields->fld_message_id == NULL) + single_fields->fld_message_id = field->fld_data.fld_message_id; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_IN_REPLY_TO: + if (single_fields->fld_in_reply_to == NULL) + single_fields->fld_in_reply_to = field->fld_data.fld_in_reply_to; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_REFERENCES: + if (single_fields->fld_references == NULL) + single_fields->fld_references = field->fld_data.fld_references; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_SUBJECT: + if (single_fields->fld_subject == NULL) + single_fields->fld_subject = field->fld_data.fld_subject; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_COMMENTS: + if (single_fields->fld_comments == NULL) + single_fields->fld_comments = field->fld_data.fld_comments; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_KEYWORDS: + if (single_fields->fld_keywords == NULL) + single_fields->fld_keywords = field->fld_data.fld_keywords; + cur = clist_next(cur); + break; + default: + cur = clist_next(cur); + break; + } + } +} + + +struct mailimf_single_fields * +mailimf_single_fields_new(struct mailimf_fields * fields) +{ + struct mailimf_single_fields * single_fields; + + single_fields = malloc(sizeof(struct mailimf_single_fields)); + if (single_fields == NULL) + goto err; + + mailimf_single_fields_init(single_fields, fields); + + return single_fields; + + err: + return NULL; +} + +void mailimf_single_fields_free(struct mailimf_single_fields * + single_fields) +{ + free(single_fields); +} + +struct mailimf_field * mailimf_field_new_custom(char * name, char * value) +{ + struct mailimf_optional_field * opt_field; + struct mailimf_field * field; + + opt_field = mailimf_optional_field_new(name, value); + if (opt_field == NULL) + goto err; + + field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, opt_field); + if (field == NULL) + goto free_opt_field; + + return field; + + free_opt_field: + mailimf_optional_field_free(opt_field); + err: + return NULL; +} diff --git a/Sources/libetpan/low-level/imf/mailimf_types_helper.h b/Sources/libetpan/low-level/imf/mailimf_types_helper.h new file mode 100644 index 00000000..09649573 --- /dev/null +++ b/Sources/libetpan/low-level/imf/mailimf_types_helper.h @@ -0,0 +1,394 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf_types_helper.h,v 1.15 2007/12/10 21:32:59 hoa Exp $ + */ + +#ifndef MAILIMF_TYPES_HELPER + +#define MAILIMF_TYPES_HELPER + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + IMPORTANT NOTE: + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + allocation functions will return NULL on failure +*/ + +/* + mailimf_mailbox_list_new_empty creates an empty list of mailboxes +*/ + +LIBETPAN_EXPORT +struct mailimf_mailbox_list * +mailimf_mailbox_list_new_empty(void); + +/* + mailimf_mailbox_list_add adds a mailbox to the list of mailboxes + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int mailimf_mailbox_list_add(struct mailimf_mailbox_list * mailbox_list, + struct mailimf_mailbox * mb); + +/* + mailimf_mailbox_list_add_parse parse the given string + into a mailimf_mailbox structure and adds it to the list of mailboxes + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int mailimf_mailbox_list_add_parse(struct mailimf_mailbox_list * mailbox_list, + char * mb_str); + +/* + mailimf_mailbox creates a mailimf_mailbox structure with the given + arguments and adds it to the list of mailboxes + + - display_name is the name that will be displayed for this mailbox, + for example 'name' in '"name" , + should be allocated with malloc() + + - address is the mailbox, for example 'mailbox@domain' + in '"name" , should be allocated with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int mailimf_mailbox_list_add_mb(struct mailimf_mailbox_list * mailbox_list, + char * display_name, char * address); + +/* + mailimf_address_list_new_empty creates an empty list of addresses +*/ + +LIBETPAN_EXPORT +struct mailimf_address_list * +mailimf_address_list_new_empty(void); + +/* + mailimf_address_list_add adds a mailbox to the list of addresses + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int mailimf_address_list_add(struct mailimf_address_list * address_list, + struct mailimf_address * addr); + +/* + mailimf_address_list_add_parse parse the given string + into a mailimf_address structure and adds it to the list of addresses + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int mailimf_address_list_add_parse(struct mailimf_address_list * address_list, + char * addr_str); + +/* + mailimf_address_list_add_mb creates a mailbox mailimf_address + with the given arguments and adds it to the list of addresses + + - display_name is the name that will be displayed for this mailbox, + for example 'name' in '"name" , + should be allocated with malloc() + + - address is the mailbox, for example 'mailbox@domain' + in '"name" , should be allocated with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int mailimf_address_list_add_mb(struct mailimf_address_list * address_list, + char * display_name, char * address); + +/* + mailimf_resent_fields_add_data adds a set of resent fields in the + given mailimf_fields structure. + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param resent_msg_id sould be allocated with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int +mailimf_resent_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * resent_date, + struct mailimf_mailbox_list * resent_from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc, + char * resent_msg_id); + +/* + mailimf_resent_fields_new_with_data_all creates a new mailimf_fields + structure with a set of resent fields + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param resent_msg_id sould be allocated with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +struct mailimf_fields * +mailimf_resent_fields_new_with_data_all(struct mailimf_date_time * + resent_date, struct mailimf_mailbox_list * resent_from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc, + char * resent_msg_id); + +/* + mailimf_resent_fields_new_with_data_all creates a new mailimf_fields + structure with a set of resent fields. + Resent-Date and Resent-Message-ID fields will be generated for you. + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +struct mailimf_fields * +mailimf_resent_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc); + +/* + this function creates a new mailimf_fields structure with no fields +*/ + +LIBETPAN_EXPORT +struct mailimf_fields * +mailimf_fields_new_empty(void); + + +/* + this function adds a field to the mailimf_fields structure + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int mailimf_fields_add(struct mailimf_fields * fields, + struct mailimf_field * field); + + +/* + mailimf_fields_add_data adds a set of fields in the + given mailimf_fields structure. + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param msg_id sould be allocated with malloc() + @param subject should be allocated with malloc() + @param in_reply_to each elements of this list should be allocated + with malloc() + @param references each elements of this list should be allocated + with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +int mailimf_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * msg_id, + clist * in_reply_to, + clist * references, + char * subject); + +/* + mailimf_fields_new_with_data_all creates a new mailimf_fields + structure with a set of fields + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param message_id sould be allocated with malloc() + @param subject should be allocated with malloc() + @param in_reply_to each elements of this list should be allocated + with malloc() + @param references each elements of this list should be allocated + with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +struct mailimf_fields * +mailimf_fields_new_with_data_all(struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * message_id, + clist * in_reply_to, + clist * references, + char * subject); + +/* + mailimf_fields_new_with_data creates a new mailimf_fields + structure with a set of fields + Date and Message-ID fields will be generated for you. + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param subject should be allocated with malloc() + @param in_reply_to each elements of this list should be allocated + with malloc() + @param references each elements of this list should be allocated + with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +LIBETPAN_EXPORT +struct mailimf_fields * +mailimf_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + clist * in_reply_to, + clist * references, + char * subject); + +/* + this function returns an allocated message identifier to + use in a Message-ID or Resent-Message-ID field +*/ + +LIBETPAN_EXPORT +char * mailimf_get_message_id(void); + +/* + this function returns a mailimf_date_time structure to + use in a Date or Resent-Date field +*/ + +LIBETPAN_EXPORT +struct mailimf_date_time * mailimf_get_current_date(void); + +LIBETPAN_EXPORT +struct mailimf_date_time * mailimf_get_date(time_t time); + +/* + mailimf_single_fields_init fills a mailimf_single_fields structure + with the content of a mailimf_fields structure +*/ + +LIBETPAN_EXPORT +void mailimf_single_fields_init(struct mailimf_single_fields * single_fields, + struct mailimf_fields * fields); + +/* + mailimf_single_fields_new creates a new mailimf_single_fields and + fills the structure with mailimf_fields +*/ + +LIBETPAN_EXPORT +struct mailimf_single_fields * +mailimf_single_fields_new(struct mailimf_fields * fields); + +LIBETPAN_EXPORT +void mailimf_single_fields_free(struct mailimf_single_fields * + single_fields); + +/* + mailimf_field_new_custom creates a new field of type optional + + @param name should be allocated with malloc() + @param value should be allocated with malloc() +*/ + +LIBETPAN_EXPORT +struct mailimf_field * mailimf_field_new_custom(char * name, char * value); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imf/mailimf_write.h b/Sources/libetpan/low-level/imf/mailimf_write.h new file mode 100644 index 00000000..4e6499a4 --- /dev/null +++ b/Sources/libetpan/low-level/imf/mailimf_write.h @@ -0,0 +1,134 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf_write.h,v 1.13 2004/11/21 21:53:37 hoa Exp $ + */ + +#ifndef MAILIMF_WRITE_H + +#define MAILIMF_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/* + mailimf_string_write writes a string to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +int mailimf_string_write(FILE * f, int * col, + const char * str, size_t length); + + +/* + mailimf_fields_write writes the fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +int mailimf_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_envelope_fields_write writes only some fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +int mailimf_envelope_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_field_write writes a field to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param field is the field to write +*/ + +int mailimf_field_write(FILE * f, int * col, + struct mailimf_field * field); + +/* + mailimf_quoted_string_write writes a string that is quoted + to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param string is the string to quote and write +*/ + +int mailimf_quoted_string_write(FILE * f, int * col, + const char * string, size_t len); + +int mailimf_address_list_write(FILE * f, int * col, + struct mailimf_address_list * addr_list); + +int mailimf_mailbox_list_write(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list); + +/* + mailimf_header_string_write writes a header value and fold the header + if needed. + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +int mailimf_header_string_write(FILE * f, int * col, + const char * str, size_t length); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imf/mailimf_write_file.c b/Sources/libetpan/low-level/imf/mailimf_write_file.c new file mode 100644 index 00000000..e420beed --- /dev/null +++ b/Sources/libetpan/low-level/imf/mailimf_write_file.c @@ -0,0 +1,157 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf_write_file.c,v 1.3 2005/06/01 12:22:18 smarinier Exp $ + */ + +#include "mailimf_write_file.h" +#include "mailimf_write_generic.h" + +static int do_write(void * data, const char * str, size_t length) +{ + FILE * f; + + f = data; + + return (int) fwrite(str, 1, length, f); +} + +LIBETPAN_EXPORT +int mailimf_string_write_file(FILE * f, int * col, + const char * str, size_t length) +{ + return mailimf_string_write_driver(do_write, f, col, str, length); +} + +LIBETPAN_EXPORT +int mailimf_fields_write_file(FILE * f, int * col, + struct mailimf_fields * fields) +{ + return mailimf_fields_write_driver(do_write, f, col, fields); +} + +LIBETPAN_EXPORT +int mailimf_envelope_fields_write_file(FILE * f, int * col, + struct mailimf_fields * fields) +{ + return mailimf_envelope_fields_write_driver(do_write, f, col, fields); +} + +LIBETPAN_EXPORT +int mailimf_field_write_file(FILE * f, int * col, + struct mailimf_field * field) +{ + return mailimf_field_write_driver(do_write, f, col, field); +} + +LIBETPAN_EXPORT +int mailimf_quoted_string_write_file(FILE * f, int * col, + const char * string, size_t len) +{ + return mailimf_quoted_string_write_driver(do_write, f, col, string, len); +} + +LIBETPAN_EXPORT +int mailimf_address_list_write_file(FILE * f, int * col, + struct mailimf_address_list * addr_list) +{ + return mailimf_address_list_write_driver(do_write, f, col, addr_list); +} + +LIBETPAN_EXPORT +int mailimf_mailbox_list_write_file(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list) +{ + return mailimf_mailbox_list_write_driver(do_write, f, col, mb_list); +} + +LIBETPAN_EXPORT +int mailimf_header_string_write_file(FILE * f, int * col, + const char * str, size_t length) +{ + return mailimf_header_string_write_driver(do_write, f, col, str, length); +} + + +/* binary compatibility with 0.34 - begin */ + +#ifdef MAILIMF_WRITE_COMPATIBILITY +int mailimf_string_write(FILE * f, int * col, + const char * str, size_t length) +{ + return mailimf_string_write_file(f, col, str, length); +} + +int mailimf_fields_write(FILE * f, int * col, + struct mailimf_fields * fields) +{ + return mailimf_fields_write_file(f, col, fields); +} + +int mailimf_envelope_fields_write(FILE * f, int * col, + struct mailimf_fields * fields) +{ + return mailimf_envelope_fields_write_file(f, col, fields); +} + +int mailimf_field_write(FILE * f, int * col, + struct mailimf_field * field) +{ + return mailimf_field_write_file(f, col, field); +} + +int mailimf_quoted_string_write(FILE * f, int * col, + const char * string, size_t len) +{ + return mailimf_quoted_string_write_file(f, col, string, len); +} + +int mailimf_address_list_write(FILE * f, int * col, + struct mailimf_address_list * addr_list) +{ + return mailimf_address_list_write_file(f, col, addr_list); +} + +int mailimf_mailbox_list_write(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list) +{ + return mailimf_mailbox_list_write_file(f, col, mb_list); +} + +int mailimf_header_string_write(FILE * f, int * col, + const char * str, size_t length) +{ + return mailimf_header_string_write_file(f, col, str, length); +} +#endif + +/* binary compatibility with 0.34 - end */ diff --git a/Sources/libetpan/low-level/imf/mailimf_write_file.h b/Sources/libetpan/low-level/imf/mailimf_write_file.h new file mode 100644 index 00000000..3bb28501 --- /dev/null +++ b/Sources/libetpan/low-level/imf/mailimf_write_file.h @@ -0,0 +1,180 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf_write_file.h,v 1.3 2005/06/01 12:22:18 smarinier Exp $ + */ + +#ifndef MAILIMF_WRITE_H + +#define MAILIMF_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#define MAILIMF_WRITE_COMPATIBILITY + +/* + mailimf_string_write_file writes a string to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ +LIBETPAN_EXPORT +int mailimf_string_write_file(FILE * f, int * col, + const char * str, size_t length); + + +/* + mailimf_fields_write_file writes the fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ +LIBETPAN_EXPORT +int mailimf_fields_write_file(FILE * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_envelope_fields_write_file writes only some fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ +LIBETPAN_EXPORT +int mailimf_envelope_fields_write_file(FILE * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_field_write_file writes a field to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param field is the field to write +*/ +LIBETPAN_EXPORT +int mailimf_field_write_file(FILE * f, int * col, + struct mailimf_field * field); + +/* + mailimf_quoted_string_write_file writes a string that is quoted + to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param string is the string to quote and write +*/ +LIBETPAN_EXPORT +int mailimf_quoted_string_write_file(FILE * f, int * col, + const char * string, size_t len); + +LIBETPAN_EXPORT +int mailimf_address_list_write_file(FILE * f, int * col, + struct mailimf_address_list * addr_list); + +LIBETPAN_EXPORT +int mailimf_mailbox_list_write_file(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list); + +/* + mailimf_header_string_write_file writes a header value and fold the header + if needed. + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +LIBETPAN_EXPORT +int mailimf_header_string_write_file(FILE * f, int * col, + const char * str, size_t length); + + + +/* binary compatibility with 0.34 - begin */ + +#ifdef MAILIMF_WRITE_COMPATIBILITY +LIBETPAN_EXPORT +int mailimf_string_write(FILE * f, int * col, + const char * str, size_t length); + +LIBETPAN_EXPORT +int mailimf_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + +LIBETPAN_EXPORT +int mailimf_envelope_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + +LIBETPAN_EXPORT +int mailimf_field_write(FILE * f, int * col, + struct mailimf_field * field); + +LIBETPAN_EXPORT +int mailimf_quoted_string_write(FILE * f, int * col, + const char * string, size_t len); + +LIBETPAN_EXPORT +int mailimf_address_list_write(FILE * f, int * col, + struct mailimf_address_list * addr_list); + +LIBETPAN_EXPORT +int mailimf_mailbox_list_write(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list); + +LIBETPAN_EXPORT +int mailimf_header_string_write(FILE * f, int * col, + const char * str, size_t length); +#endif + +/* binary compatibility with 0.34 - end */ + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imf/mailimf_write_generic.c b/Sources/libetpan/low-level/imf/mailimf_write_generic.c new file mode 100644 index 00000000..7c91a508 --- /dev/null +++ b/Sources/libetpan/low-level/imf/mailimf_write_generic.c @@ -0,0 +1,2030 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf_write_generic.c,v 1.3 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailimf_write_generic.h" + +#include +#include +#include + +#define MAX_MAIL_COL 72 + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define MAX_VALID_IMF_LINE 998 + +static int mailimf_orig_date_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + struct mailimf_orig_date * date); +static int mailimf_date_time_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_date_time * date_time); +static int mailimf_from_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_from * from); +static int mailimf_sender_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_sender * sender); +static int mailimf_reply_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_reply_to * reply_to); +static int mailimf_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_to * to); +static int mailimf_cc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_cc * to); +static int mailimf_bcc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_bcc * to); +static int mailimf_message_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_message_id * message_id); +static int mailimf_msg_id_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + clist * list); +static int mailimf_in_reply_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_in_reply_to * + in_reply_to); +static int mailimf_references_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_references * references); +static int mailimf_subject_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_subject * subject); + +static int mailimf_address_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_address * addr); +static int mailimf_group_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_group * group); + +static int mailimf_mailbox_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_mailbox * mb); + +static int mailimf_comments_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_comments * comments); + +static int mailimf_optional_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_optional_field * field); + +static int mailimf_keywords_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_keywords * keywords); + +static int mailimf_return_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_return * return_path); + +static int mailimf_path_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_path * path); + +static int mailimf_resent_date_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_orig_date * date); + +static int mailimf_resent_from_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_from * from); + +static int mailimf_resent_sender_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_sender * sender); + +static int mailimf_resent_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_to * to); + +static int mailimf_resent_cc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_cc * cc); + +static int mailimf_resent_bcc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_bcc * bcc); + +static int +mailimf_resent_msg_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_message_id * message_id); + + + +/* ************************ */ + +#if 0 +int mailimf_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + char * str, size_t length) +{ + int r; + + if (length != 0) { + r = fwrite(str, sizeof(char), length, f); + if (r < 0) + return MAILIMF_ERROR_FILE; + * col += length; + } + + return MAILIMF_NO_ERROR; +} +#endif + +#define CRLF "\r\n" +#define HEADER_FOLD "\r\n " + +static inline int flush_buf(int (* do_write)(void *, const char *, size_t), void * data, const char * str, size_t length) +{ + if (length != 0) { + int r; + + if (length > 0) { + r = do_write(data, str, length); + if (r == 0) + return MAILIMF_ERROR_FILE; + } + } + return MAILIMF_NO_ERROR; +} + +#define CUT_AT_MAX_VALID_IMF_LINE + +int mailimf_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + const char * str, size_t length) +{ + int r; + size_t count; + const char * block_begin; + const char * p; + int done; + + p = str; + block_begin = str; + count = 0; + + while (length > 0) { +#ifdef CUT_AT_MAX_VALID_IMF_LINE + if (count >= 998) { + /* + cut lines at maximum valid length for internet message + format standard (currently RFC 2822) + + This should not happen. + In case there are some lines larger than 998 in body, + the encoding must be changed into base64 or quoted-printable + so that wrapping to 72 columns is done. + */ + + r = flush_buf(do_write, data, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + + r = do_write(data, CRLF, sizeof(CRLF) - 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + + count = 0; + block_begin = p; + + * col = 0; + } +#endif + switch (* p) { + case '\n': + r = flush_buf(do_write, data, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + + r = do_write(data, CRLF, sizeof(CRLF) - 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + + p ++; + length --; + count = 0; + block_begin = p; + + * col = 0; + break; + + case '\r': + done = 0; + if (length >= 2) { + if (* (p + 1) == '\n') { + r = flush_buf(do_write, data, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + + r = do_write(data, CRLF, sizeof(CRLF) - 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + + p += 2; + length -= 2; + count = 0; + block_begin = p; + + * col = 0; + + done = 1; + } + } + if (!done) { + r = flush_buf(do_write, data, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + + r = do_write(data, CRLF, sizeof(CRLF) - 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + + p ++; + length --; + count = 0; + block_begin = p; + + * col = 0; + } + break; + + default: + p ++; + count ++; + length --; + break; + } + } + + r = flush_buf(do_write, data, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + * col += count; + + return MAILIMF_NO_ERROR; +} + +#if 0 +int mailimf_header_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + char * str, size_t length) +{ + char * p; + char * block_begin; + int current_col; + char * last_cut; + int r; + int first; + + if (* col + length < MAX_MAIL_COL) + return mailimf_string_write_driver(do_write, data, col, str, length); + + first = 1; + p = str; + block_begin = p; + last_cut = block_begin; + current_col = * col; + + while (1) { + if (current_col >= MAX_MAIL_COL) { + /* if we reach the maximum recommanded size of line */ + if (last_cut == block_begin) { + /* if we could not find any place to cut */ + if (first) { + /* fold the header */ + r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + current_col = * col + p - block_begin; + first = 0; + } + else { + /* cut the header */ + r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + first = 0; + block_begin = p; + last_cut = block_begin; + current_col = * col + p - block_begin; + } + } + else { + /* if we found a place to cut */ + r = mailimf_string_write_driver(do_write, data, col, block_begin, last_cut - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + first = 0; + block_begin = last_cut; + last_cut = block_begin; + current_col = * col + p - block_begin; + continue; + } + } + else { + if (length == 0) + break; + + switch (* p) { + case ' ': + case '\t': + last_cut = p; + current_col ++; + break; + + case '\r': + case '\n': + current_col = 0; + break; + + default: + current_col ++; + break; + } + + p ++; + length --; + } + } + + return mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin); +} +#endif + +#if 0 +enum { + STATE_LOWER_72, + STATE_LOWER_72_CUT, + STATE_EQUAL_72, + STATE_LOWER_998, + STATE_EQUAL_998, +}; + +int mailimf_header_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + const char * str, size_t length) +{ + int state; + const char * p; + const char * block_begin; + size_t size; + const char * cut; + int r; + + if (* col < MAX_MAIL_COL) + state = STATE_LOWER_72_CUT; + else if (* col == MAX_MAIL_COL) + state = STATE_EQUAL_72; + else if (* col < MAX_VALID_IMF_LINE) + state = STATE_LOWER_998; + else + state = STATE_EQUAL_998; + + p = str; + block_begin = p; + size = * col; + cut = p; + + while (length > 0) { + switch (state) { + case STATE_LOWER_72: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + break; + + case ' ': + case '\t': + cut = p; + p ++; + length --; + size ++; + state = STATE_LOWER_72_CUT; + break; + + default: + if (size < MAX_MAIL_COL - 1) { + p ++; + length --; + size ++; + } + else { + state = STATE_EQUAL_72; + p ++; + length --; + size ++; + } + break; + } + break; /* end of STATE_LOWER_72 */ + + case STATE_LOWER_72_CUT: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + state = STATE_LOWER_72; + break; + + case ' ': + case '\t': + cut = p; + p ++; + length --; + size ++; + break; + + default: + if (size < MAX_MAIL_COL) { + p ++; + length --; + size ++; + } + else { + r = mailimf_string_write_driver(do_write, data, col, block_begin, cut - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = cut; + if ((* block_begin == ' ') || (* block_begin == '\t')) + block_begin ++; + size = p - block_begin + * col; + state = STATE_LOWER_72; + } + break; + } + break; /* end of STATE_LOWER_72_CUT */ + + case STATE_EQUAL_72: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + state = STATE_LOWER_72; + break; + + case ' ': + case '\t': + r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = p; + size = p - block_begin + * col; + state = STATE_LOWER_72; + break; + + default: + p ++; + length --; + size ++; + state = STATE_LOWER_998; + break; + } + break; /* end of STATE_EQUAL_72 */ + + case STATE_LOWER_998: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + state = STATE_LOWER_72; + break; + + case ' ': + case '\t': + r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = p; + size = p - block_begin + * col; + state = STATE_LOWER_72; + break; + + default: + if (size < MAX_VALID_IMF_LINE - 1) { + p ++; + length --; + size ++; + } + else { + p ++; + length --; + size = 0; + state = STATE_EQUAL_998; + } + break; + } + break; /* end of STATE_LOWER_998 */ + + case STATE_EQUAL_998: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + state = STATE_LOWER_72; + break; + + case ' ': + case '\t': + r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = p; + size = p - block_begin + * col; + state = STATE_LOWER_72; + break; + + default: +#ifdef CUT_AT_MAX_VALID_IMF_LINE + r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = p; + size = p - block_begin + * col; + state = STATE_LOWER_72; +#else + p ++; + length --; + size ++; +#endif + break; + } + break; /* end of STATE_EQUAL_998 */ + } + } + + r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +enum { + STATE_BEGIN, + STATE_WORD, + STATE_SPACE +}; + +int mailimf_header_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + const char * str, size_t length) +{ + int state; + const char * p; + const char * word_begin; + int first; + + state = STATE_BEGIN; + + p = str; + word_begin = p; + first = 1; + + while (length > 0) { + switch (state) { + case STATE_BEGIN: + switch (* p) { + case '\r': + case '\n': + case ' ': + case '\t': + p ++; + length --; + break; + + default: + word_begin = p; + state = STATE_WORD; + break; + } + break; + + case STATE_SPACE: + switch (* p) { + case '\r': + case '\n': + case ' ': + case '\t': + p ++; + length --; + break; + + default: + word_begin = p; + state = STATE_WORD; + break; + } + break; + + case STATE_WORD: + switch (* p) { + case '\r': + case '\n': + case ' ': + case '\t': + if (p - word_begin + (* col) + 1 > MAX_MAIL_COL) + mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + else { + if (!first) + mailimf_string_write_driver(do_write, data, col, " ", 1); + } + first = 0; + mailimf_string_write_driver(do_write, data, col, word_begin, p - word_begin); + state = STATE_SPACE; + break; + + default: + if (p - word_begin + (* col) >= MAX_VALID_IMF_LINE) { + mailimf_string_write_driver(do_write, data, col, word_begin, p - word_begin); + mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + word_begin = p; + } + p ++; + length --; + break; + } + break; + } + } + + if (state == STATE_WORD) { + if (p - word_begin + (* col) >= MAX_MAIL_COL) + mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + else { + if (!first) + mailimf_string_write_driver(do_write, data, col, " ", 1); + } + first = 0; + mailimf_string_write_driver(do_write, data, col, word_begin, p - word_begin); + } + + return MAILIMF_NO_ERROR; +} + +int mailimf_envelope_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + int r; + struct mailimf_field * field; + + field = clist_content(cur); + if (field->fld_type != MAILIMF_FIELD_OPTIONAL_FIELD) { + r = mailimf_field_write_driver(do_write, data, col, field); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + + return MAILIMF_NO_ERROR; +} + +int mailimf_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + int r; + + r = mailimf_field_write_driver(do_write, data, col, clist_content(cur)); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + +#if 0 +int mailimf_unparsed_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_unparsed_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->list) ; cur != NULL ; cur = cur->next) { + int r; + + r = mailimf_optional_field_write_driver(do_write, data, col, cur->data); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} +#endif + +int mailimf_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_field * field) +{ + int r; + + switch (field->fld_type) { + case MAILIMF_FIELD_RETURN_PATH: + r = mailimf_return_write_driver(do_write, data, col, field->fld_data.fld_return_path); + break; + case MAILIMF_FIELD_RESENT_DATE: + r = mailimf_resent_date_write_driver(do_write, data, col, field->fld_data.fld_resent_date); + break; + case MAILIMF_FIELD_RESENT_FROM: + r = mailimf_resent_from_write_driver(do_write, data, col, field->fld_data.fld_resent_from); + break; + case MAILIMF_FIELD_RESENT_SENDER: + r = mailimf_resent_sender_write_driver(do_write, data, col, field->fld_data.fld_resent_sender); + break; + case MAILIMF_FIELD_RESENT_TO: + r = mailimf_resent_to_write_driver(do_write, data, col, field->fld_data.fld_resent_to); + break; + case MAILIMF_FIELD_RESENT_CC: + r = mailimf_resent_cc_write_driver(do_write, data, col, field->fld_data.fld_resent_cc); + break; + case MAILIMF_FIELD_RESENT_BCC: + r = mailimf_resent_bcc_write_driver(do_write, data, col, field->fld_data.fld_resent_bcc); + break; + case MAILIMF_FIELD_RESENT_MSG_ID: + r = mailimf_resent_msg_id_write_driver(do_write, data, col, field->fld_data.fld_resent_msg_id); + break; + case MAILIMF_FIELD_ORIG_DATE: + r = mailimf_orig_date_write_driver(do_write, data, col, field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_FROM: + r = mailimf_from_write_driver(do_write, data, col, field->fld_data.fld_from); + break; + case MAILIMF_FIELD_SENDER: + r = mailimf_sender_write_driver(do_write, data, col, field->fld_data.fld_sender); + break; + case MAILIMF_FIELD_REPLY_TO: + r = mailimf_reply_to_write_driver(do_write, data, col, field->fld_data.fld_reply_to); + break; + case MAILIMF_FIELD_TO: + r = mailimf_to_write_driver(do_write, data, col, field->fld_data.fld_to); + break; + case MAILIMF_FIELD_CC: + r = mailimf_cc_write_driver(do_write, data, col, field->fld_data.fld_cc); + break; + case MAILIMF_FIELD_BCC: + r = mailimf_bcc_write_driver(do_write, data, col, field->fld_data.fld_bcc); + break; + case MAILIMF_FIELD_MESSAGE_ID: + r = mailimf_message_id_write_driver(do_write, data, col, field->fld_data.fld_message_id); + break; + case MAILIMF_FIELD_IN_REPLY_TO: + r = mailimf_in_reply_to_write_driver(do_write, data, col, field->fld_data.fld_in_reply_to); + break; + case MAILIMF_FIELD_REFERENCES: + r = mailimf_references_write_driver(do_write, data, col, field->fld_data.fld_references); + break; + case MAILIMF_FIELD_SUBJECT: + r = mailimf_subject_write_driver(do_write, data, col, field->fld_data.fld_subject); + break; + case MAILIMF_FIELD_COMMENTS: + r = mailimf_comments_write_driver(do_write, data, col, field->fld_data.fld_comments); + break; + case MAILIMF_FIELD_KEYWORDS: + r = mailimf_keywords_write_driver(do_write, data, col, field->fld_data.fld_keywords); + break; + case MAILIMF_FIELD_OPTIONAL_FIELD: + r = mailimf_optional_field_write_driver(do_write, data, col, field->fld_data.fld_optional_field); + break; + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_orig_date_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_orig_date * date) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Date: ", 6); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_date_time_write_driver(do_write, data, col, date->dt_date_time); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +#define MAX_DATE_STR 256 + +/* 0 = Sunday */ +/* y > 1752 */ + +static int dayofweek(int year, int month, int day) +{ + static int offset[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; + + year -= month < 3; + + return (year + year/4 - year/100 + year/400 + offset[month-1] + day) % 7; +} + +static const char * week_of_day_str[] = { "Sun", "Mon", "Tue", "Wed", "Thu", + "Fri", "Sat"}; +static const char * month_str[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + +static int mailimf_date_time_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_date_time * date_time) +{ + int r; + char date_str[MAX_DATE_STR]; +#if 0 + struct tm tmval; + time_t timeval; +#endif + int wday; + +#if 0 + tmval.tm_sec = date_time->sec; + tmval.tm_min = date_time->min; + tmval.tm_hour = date_time->hour; + tmval.tm_sec = date_time->sec; + tmval.tm_mday = date_time->day; + tmval.tm_mon = date_time->month - 1; + tmval.tm_year = date_time->year - 1900; + tmval.tm_isdst = 1; + + timeval = mktime(&tmval); + + localtime_r(&timeval, &tmval); +#endif + + wday = dayofweek(date_time->dt_year, date_time->dt_month, date_time->dt_day); + + snprintf(date_str, MAX_DATE_STR, "%s, %i %s %i %02i:%02i:%02i %+05i", + week_of_day_str[wday], date_time->dt_day, + month_str[date_time->dt_month - 1], + date_time->dt_year, date_time->dt_hour, + date_time->dt_min, date_time->dt_sec, + date_time->dt_zone); + + r = mailimf_string_write_driver(do_write, data, col, date_str, strlen(date_str)); + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int mailimf_from_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_from * from) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "From: ", 6); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_mailbox_list_write_driver(do_write, data, col, from->frm_mb_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_sender_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_sender * sender) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Sender: ", 8); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_mailbox_write_driver(do_write, data, col, sender->snd_mb); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_reply_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_reply_to * reply_to) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Reply-To: ", 10); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write_driver(do_write, data, col, reply_to->rt_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_to * to) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "To: ", 4); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write_driver(do_write, data, col, to->to_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_cc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_cc * cc) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Cc: ", 4); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write_driver(do_write, data, col, cc->cc_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_bcc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_bcc * bcc) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Bcc: ", 5); + if (r != MAILIMF_NO_ERROR) + return r; + + if (bcc->bcc_addr_list != NULL) { + r = mailimf_address_list_write_driver(do_write, data, col, bcc->bcc_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_message_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_message_id * message_id) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Message-ID: ", 12); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, + message_id->mid_value, + strlen(message_id->mid_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_msg_id_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, clist * mid_list) +{ + clistiter * cur; + int r; + int first; + + first = TRUE; + + for(cur = clist_begin(mid_list) ; cur != NULL ; cur = clist_next(cur)) { + char * msgid; + size_t len; + + msgid = clist_content(cur); + len = strlen(msgid); + + /* + XXX - if this is the first message ID, don't fold. + This is a workaround for a bug of old versions of INN. + */ + if (!first) { + if (* col > 1) { + + if (* col + len >= MAX_MAIL_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + first = TRUE; + } + } + } + + if (!first) { + r = mailimf_string_write_driver(do_write, data, col, " ", 1); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + + r = mailimf_string_write_driver(do_write, data, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, msgid, len); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_in_reply_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_in_reply_to * in_reply_to) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "In-Reply-To: ", 13); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_msg_id_list_write_driver(do_write, data, col, in_reply_to->mid_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_references_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_references * references) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "References: ", 12); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_msg_id_list_write_driver(do_write, data, col, references->mid_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + + +static int mailimf_subject_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_subject * subject) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Subject: ", 9); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_header_string_write_driver(do_write, data, col, + subject->sbj_value, strlen(subject->sbj_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +int mailimf_address_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_address_list * addr_list) +{ + clistiter * cur; + int r; + int first; + + first = TRUE; + + for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_address * addr; + + addr = clist_content(cur); + + if (!first) { + r = mailimf_string_write_driver(do_write, data, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + + r = mailimf_address_write_driver(do_write, data, col, addr); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_address_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_address * addr) +{ + int r; + + switch(addr->ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + r = mailimf_mailbox_write_driver(do_write, data, col, addr->ad_data.ad_mailbox); + if (r != MAILIMF_NO_ERROR) + return r; + + break; + + case MAILIMF_ADDRESS_GROUP: + r = mailimf_group_write_driver(do_write, data, col, addr->ad_data.ad_group); + if (r != MAILIMF_NO_ERROR) + return r; + + break; + } + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_group_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_group * group) +{ + int r; + + r = mailimf_header_string_write_driver(do_write, data, col, group->grp_display_name, + strlen(group->grp_display_name)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, ": ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + if (group->grp_mb_list != NULL) { + r = mailimf_mailbox_list_write_driver(do_write, data, col, group->grp_mb_list); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write_driver(do_write, data, col, ";", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + + +int mailimf_mailbox_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_mailbox_list * mb_list) +{ + clistiter * cur; + int r; + int first; + + first = TRUE; + + for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = clist_content(cur); + + if (!first) { + r = mailimf_string_write_driver(do_write, data, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + + r = mailimf_mailbox_write_driver(do_write, data, col, mb); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + +int mailimf_quoted_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + const char * string, size_t len) +{ + int r; + size_t i; + + r = do_write(data, "\"", 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + for(i = 0 ; i < len ; i ++) { + switch (string[i]) { + case '\\': + case '\"': + r = do_write(data, "\\", 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + r = do_write(data, &string[i], 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + (* col) += 2; + break; + + default: + r = do_write(data, &string[i], 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + (* col) ++; + break; + } + } + r = do_write(data, "\"", 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + + return MAILIMF_NO_ERROR; +} + + +/* +static int +atext = ALPHA / DIGIT / ; Any character except controls, + "!" / "#" / ; SP, and specials. + "$" / "%" / ; Used for atoms + "&" / "'" / + "*" / "+" / + "-" / "/" / + "=" / "?" / + "^" / "_" / + "`" / "{" / + "|" / "}" / + "~" +*/ + +static int is_atext(const char * s) +{ + const char * p; + + for(p = s ; * p != 0 ; p ++) { + if (isalpha((unsigned char) * p)) + continue; + if (isdigit((unsigned char) * p)) + continue; + switch (*p) { + case ' ': + case '\t': + case '!': + case '#': + case '$': + case '%': + case '&': + case '\'': + case '*': + case '+': + case '-': + case '/': + case '=': + case '?': + case '^': + case '_': + case '`': + case '{': + case '|': + case '}': + case '~': + break; + default: + return 0; + } + } + + return 1; +} + +static int mailimf_mailbox_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_mailbox * mb) +{ + int r; + int do_fold; + +#if 0 + if (* col > 1) { + + if (mb->mb_display_name != NULL) { + if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } + } +#endif + + if (mb->mb_display_name) { + + if (is_atext(mb->mb_display_name)) { + r = mailimf_header_string_write_driver(do_write, data, col, mb->mb_display_name, + strlen(mb->mb_display_name)); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + if (mb->mb_display_name != NULL) { + if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + + if (strlen(mb->mb_display_name) > MAX_VALID_IMF_LINE / 2) + return MAILIMF_ERROR_INVAL; + + r = mailimf_quoted_string_write_driver(do_write, data, col, mb->mb_display_name, + strlen(mb->mb_display_name)); + if (r != MAILIMF_NO_ERROR) + return r; + } + + do_fold = 0; + if (* col > 1) { + + if (* col + strlen(mb->mb_addr_spec) + 3 >= MAX_MAIL_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + do_fold = 1; + } + } + + if (do_fold) + r = mailimf_string_write_driver(do_write, data, col, "<", 1); + else + r = mailimf_string_write_driver(do_write, data, col, " <", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, mb->mb_addr_spec, + strlen(mb->mb_addr_spec)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + if (* col + strlen(mb->mb_addr_spec) >= MAX_MAIL_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write_driver(do_write, data, col, + mb->mb_addr_spec, strlen(mb->mb_addr_spec)); + if (r != MAILIMF_NO_ERROR) + return r; + } + + + return MAILIMF_NO_ERROR; +} + +static int mailimf_comments_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_comments * comments) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Comments: ", 10); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_header_string_write_driver(do_write, data, col, + comments->cm_value, strlen(comments->cm_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_optional_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_optional_field * field) +{ + int r; + + if (strlen(field->fld_name) + 2 > MAX_VALID_IMF_LINE) + return MAILIMF_ERROR_INVAL; + + r = mailimf_string_write_driver(do_write, data, col, field->fld_name, strlen(field->fld_name)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, ": ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_header_string_write_driver(do_write, data, col, field->fld_value, + strlen(field->fld_value)); + if (r != MAILIMF_NO_ERROR) + return r; + +#if 0 + /* XXX parsing debug */ + mailimf_string_write_driver(do_write, data, col, " (X)", 4); +#endif + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_keywords_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_keywords * keywords) +{ + int r; + clistiter * cur; + int first; + + r = mailimf_string_write_driver(do_write, data, col, "Keywords: ", 10); + if (r != MAILIMF_NO_ERROR) + return r; + + first = TRUE; + + for(cur = clist_begin(keywords->kw_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * keyword; + size_t len; + + keyword = clist_content(cur); + len = strlen(keyword); + + if (!first) { + r = mailimf_string_write_driver(do_write, data, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + +#if 0 + if (* col > 1) { + + if (* col + len >= MAX_MAIL_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } +#endif + + r = mailimf_header_string_write_driver(do_write, data, col, keyword, len); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +#if 0 +static int mailimf_delivering_info_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_delivering_info * info) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(info->received_fields) ; + cur != NULL ; cur = cur->next) { + struct mailimf_trace_resent_fields * field; + + field = cur->data; + + r = mailimf_trace_resent_fields_write_driver(do_write, data, col, field); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + +static int +mailimf_trace_resent_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_trace_resent_fields * field) +{ + int r; + + if (field->return_path != NULL) { + r = mailimf_return_write_driver(do_write, data, col, field->return_path); + if (r != MAILIMF_NO_ERROR) + return r; + } + + if (field->resent_fields != NULL) { + r = mailimf_resent_fields_write_driver(do_write, data, col, field->resent_fields); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} +#endif + +static int mailimf_return_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_return * return_path) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Return-Path: ", 13); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_path_write_driver(do_write, data, col, return_path->ret_path); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_path_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_path * path) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + if (path->pt_addr_spec != NULL) { + r = mailimf_string_write_driver(do_write, data, col, path->pt_addr_spec, + strlen(path->pt_addr_spec)); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write_driver(do_write, data, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +#if 0 +static int mailimf_resent_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_resent_fields_list * + resent_fields) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(resent_fields->list) ; cur != NULL ; cur = cur->next) { + struct mailimf_resent_field * field; + + field = cur->data; + + r = mailimf_resent_field_write_driver(do_write, data, col, field); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + + +static int mailimf_resent_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_resent_field * + resent_field) +{ + int r; + + switch (resent_field->type) { + case MAILIMF_RESENT_FIELD_DATE: + r = mailimf_resent_date_write_driver(do_write, data, col, resent_field->resent_date); + break; + + case MAILIMF_RESENT_FIELD_FROM: + r = mailimf_resent_from_write_driver(do_write, data, col, resent_field->resent_from); + break; + + case MAILIMF_RESENT_FIELD_SENDER: + r = mailimf_resent_sender_write_driver(do_write, data, col, resent_field->resent_sender); + break; + + case MAILIMF_RESENT_FIELD_TO: + r = mailimf_resent_to_write_driver(do_write, data, col, resent_field->resent_to); + break; + + case MAILIMF_RESENT_FIELD_CC: + r = mailimf_resent_cc_write_driver(do_write, data, col, resent_field->resent_cc); + break; + + case MAILIMF_RESENT_FIELD_BCC: + r = mailimf_resent_bcc_write_driver(do_write, data, col, resent_field->resent_bcc); + break; + + case MAILIMF_RESENT_FIELD_MSG_ID: + r = mailimf_resent_msg_id_write_driver(do_write, data, col, resent_field->resent_msg_id); + break; + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +static int mailimf_resent_date_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_orig_date * date) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Resent-Date: ", 13); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_date_time_write_driver(do_write, data, col, date->dt_date_time); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_resent_from_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_from * from) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Resent-From: ", 13); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_mailbox_list_write_driver(do_write, data, col, from->frm_mb_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_resent_sender_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_sender * sender) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Resent-Sender: ", 15); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_mailbox_write_driver(do_write, data, col, sender->snd_mb); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_resent_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_to * to) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Resent-To: ", 11); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write_driver(do_write, data, col, to->to_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_resent_cc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_cc * cc) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Resent-Cc: ", 11); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write_driver(do_write, data, col, cc->cc_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_resent_bcc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_bcc * bcc) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Resent-Bcc: ", 12); + if (r != MAILIMF_NO_ERROR) + return r; + + if (bcc->bcc_addr_list != NULL) { + r = mailimf_address_list_write_driver(do_write, data, col, bcc->bcc_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int +mailimf_resent_msg_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_message_id * message_id) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Resent-Message-ID: ", 19); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, + message_id->mid_value, strlen(message_id->mid_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} diff --git a/Sources/libetpan/low-level/imf/mailimf_write_generic.h b/Sources/libetpan/low-level/imf/mailimf_write_generic.h new file mode 100644 index 00000000..4cd65e9a --- /dev/null +++ b/Sources/libetpan/low-level/imf/mailimf_write_generic.h @@ -0,0 +1,150 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf_write_generic.h,v 1.3 2007/12/10 21:32:59 hoa Exp $ + */ + +#ifndef MAILIMF_WRITE_GENERIC_H + +#define MAILIMF_WRITE_GENERIC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/* + mailimf_string_write writes a string to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +LIBETPAN_EXPORT +int mailimf_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + const char * str, size_t length); + + +/* + mailimf_fields_write writes the fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +LIBETPAN_EXPORT +int mailimf_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + struct mailimf_fields * fields); + + +/* + mailimf_envelope_fields_write writes only some fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +LIBETPAN_EXPORT +int mailimf_envelope_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + struct mailimf_fields * fields); + + +/* + mailimf_field_write writes a field to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param field is the field to write +*/ + +LIBETPAN_EXPORT +int mailimf_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + struct mailimf_field * field); + +/* + mailimf_quoted_string_write writes a string that is quoted + to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param string is the string to quote and write +*/ + +LIBETPAN_EXPORT +int mailimf_quoted_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + const char * string, size_t len); + +LIBETPAN_EXPORT +int mailimf_address_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + struct mailimf_address_list * addr_list); + +LIBETPAN_EXPORT +int mailimf_mailbox_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + struct mailimf_mailbox_list * mb_list); + +/* + mailimf_header_string_write writes a header value and fold the header + if needed. + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +LIBETPAN_EXPORT +int mailimf_header_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + const char * str, size_t length); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/imf/mailimf_write_mem.c b/Sources/libetpan/low-level/imf/mailimf_write_mem.c new file mode 100644 index 00000000..6b06330a --- /dev/null +++ b/Sources/libetpan/low-level/imf/mailimf_write_mem.c @@ -0,0 +1,106 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf_write_mem.c,v 1.2 2004/11/21 21:53:37 hoa Exp $ + */ + +#include "mailimf_write_mem.h" +#include "mailimf_write_generic.h" + +static int do_write(void * data, const char * str, size_t length) +{ + MMAPString * f; + + f = data; + + if (mmap_string_append_len(f, str, length) == NULL) + return 0; + else + return (int) length; +} + +LIBETPAN_EXPORT +int mailimf_string_write_mem(MMAPString * f, int * col, + const char * str, size_t length) +{ + return mailimf_string_write_driver(do_write, f, col, str, length); +} + +LIBETPAN_EXPORT +int mailimf_fields_write_mem(MMAPString * f, int * col, + struct mailimf_fields * fields) +{ + return mailimf_fields_write_driver(do_write, f, col, fields); +} + +LIBETPAN_EXPORT +int mailimf_envelope_fields_write_mem(MMAPString * f, int * col, + struct mailimf_fields * fields) +{ + return mailimf_envelope_fields_write_driver(do_write, f, col, fields); +} + +LIBETPAN_EXPORT +int mailimf_field_write_mem(MMAPString * f, int * col, + struct mailimf_field * field) +{ + return mailimf_field_write_driver(do_write, f, col, field); +} + +LIBETPAN_EXPORT +int mailimf_quoted_string_write_mem(MMAPString * f, int * col, + const char * string, size_t len) +{ + return mailimf_quoted_string_write_driver(do_write, f, col, string, len); +} + +LIBETPAN_EXPORT +int mailimf_address_list_write_mem(MMAPString * f, int * col, + struct mailimf_address_list * addr_list) +{ + return mailimf_address_list_write_driver(do_write, f, col, addr_list); +} + +LIBETPAN_EXPORT +int mailimf_mailbox_list_write_mem(MMAPString * f, int * col, + struct mailimf_mailbox_list * mb_list) +{ + return mailimf_mailbox_list_write_driver(do_write, f, col, mb_list); +} + +LIBETPAN_EXPORT +int mailimf_header_string_write_mem(MMAPString * f, int * col, + const char * str, size_t length) +{ + return mailimf_header_string_write_driver(do_write, f, col, str, length); +} + diff --git a/Sources/libetpan/low-level/imf/mailimf_write_mem.h b/Sources/libetpan/low-level/imf/mailimf_write_mem.h new file mode 100644 index 00000000..adf2571f --- /dev/null +++ b/Sources/libetpan/low-level/imf/mailimf_write_mem.h @@ -0,0 +1,143 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf_write_mem.h,v 1.2 2004/11/21 21:53:37 hoa Exp $ + */ + +#ifndef MAILIMF_WRITE_MEM_H + +#define MAILIMF_WRITE_MEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +/* + mailimf_string_write_mem appends a string to a given string + + @param f is the string + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +LIBETPAN_EXPORT +int mailimf_string_write_mem(MMAPString * f, int * col, + const char * str, size_t length); + + +/* + mailimf_fields_write_mem appends the fields to a given string + + @param f is the string + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +LIBETPAN_EXPORT +int mailimf_fields_write_mem(MMAPString * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_envelope_fields_write_mem appends some fields to a given string + + @param f is the string + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +LIBETPAN_EXPORT +int mailimf_envelope_fields_write_mem(MMAPString * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_field_write_mem appends a field to a given string + + @param f is the string + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param field is the field to write +*/ + +LIBETPAN_EXPORT +int mailimf_field_write_mem(MMAPString * f, int * col, + struct mailimf_field * field); + +/* + mailimf_quoted_string_write_mem appends a string that is quoted + to a given string + + @param f is the string + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param string is the string to quote and write +*/ + +LIBETPAN_EXPORT +int mailimf_quoted_string_write_mem(MMAPString * f, int * col, + const char * string, size_t len); + +LIBETPAN_EXPORT +int mailimf_address_list_write_mem(MMAPString * f, int * col, + struct mailimf_address_list * addr_list); + +LIBETPAN_EXPORT +int mailimf_mailbox_list_write_mem(MMAPString * f, int * col, + struct mailimf_mailbox_list * mb_list); + +/* + mailimf_header_string_write_mem appends a header value and fold the header + if needed. + + @param f is the string + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +LIBETPAN_EXPORT +int mailimf_header_string_write_mem(MMAPString * f, int * col, + const char * str, size_t length); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/maildir/Makefile.am b/Sources/libetpan/low-level/maildir/Makefile.am new file mode 100644 index 00000000..2116f402 --- /dev/null +++ b/Sources/libetpan/low-level/maildir/Makefile.am @@ -0,0 +1,41 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +etpaninclude_HEADERS = \ + maildir.h maildir_types.h + +AM_CPPFLAGS = -I$(top_builddir)/include \ + -I$(top_srcdir)/src/data-types + +noinst_LTLIBRARIES = libmaildir.la + +libmaildir_la_SOURCES = \ + maildir.c diff --git a/Sources/libetpan/low-level/maildir/maildir.c b/Sources/libetpan/low-level/maildir/maildir.c new file mode 100644 index 00000000..ac6f752e --- /dev/null +++ b/Sources/libetpan/low-level/maildir/maildir.c @@ -0,0 +1,811 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildir.c,v 1.19 2008/02/17 13:13:29 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "maildir.h" + +#include +#include +#include +#ifdef WIN32 +# include "win_etpan.h" +#else +# include +# include +# include +#endif +#include +#include +#include +#include +#include + +#ifdef LIBETPAN_SYSTEM_BASENAME +#include +#endif + +/* + We suppose the maildir mailbox remains on one unique filesystem. +*/ + +struct maildir * maildir_new(const char * path) +{ + struct maildir * md; + + md = malloc(sizeof(* md)); + if (md == NULL) + goto err; + + md->mdir_counter = 0; + md->mdir_mtime_new = (time_t) -1; + md->mdir_mtime_cur = (time_t) -1; + + md->mdir_pid = getpid(); + gethostname(md->mdir_hostname, sizeof(md->mdir_hostname)); + strncpy(md->mdir_path, path, sizeof(md->mdir_path)); + md->mdir_path[PATH_MAX - 1] = '\0'; + + md->mdir_msg_list = carray_new(128); + if (md->mdir_msg_list == NULL) + goto free; + + md->mdir_msg_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYNONE); + if (md->mdir_msg_hash == NULL) + goto free_msg_list; + + return md; + + free_msg_list: + carray_free(md->mdir_msg_list); + free: + free(md); + err: + return NULL; +} + +static void maildir_flush(struct maildir * md, int msg_new); +static void msg_free(struct maildir_msg * msg); + +void maildir_free(struct maildir * md) +{ + maildir_flush(md, 0); + maildir_flush(md, 1); + chash_free(md->mdir_msg_hash); + carray_free(md->mdir_msg_list); + free(md); +} + +#define MAX_TRY_ALLOC 32 + +static char * maildir_get_new_message_filename(struct maildir * md, + char * tmp_file) +{ + char filename[PATH_MAX]; + char basename[PATH_MAX]; + int k; + time_t now; + int got_file; + int r; + + got_file = 0; + now = time(NULL); + k = 0; + while (k < MAX_TRY_ALLOC) { + snprintf(basename, sizeof(basename), "%lu.%u_%u.%s", + (unsigned long) now, md->mdir_pid, md->mdir_counter, md->mdir_hostname); + snprintf(filename, sizeof(filename), "%s/tmp/%s", + md->mdir_path, basename); + + if (link(tmp_file, filename) == 0) { + got_file = 1; + unlink(tmp_file); + } + else if (errno == EXDEV) { + unlink(tmp_file); + return NULL; + } + else if (errno == EPERM) { + r = rename(tmp_file, filename); + if (r < 0) { + unlink(tmp_file); + return NULL; + } + got_file = 1; + } + + if (got_file) { + char * dup_filename; + + dup_filename = strdup(filename); + if (dup_filename == NULL) { + unlink(filename); + return NULL; + } + + md->mdir_counter ++; + + return dup_filename; + } + + md->mdir_counter ++; + k ++; + } + + return NULL; +} + + +static void msg_free(struct maildir_msg * msg) +{ + free(msg->msg_uid); + free(msg->msg_filename); + free(msg); +} + +/* + msg_new() + + filename is given without path +*/ + +static struct maildir_msg * msg_new(char * filename, int new_msg) +{ + struct maildir_msg * msg; + char * p; + int flags; + size_t uid_len; + char * begin_uid; + + /* name of file : xxx-xxx_xxx-xxx:2,SRFT */ + + msg = malloc(sizeof(* msg)); + if (msg == NULL) + goto err; + + msg->msg_filename = strdup(filename); + if (msg->msg_filename == NULL) + goto free; + + begin_uid = filename; + + uid_len = strlen(begin_uid); + + flags = 0; + p = strstr(filename, ":2,"); + if (p != NULL) { + uid_len = p - begin_uid; + + p += 3; + + /* parse flags */ + while (* p != '\0') { + switch (* p) { + case 'S': + flags |= MAILDIR_FLAG_SEEN; + break; + case 'R': + flags |= MAILDIR_FLAG_REPLIED; + break; + case 'F': + flags |= MAILDIR_FLAG_FLAGGED; + break; + case 'T': + flags |= MAILDIR_FLAG_TRASHED; + break; + } + p ++; + } + } + + if (new_msg) + flags |= MAILDIR_FLAG_NEW; + + msg->msg_flags = flags; + + msg->msg_uid = malloc(uid_len + 1); + if (msg->msg_uid == NULL) + goto free_filename; + + strncpy(msg->msg_uid, begin_uid, uid_len); + msg->msg_uid[uid_len] = '\0'; + + return msg; + + free_filename: + free(msg->msg_filename); + free: + free(msg); + err: + return NULL; +} + +static void maildir_flush(struct maildir * md, int new_msg) +{ + unsigned int i; + + i = 0; + while (i < carray_count(md->mdir_msg_list)) { + struct maildir_msg * msg; + int delete; + + msg = carray_get(md->mdir_msg_list, i); + + if (new_msg) { + delete = 0; + if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) + delete = 1; + } + else { + delete = 1; + if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) + delete = 0; + } + + if (delete) { + chashdatum key; + + key.data = msg->msg_uid; + key.len = (unsigned int) strlen(msg->msg_uid); + chash_delete(md->mdir_msg_hash, &key, NULL); + + carray_delete(md->mdir_msg_list, i); + msg_free(msg); + } + else { + i ++; + } + } +} + +static int add_message(struct maildir * md, + char * filename, int is_new) +{ + struct maildir_msg * msg; + chashdatum key; + chashdatum value; + unsigned int i; + int res; + int r; + + msg = msg_new(filename, is_new); + if (msg == NULL) { + res = MAILDIR_ERROR_MEMORY; + goto err; + } + + r = carray_add(md->mdir_msg_list, msg, &i); + if (r < 0) { + res = MAILDIR_ERROR_MEMORY; + goto free_msg; + } + + key.data = msg->msg_uid; + key.len = (unsigned int) strlen(msg->msg_uid); + value.data = msg; + value.len = 0; + + r = chash_set(md->mdir_msg_hash, &key, &value, NULL); + if (r < 0) { + res = MAILDIR_ERROR_MEMORY; + goto delete; + } + + return MAILDIR_NO_ERROR; + + delete: + carray_delete(md->mdir_msg_list, i); + free_msg: + msg_free(msg); + err: + return res; +} + +static int add_directory(struct maildir * md, char * path, int is_new) +{ + DIR * d; + struct dirent * entry; + int res; + int r; +#if 0 + char filename[PATH_MAX]; +#endif + + d = opendir(path); + if (d == NULL) { + res = MAILDIR_ERROR_DIRECTORY; + goto err; + } + + while ((entry = readdir(d)) != NULL) { +#if 0 + struct stat stat_info; + + snprintf(filename, sizeof(filename), "%s/%s", path, entry->d_name); + + r = stat(filename, &stat_info); + if (r < 0) + continue; + + if (S_ISDIR(stat_info.st_mode)) + continue; +#endif + + if (entry->d_name[0] == '.') + continue; + + r = add_message(md, entry->d_name, is_new); + if (r != MAILDIR_NO_ERROR) { + /* ignore errors */ + } + } + + closedir(d); + + return MAILDIR_NO_ERROR; + + err: + return res; +} + +int maildir_update(struct maildir * md) +{ + struct stat stat_info; + char path_new[PATH_MAX]; + char path_cur[PATH_MAX]; + char path_maildirfolder[PATH_MAX]; + int r; + int res; + int changed; + + snprintf(path_new, sizeof(path_new), "%s/new", md->mdir_path); + snprintf(path_cur, sizeof(path_cur), "%s/cur", md->mdir_path); + + changed = 0; + + /* did new/ changed ? */ + + r = stat(path_new, &stat_info); + if (r < 0) { + res = MAILDIR_ERROR_DIRECTORY; + goto free; + } + + if (md->mdir_mtime_new != stat_info.st_mtime) { + md->mdir_mtime_new = stat_info.st_mtime; + changed = 1; + } + + /* did cur/ changed ? */ + + r = stat(path_cur, &stat_info); + if (r < 0) { + res = MAILDIR_ERROR_DIRECTORY; + goto free; + } + + if (md->mdir_mtime_cur != stat_info.st_mtime) { + md->mdir_mtime_cur = stat_info.st_mtime; + changed = 1; + } + + if (changed) { + maildir_flush(md, 0); + maildir_flush(md, 1); + + /* messages in new */ + r = add_directory(md, path_new, 1); + if (r != MAILDIR_NO_ERROR) { + res = r; + goto free; + } + + /* messages in cur */ + r = add_directory(md, path_cur, 0); + if (r != MAILDIR_NO_ERROR) { + res = r; + goto free; + } + } + + snprintf(path_maildirfolder, sizeof(path_maildirfolder), + "%s/maildirfolder", md->mdir_path); + + if (stat(path_maildirfolder, &stat_info) == -1) { + int fd; + + fd = creat(path_maildirfolder, S_IRUSR | S_IWUSR); + if (fd != -1) + close(fd); + } + + return MAILDIR_NO_ERROR; + + free: + maildir_flush(md, 0); + maildir_flush(md, 1); + md->mdir_mtime_cur = (time_t) -1; + md->mdir_mtime_new = (time_t) -1; + return res; +} + +#ifndef LIBETPAN_SYSTEM_BASENAME +static char * libetpan_basename(char * filename) +{ + char * next; + char * p; + + p = filename; + next = strchr(p, '/'); + + while (next != NULL) { + p = next; + next = strchr(p + 1, '/'); + } + + if (p == filename) + return filename; + else + return p + 1; +} +#else +#define libetpan_basename(a) basename(a) +#endif + +int maildir_message_add_uid(struct maildir * md, + const char * message, size_t size, + char * uid, size_t max_uid_len) +{ + char path_new[PATH_MAX]; + char tmpname[PATH_MAX]; + int fd; + int r; + char * mapping; + char * delivery_tmp_name; + char * delivery_tmp_basename; + char delivery_new_name[PATH_MAX]; + char * delivery_new_basename; + int res; + struct stat stat_info; + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = r; + goto err; + } + + /* write to tmp/ with a classic temporary file */ + + snprintf(tmpname, sizeof(tmpname), "%s/tmp/etpan-maildir-XXXXXX", + md->mdir_path); + fd = mkstemp(tmpname); + if (fd < 0) { + res = MAILDIR_ERROR_FILE; + goto err; + } + + r = ftruncate(fd, size); + if (r < 0) { + res = MAILDIR_ERROR_FILE; + goto close; + } + + mapping = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (mapping == (char *)MAP_FAILED) { + res = MAILDIR_ERROR_FILE; + goto close; + } + + memcpy(mapping, message, size); + + msync(mapping, size, MS_SYNC); + munmap(mapping, size); + + close(fd); + + /* write to tmp/ with maildir standard name */ + + delivery_tmp_name = maildir_get_new_message_filename(md, tmpname); + if (delivery_tmp_name == NULL) { + res = MAILDIR_ERROR_FILE; + goto unlink; + } + + /* write to new/ with maildir standard name */ + + strncpy(tmpname, delivery_tmp_name, sizeof(tmpname)); + tmpname[sizeof(tmpname) - 1] = '\0'; + + delivery_tmp_basename = libetpan_basename(tmpname); + + snprintf(delivery_new_name, sizeof(delivery_new_name), "%s/new/%s", + md->mdir_path, delivery_tmp_basename); + + r = link(delivery_tmp_name, delivery_new_name); + if (r == 0) { + unlink(delivery_tmp_name); + } + else if (errno == EXDEV) { + res = MAILDIR_ERROR_FOLDER; + goto unlink_tmp; + } + else if (errno == EPERM) { + r = rename(delivery_tmp_name, delivery_new_name); + if (r < 0) { + res = MAILDIR_ERROR_FILE; + goto unlink_tmp; + } + } + + snprintf(path_new, sizeof(path_new), "%s/new", md->mdir_path); + r = stat(path_new, &stat_info); + if (r < 0) { + unlink(delivery_new_name); + res = MAILDIR_ERROR_FILE; + goto unlink_tmp; + } + + md->mdir_mtime_new = stat_info.st_mtime; + + delivery_new_basename = libetpan_basename(delivery_new_name); + + r = add_message(md, delivery_new_basename, 1); + if (r != MAILDIR_NO_ERROR) { + unlink(delivery_new_name); + res = MAILDIR_ERROR_FILE; + goto unlink_tmp; + } + + if (uid != NULL) + strncpy(uid, delivery_new_basename, max_uid_len); + + free(delivery_tmp_name); + + return MAILDIR_NO_ERROR; + + unlink_tmp: + unlink(delivery_tmp_name); + free(delivery_tmp_name); + goto err; + close: + close(fd); + unlink: + unlink(tmpname); + err: + return res; +} + +int maildir_message_add(struct maildir * md, + const char * message, size_t size) +{ + return maildir_message_add_uid(md, message, size, + NULL, 0); +} + +int maildir_message_add_file_uid(struct maildir * md, int fd, + char * uid, size_t max_uid_len) +{ + char * message; + struct stat buf; + int r; + + if (fstat(fd, &buf) == -1) + return MAILDIR_ERROR_FILE; + + message = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (message == (char *)MAP_FAILED) + return MAILDIR_ERROR_FILE; + + r = maildir_message_add_uid(md, message, buf.st_size, uid, max_uid_len); + + munmap(message, buf.st_size); + + return r; +} + +int maildir_message_add_file(struct maildir * md, int fd) +{ + return maildir_message_add_file_uid(md, fd, + NULL, 0); +} + +char * maildir_message_get(struct maildir * md, const char * uid) +{ + chashdatum key; + chashdatum value; + char filename[PATH_MAX]; + char * dup_filename; + struct maildir_msg * msg; + char * dir; + int r; + + key.data = (void *) uid; + key.len = (unsigned int) strlen(uid); + r = chash_get(md->mdir_msg_hash, &key, &value); + if (r < 0) + return NULL; + + msg = value.data; + if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) + dir = "new"; + else + dir = "cur"; + + snprintf(filename, sizeof(filename), "%s/%s/%s", + md->mdir_path, dir, msg->msg_filename); + + dup_filename = strdup(filename); + if (dup_filename == NULL) + return NULL; + + return dup_filename; +} + +int maildir_message_remove(struct maildir * md, const char * uid) +{ + chashdatum key; + chashdatum value; + char filename[PATH_MAX]; + struct maildir_msg * msg; + char * dir; + int r; + int res; + + key.data = (void *) uid; + key.len = (unsigned int) strlen(uid); + r = chash_get(md->mdir_msg_hash, &key, &value); + if (r < 0) { + res = MAILDIR_ERROR_NOT_FOUND; + goto err; + } + + msg = value.data; + if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) + dir = "new"; + else + dir = "cur"; + + snprintf(filename, sizeof(filename), "%s/%s/%s", + md->mdir_path, dir, msg->msg_filename); + + r = unlink(filename); + if (r < 0) { + res = MAILDIR_ERROR_FILE; + goto err; + } + + return MAILDIR_NO_ERROR; + + err: + return res; +} + +int maildir_message_change_flags(struct maildir * md, + const char * uid, int new_flags) +{ + chashdatum key; + chashdatum value; + char filename[PATH_MAX]; + struct maildir_msg * msg; + char * dir; + int r; + char new_filename[PATH_MAX]; + char flag_str[5]; + size_t i; + int res; + char * dup_filename; + + key.data = (void *) uid; + key.len = (unsigned int) strlen(uid); + r = chash_get(md->mdir_msg_hash, &key, &value); + if (r < 0) { + res = MAILDIR_ERROR_NOT_FOUND; + goto err; + } + + msg = value.data; + if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) + dir = "new"; + else + dir = "cur"; + + snprintf(filename, sizeof(filename), "%s/%s/%s", + md->mdir_path, dir, msg->msg_filename); + + if ((new_flags & MAILDIR_FLAG_NEW) != 0) + dir = "new"; + else + dir = "cur"; + + i = 0; + if ((new_flags & MAILDIR_FLAG_SEEN) != 0) { + flag_str[i] = 'S'; + i ++; + } + if ((new_flags & MAILDIR_FLAG_REPLIED) != 0) { + flag_str[i] = 'R'; + i ++; + } + if ((new_flags & MAILDIR_FLAG_FLAGGED) != 0) { + flag_str[i] = 'F'; + i ++; + } + if ((new_flags & MAILDIR_FLAG_TRASHED) != 0) { + flag_str[i] = 'T'; + i ++; + } + flag_str[i] = 0; + + if (flag_str[0] == '\0') + snprintf(new_filename, sizeof(new_filename), "%s/%s/%s", + md->mdir_path, dir, msg->msg_uid); + else + snprintf(new_filename, sizeof(new_filename), "%s/%s/%s:2,%s", + md->mdir_path, dir, msg->msg_uid, flag_str); + + if (strcmp(filename, new_filename) == 0) + return MAILDIR_NO_ERROR; + + r = link(filename, new_filename); + if (r == 0) { + unlink(filename); + } + else if (errno == EXDEV) { + res = MAILDIR_ERROR_FOLDER; + goto err; + } + else if (errno == EPERM) { + r = rename(filename, new_filename); + if (r < 0) { + res = MAILDIR_ERROR_FOLDER; + goto err; + } + } + + dup_filename = strdup(libetpan_basename(new_filename)); + if (dup_filename != NULL) { + free(msg->msg_filename); + msg->msg_filename = dup_filename; + } + + msg->msg_flags = new_flags; + + return MAILDIR_NO_ERROR; + + err: + return res; +} diff --git a/Sources/libetpan/low-level/maildir/maildir.h b/Sources/libetpan/low-level/maildir/maildir.h new file mode 100644 index 00000000..a4aaeeda --- /dev/null +++ b/Sources/libetpan/low-level/maildir/maildir.h @@ -0,0 +1,67 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildir.h,v 1.5 2004/11/21 21:53:38 hoa Exp $ + */ + +#ifndef MAILDIR_H + +#define MAILDIR_H + +#include + +struct maildir * maildir_new(const char * path); + +void maildir_free(struct maildir * md); + +int maildir_update(struct maildir * md); + +int maildir_message_add_uid(struct maildir * md, + const char * message, size_t size, + char * uid, size_t max_uid_len); + +int maildir_message_add(struct maildir * md, + const char * message, size_t size); + +int maildir_message_add_file_uid(struct maildir * md, int fd, + char * uid, size_t max_uid_len); + +int maildir_message_add_file(struct maildir * md, int fd); + +char * maildir_message_get(struct maildir * md, const char * uid); + +int maildir_message_remove(struct maildir * md, const char * uid); + +int maildir_message_change_flags(struct maildir * md, + const char * uid, int new_flags); + +#endif diff --git a/Sources/libetpan/low-level/maildir/maildir_types.h b/Sources/libetpan/low-level/maildir/maildir_types.h new file mode 100644 index 00000000..16cd047a --- /dev/null +++ b/Sources/libetpan/low-level/maildir/maildir_types.h @@ -0,0 +1,93 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildir_types.h,v 1.9 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifndef MAILDIR_TYPES_H + +#define MAILDIR_TYPES_H + +#include +#include +#include +#include +#ifdef HAVE_INTTYPES_H +# include +#endif + +#include + +#define LIBETPAN_MAILDIR + +enum { + MAILDIR_NO_ERROR = 0, + MAILDIR_ERROR_CREATE, + MAILDIR_ERROR_DIRECTORY, + MAILDIR_ERROR_MEMORY, + MAILDIR_ERROR_FILE, + MAILDIR_ERROR_NOT_FOUND, + MAILDIR_ERROR_FOLDER +}; + +#define MAILDIR_FLAG_NEW (1 << 0) +#define MAILDIR_FLAG_SEEN (1 << 1) +#define MAILDIR_FLAG_REPLIED (1 << 2) +#define MAILDIR_FLAG_FLAGGED (1 << 3) +#define MAILDIR_FLAG_TRASHED (1 << 4) + +struct maildir_msg { + char * msg_uid; + char * msg_filename; + int msg_flags; +}; + +/* + work around for missing #define HOST_NAME_MAX in Linux +*/ + +#ifndef HOST_NAME_MAX +#define HOST_NAME_MAX 255 +#endif + +struct maildir { + pid_t mdir_pid; + char mdir_hostname[HOST_NAME_MAX]; + char mdir_path[PATH_MAX]; + uint32_t mdir_counter; + time_t mdir_mtime_new; + time_t mdir_mtime_cur; + carray * mdir_msg_list; + chash * mdir_msg_hash; +}; + +#endif diff --git a/Sources/libetpan/low-level/mbox/Makefile.am b/Sources/libetpan/low-level/mbox/Makefile.am new file mode 100644 index 00000000..a86667a5 --- /dev/null +++ b/Sources/libetpan/low-level/mbox/Makefile.am @@ -0,0 +1,44 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +EXTRA_DIST = TODO + +etpaninclude_HEADERS = \ + mailmbox.h mailmbox_types.h + +AM_CPPFLAGS = -I$(top_builddir)/include \ + -I$(top_srcdir)/src/data-types \ + -I$(top_srcdir)/src/low-level/imf + +noinst_LTLIBRARIES = libmbox.la + +libmbox_la_SOURCES = \ + mailmbox_parse.h mailmbox_parse.c mailmbox.c mailmbox_types.c diff --git a/Sources/libetpan/low-level/mbox/TODO b/Sources/libetpan/low-level/mbox/TODO new file mode 100644 index 00000000..e69de29b diff --git a/Sources/libetpan/low-level/mbox/mailmbox.c b/Sources/libetpan/low-level/mbox/mailmbox.c new file mode 100644 index 00000000..50a85267 --- /dev/null +++ b/Sources/libetpan/low-level/mbox/mailmbox.c @@ -0,0 +1,1566 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmbox.c,v 1.48 2010/04/05 14:21:36 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailmbox.h" + +#ifdef WIN32 +# include "win_etpan.h" +#else +# include +# include +# include +#endif +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "libetpan-config.h" + +#include "mmapstring.h" +#include "mailmbox_parse.h" +#include "maillock.h" + +#if 0 +#define CRLF_BADNESS +#endif + +/* + http://www.qmail.org/qmail-manual-html/man5/mbox.html + RFC 2076 +*/ + +/* used only in case the directory which contains the original file + is not writable */ +#define TMPDIR "/tmp" + +/* mbox is a file with a corresponding filename */ + +#define UID_HEADER "X-LibEtPan-UID:" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +int mailmbox_write_lock(struct mailmbox_folder * folder) +{ + int r; + + if (folder->mb_read_only) + return MAILMBOX_ERROR_READONLY; + + r = maillock_write_lock(folder->mb_filename, folder->mb_fd); + if (r == 0) + return MAILMBOX_NO_ERROR; + else + return MAILMBOX_ERROR_FILE; +} + +int mailmbox_write_unlock(struct mailmbox_folder * folder) +{ + int r; + + r = maillock_write_unlock(folder->mb_filename, folder->mb_fd); + if (r == 0) + return MAILMBOX_NO_ERROR; + else + return MAILMBOX_ERROR_FILE; +} + +int mailmbox_read_lock(struct mailmbox_folder * folder) +{ + int r; + + r = maillock_read_lock(folder->mb_filename, folder->mb_fd); + if (r == 0) + return MAILMBOX_NO_ERROR; + else + return MAILMBOX_ERROR_FILE; +} + +int mailmbox_read_unlock(struct mailmbox_folder * folder) +{ + int r; + + r = maillock_read_unlock(folder->mb_filename, folder->mb_fd); + if (r == 0) + return MAILMBOX_NO_ERROR; + else + return MAILMBOX_ERROR_FILE; +} + + +/* + map the file into memory. + the file must be locked. +*/ + +int mailmbox_map(struct mailmbox_folder * folder) +{ + char * str; + struct stat buf; + int res; + int r; + + r = stat(folder->mb_filename, &buf); + if (r < 0) { + res = MAILMBOX_ERROR_FILE; + goto err; + } + + if (folder->mb_read_only) + str = (char *) mmap(0, buf.st_size, PROT_READ, + MAP_PRIVATE, folder->mb_fd, 0); + else + str = (char *) mmap(0, buf.st_size, PROT_READ | PROT_WRITE, + MAP_SHARED, folder->mb_fd, 0); + if (str == (char *)MAP_FAILED) { + res = MAILMBOX_ERROR_FILE; + goto err; + } + + folder->mb_mapping = str; + folder->mb_mapping_size = buf.st_size; + + return MAILMBOX_NO_ERROR; + + err: + return res; +} + +/* + unmap the file +*/ + +void mailmbox_unmap(struct mailmbox_folder * folder) +{ + munmap(folder->mb_mapping, folder->mb_mapping_size); + folder->mb_mapping = NULL; + folder->mb_mapping_size = 0; +} + +void mailmbox_sync(struct mailmbox_folder * folder) +{ + msync(folder->mb_mapping, folder->mb_mapping_size, MS_SYNC); +} + +void mailmbox_timestamp(struct mailmbox_folder * folder) +{ + int r; + struct stat buf; + + r = stat(folder->mb_filename, &buf); + if (r < 0) + folder->mb_mtime = (time_t) -1; + else + folder->mb_mtime = buf.st_mtime; +} + +/* + open the file +*/ + +int mailmbox_open(struct mailmbox_folder * folder) +{ + int fd; + int read_only; + + fd = -1; + read_only = TRUE; + + if (!folder->mb_read_only) { + read_only = FALSE; + fd = open(folder->mb_filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + } + + if (folder->mb_read_only || (fd < 0)) { + read_only = TRUE; + fd = open(folder->mb_filename, O_RDONLY); + if (fd < 0) + return MAILMBOX_ERROR_FILE_NOT_FOUND; + } + + folder->mb_fd = fd; + folder->mb_read_only = read_only; + + return MAILMBOX_NO_ERROR; +} + +/* + close the file +*/ + +void mailmbox_close(struct mailmbox_folder * folder) +{ + close(folder->mb_fd); + folder->mb_fd = -1; +} + + +static int mailmbox_validate_lock(struct mailmbox_folder * folder, + int (* custom_lock)(struct mailmbox_folder *), + int (* custom_unlock)(struct mailmbox_folder *)) +{ + struct stat buf; + int res; + int r; + + r = stat(folder->mb_filename, &buf); + if (r < 0) { + buf.st_mtime = (time_t) -1; + } + + if ((buf.st_mtime != folder->mb_mtime) || + ((size_t) buf.st_size != folder->mb_mapping_size)) { + mailmbox_unmap(folder); + mailmbox_close(folder); + + r = mailmbox_open(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + r = custom_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + r = mailmbox_map(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err_unlock; + } + + r = mailmbox_parse(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err_unlock; + } + + folder->mb_mtime = buf.st_mtime; + + return MAILMBOX_NO_ERROR; + } + else { + r = custom_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + } + + return MAILMBOX_NO_ERROR; + + err_unlock: + custom_unlock(folder); + err: + return res; +} + + +int mailmbox_validate_write_lock(struct mailmbox_folder * folder) +{ + return mailmbox_validate_lock(folder, + mailmbox_write_lock, + mailmbox_write_unlock); +} + + +int mailmbox_validate_read_lock(struct mailmbox_folder * folder) +{ + return mailmbox_validate_lock(folder, + mailmbox_read_lock, + mailmbox_read_unlock); +} + + +/* ********************************************************************** */ +/* append messages */ + +#define MAX_FROM_LINE_SIZE 256 + +static inline size_t get_line(const char * line, size_t length, + const char ** pnext_line, size_t * pcount) +{ + size_t count; + + count = 0; + + while (1) { + if (length == 0) + break; + + if (* line == '\r') { + line ++; + + count ++; + length --; + + if (length > 0) { + if (* line == '\n') { + line ++; + + count ++; + length --; + + break; + } + } + } + else if (* line == '\n') { + line ++; + + count ++; + length --; + + break; + } + else { + line ++; + length --; + count ++; + } + } + + * pnext_line = line; + * pcount = count; + + return count; +} + +/* + TODO : should strip \r\n if any + see also in write_fixed_line +*/ + +static inline size_t get_fixed_line_size(const char * line, size_t length, + const char ** pnext_line, size_t * pcount, + size_t * pfixed_count) +{ + size_t count; + const char * next_line; + size_t fixed_count; + + if (!get_line(line, length, &next_line, &count)) + return 0; + + fixed_count = count; + if (count >= 5) { + if (line[0] == 'F') { + if (strncmp(line, "From ", 5) == 0) + fixed_count ++; + } + } + + * pnext_line = next_line; + * pcount = count; + * pfixed_count = fixed_count; + + return count; +} + +static size_t get_fixed_message_size(const char * message, size_t size, + uint32_t uid, int force_no_uid) +{ + size_t fixed_size; + size_t cur_token; + size_t left; + const char * next; + const char * cur; + int end; + int r; + uint32_t tmp_uid; + + cur_token = 0; + + fixed_size = 0; + + /* headers */ + + end = FALSE; + while (!end) { + size_t begin; + int ignore; + + ignore = FALSE; + begin = cur_token; + if (cur_token + strlen(UID_HEADER) <= size) { + if (message[cur_token] == 'X') { + if (strncasecmp(message + cur_token, UID_HEADER, + strlen(UID_HEADER)) == 0) { + ignore = TRUE; + } + } + } + + r = mailimf_ignore_field_parse(message, size, &cur_token); + switch (r) { + case MAILIMF_NO_ERROR: + if (!ignore) + fixed_size += cur_token - begin; + break; + case MAILIMF_ERROR_PARSE: + default: + end = TRUE; + break; + } + } + + if (!force_no_uid) { + /* UID header */ + +#ifdef CRLF_BADNESS + fixed_size += strlen(UID_HEADER " \r\n"); +#else + fixed_size += strlen(UID_HEADER " \n"); +#endif + + tmp_uid = uid; + while (tmp_uid >= 10) { + tmp_uid /= 10; + fixed_size ++; + } + fixed_size ++; + } + + /* body */ + + left = size - cur_token; + next = message + cur_token; + while (left > 0) { + size_t count; + size_t fixed_count; + + cur = next; + + if (!get_fixed_line_size(cur, left, &next, &count, &fixed_count)) + break; + + fixed_size += fixed_count; + left -= count; + } + + return fixed_size; +} + +static inline char * write_fixed_line(char * str, + const char * line, size_t length, + const char ** pnext_line, size_t * pcount) +{ + size_t count; + const char * next_line; + + if (!get_line(line, length, &next_line, &count)) + return str; + + if (count >= 5) { + if (line[0] == 'F') { + if (strncmp(line, "From ", 5) == 0) { + * str = '>'; + str ++; + } + } + } + + memcpy(str, line, count); + + * pnext_line = next_line; + * pcount = count; + str += count; + + return str; +} + +static char * write_fixed_message(char * str, + const char * message, size_t size, + uint32_t uid, int force_no_uid) +{ + size_t cur_token; + size_t left; + int end; + int r; + const char * cur_src; + size_t numlen; + + cur_token = 0; + + /* headers */ + + end = FALSE; + while (!end) { + size_t begin; + int ignore; + + ignore = FALSE; + begin = cur_token; + if (cur_token + strlen(UID_HEADER) <= size) { + if (message[cur_token] == 'X') { + if (strncasecmp(message + cur_token, UID_HEADER, + strlen(UID_HEADER)) == 0) { + ignore = TRUE; + } + } + } + + r = mailimf_ignore_field_parse(message, size, &cur_token); + switch (r) { + case MAILIMF_NO_ERROR: + if (!ignore) { + memcpy(str, message + begin, cur_token - begin); + str += cur_token - begin; + } + break; + case MAILIMF_ERROR_PARSE: + default: + end = TRUE; + break; + } + } + + if (!force_no_uid) { + /* UID header */ + + memcpy(str, UID_HEADER " ", strlen(UID_HEADER " ")); + str += strlen(UID_HEADER " "); +#ifdef CRLF_BADNESS + numlen = snprintf(str, 20, "%i\r\n", uid); +#else + numlen = snprintf(str, 20, "%i\n", uid); +#endif + str += numlen; + } + + /* body */ + + cur_src = message + cur_token; + left = size - cur_token; + while (left > 0) { + size_t count; + const char * next; + + count = 0; + next = NULL; + str = write_fixed_line(str, cur_src, left, &next, &count); + + cur_src = next; + left -= count; + } + + return str; +} + +#define DEFAULT_FROM_LINE "From - Wed Jun 30 21:49:08 1993\n" + +int +mailmbox_append_message_list_no_lock(struct mailmbox_folder * folder, + carray * append_tab) +{ + size_t extra_size; + int r; + char from_line[MAX_FROM_LINE_SIZE] = DEFAULT_FROM_LINE; + struct tm time_info; + time_t date; + int res; + size_t old_size; + char * str; + unsigned int i; + size_t from_size; + size_t left; + size_t crlf_count; + + if (folder->mb_read_only) { + res = MAILMBOX_ERROR_READONLY; + goto err; + } + + date = time(NULL); + from_size = strlen(DEFAULT_FROM_LINE); + if (localtime_r(&date, &time_info) != NULL) +#ifdef CRLF_BADNESS + from_size = strftime(from_line, MAX_FROM_LINE_SIZE, "From - %c\r\n", &time_info); +#else + from_size = strftime(from_line, MAX_FROM_LINE_SIZE, "From - %c\n", &time_info); +#endif + + extra_size = 0; + for(i = 0 ; i < carray_count(append_tab) ; i ++) { + struct mailmbox_append_info * info; + + info = carray_get(append_tab, i); + extra_size += from_size; + extra_size += get_fixed_message_size(info->ai_message, info->ai_size, + folder->mb_max_uid + i + 1, + folder->mb_no_uid); +#ifdef CRLF_BADNESS + extra_size += 2; /* CR LF */ +#else + extra_size += 1; /* CR LF */ +#endif + + info->ai_uid = folder->mb_max_uid + i + 1; + } + + left = folder->mb_mapping_size; + crlf_count = 0; + while (left >= 1) { + if (folder->mb_mapping[left - 1] == '\n') { + crlf_count ++; + left --; + } +#ifdef CRLF_BADNESS + else if (folder->mb_mapping[left - 1] == '\r') { + left --; + } +#endif + else + break; + + if (crlf_count == 2) + break; + } + + old_size = folder->mb_mapping_size; + mailmbox_unmap(folder); + + if (old_size != 0) { + if (crlf_count != 2) +#ifdef CRLF_BADNESS + extra_size += (2 - crlf_count) * 2; +#else + /* Need the number of LFs, not CRLFs */ + extra_size += (2 - crlf_count) * 1; +#endif + } + + r = ftruncate(folder->mb_fd, extra_size + old_size); + if (r < 0) { + mailmbox_map(folder); + res = MAILMBOX_ERROR_FILE; + goto err; + } + + r = mailmbox_map(folder); + if (r < 0) { + r = ftruncate(folder->mb_fd, old_size); + return MAILMBOX_ERROR_FILE; + } + + str = folder->mb_mapping + old_size; + + if (old_size != 0) { + for(i = 0 ; i < 2 - crlf_count ; i ++) { +#ifdef CRLF_BADNESS + * str = '\r'; + str ++; +#endif + * str = '\n'; + str ++; + } + } + + for(i = 0 ; i < carray_count(append_tab) ; i ++) { + struct mailmbox_append_info * info; + + info = carray_get(append_tab, i); + + memcpy(str, from_line, from_size); + + str += strlen(from_line); + + str = write_fixed_message(str, info->ai_message, info->ai_size, + folder->mb_max_uid + i + 1, + folder->mb_no_uid); + +#ifdef CRLF_BADNESS + * str = '\r'; + str ++; +#endif + * str = '\n'; + str ++; + } + + folder->mb_max_uid += carray_count(append_tab); + + return MAILMBOX_NO_ERROR; + + err: + return res; +} + +int +mailmbox_append_message_list(struct mailmbox_folder * folder, + carray * append_tab) +{ + int r; + int res; + size_t cur_token; + + r = mailmbox_validate_write_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + r = mailmbox_expunge_no_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto unlock; + } + + cur_token = folder->mb_mapping_size; + + r = mailmbox_append_message_list_no_lock(folder, append_tab); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto unlock; + } + + mailmbox_sync(folder); + + r = mailmbox_parse_additionnal(folder, &cur_token); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto unlock; + } + + mailmbox_timestamp(folder); + + mailmbox_write_unlock(folder); + + return MAILMBOX_NO_ERROR; + + unlock: + mailmbox_write_unlock(folder); + err: + return res; +} + +int +mailmbox_append_message_uid(struct mailmbox_folder * folder, + const char * data, size_t len, unsigned int * puid) +{ + carray * tab; + struct mailmbox_append_info * append_info; + int res; + int r; + + tab = carray_new(1); + if (tab == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto err; + } + + append_info = mailmbox_append_info_new(data, len); + if (append_info == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto free_list; + } + + r = carray_add(tab, append_info, NULL); + if (r < 0) { + res = MAILMBOX_ERROR_MEMORY; + goto free_append_info; + } + + r = mailmbox_append_message_list(folder, tab); + + if (puid != NULL) + * puid = append_info->ai_uid; + + mailmbox_append_info_free(append_info); + carray_free(tab); + + return r; + + free_append_info: + mailmbox_append_info_free(append_info); + free_list: + carray_free(tab); + err: + return res; +} + +int +mailmbox_append_message(struct mailmbox_folder * folder, + const char * data, size_t len) +{ + return mailmbox_append_message_uid(folder, data, len, NULL); +} + +/* ********************************************************************** */ + +int mailmbox_fetch_msg_no_lock(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len) +{ + struct mailmbox_msg_info * info; + int res; + chashdatum key; + chashdatum data; + int r; + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAILMBOX_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = data.data; + + if (info->msg_deleted) { + res = MAILMBOX_ERROR_MSG_NOT_FOUND; + goto err; + } + + * result = folder->mb_mapping + info->msg_headers; + * result_len = info->msg_size - info->msg_start_len; + + return MAILMBOX_NO_ERROR; + + err: + return res; +} + +int mailmbox_fetch_msg_headers_no_lock(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len) +{ + struct mailmbox_msg_info * info; + int res; + chashdatum key; + chashdatum data; + int r; + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAILMBOX_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = data.data; + + if (info->msg_deleted) { + res = MAILMBOX_ERROR_MSG_NOT_FOUND; + goto err; + } + + * result = folder->mb_mapping + info->msg_headers; + * result_len = info->msg_headers_len; + + return MAILMBOX_NO_ERROR; + + err: + return res; +} + +int mailmbox_fetch_msg(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len) +{ + MMAPString * mmapstr; + int res; + char * data; + size_t len; + int r; + size_t fixed_size; + char * end; + + r = mailmbox_validate_read_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + r = mailmbox_fetch_msg_no_lock(folder, num, &data, &len); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto unlock; + } + + /* size with no uid */ + fixed_size = get_fixed_message_size(data, len, 0, 1 /* force no uid */); + +#if 0 + mmapstr = mmap_string_new_len(data, fixed_size); + if (mmapstr == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto unlock; + } +#endif + mmapstr = mmap_string_sized_new(fixed_size); + if (mmapstr == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto unlock; + } + + end = write_fixed_message(mmapstr->str, data, len, 0, 1 /* force no uid */); + * end = '\0'; + mmapstr->len = fixed_size; + + r = mmap_string_ref(mmapstr); + if (r < 0) { + mmap_string_free(mmapstr); + res = MAILMBOX_ERROR_MEMORY; + goto unlock; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + mailmbox_read_unlock(folder); + + return MAILMBOX_NO_ERROR; + + unlock: + mailmbox_read_unlock(folder); + err: + return res; +} + +int mailmbox_fetch_msg_headers(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len) +{ + MMAPString * mmapstr; + int res; + char * data; + size_t len; + int r; + size_t fixed_size; + char * end; + + r = mailmbox_validate_read_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + r = mailmbox_fetch_msg_headers_no_lock(folder, num, &data, &len); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto unlock; + } + +#if 0 + mmapstr = mmap_string_new_len(data, len); + if (mmapstr == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto unlock; + } +#endif + /* size with no uid */ + fixed_size = get_fixed_message_size(data, len, 0, 1 /* force no uid */); + + mmapstr = mmap_string_sized_new(fixed_size); + if (mmapstr == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto unlock; + } + + end = write_fixed_message(mmapstr->str, data, len, 0, 1 /* force no uid */); + * end = '\0'; + mmapstr->len = fixed_size; + + r = mmap_string_ref(mmapstr); + if (r < 0) { + mmap_string_free(mmapstr); + res = MAILMBOX_ERROR_MEMORY; + goto unlock; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + mailmbox_read_unlock(folder); + + return MAILMBOX_NO_ERROR; + + unlock: + mailmbox_read_unlock(folder); + err: + return res; +} + +void mailmbox_fetch_result_free(char * msg) +{ + mmap_string_unref(msg); +} + + +int mailmbox_copy_msg_list(struct mailmbox_folder * dest_folder, + struct mailmbox_folder * src_folder, + carray * tab) +{ + int r; + int res; + carray * append_tab; + unsigned int i; + + r = mailmbox_validate_read_lock(src_folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + append_tab = carray_new(carray_count(tab)); + if (append_tab == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto src_unlock; + } + + for(i = 0 ; i < carray_count(tab) ; i ++) { + struct mailmbox_append_info * append_info; + char * data; + size_t len; + uint32_t uid; + + uid = * ((uint32_t *) carray_get(tab, i)); + + r = mailmbox_fetch_msg_no_lock(src_folder, uid, &data, &len); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto free_list; + } + + append_info = mailmbox_append_info_new(data, len); + if (append_info == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto free_list; + } + + r = carray_add(append_tab, append_info, NULL); + if (r < 0) { + mailmbox_append_info_free(append_info); + res = MAILMBOX_ERROR_MEMORY; + goto free_list; + } + } + + r = mailmbox_append_message_list(dest_folder, append_tab); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto src_unlock; + } + + for(i = 0 ; i < carray_count(append_tab) ; i ++) { + struct mailmbox_append_info * append_info; + + append_info = carray_get(append_tab, i); + mailmbox_append_info_free(append_info); + } + carray_free(append_tab); + + mailmbox_read_unlock(src_folder); + + return MAILMBOX_NO_ERROR; + + free_list: + for(i = 0 ; i < carray_count(append_tab) ; i ++) { + struct mailmbox_append_info * append_info; + + append_info = carray_get(append_tab, i); + mailmbox_append_info_free(append_info); + } + carray_free(append_tab); + src_unlock: + mailmbox_read_unlock(src_folder); + err: + return res; +} + +int mailmbox_copy_msg(struct mailmbox_folder * dest_folder, + struct mailmbox_folder * src_folder, + uint32_t uid) +{ + carray * tab; + int res; + uint32_t * puid; + int r; + + tab = carray_new(1); + if (tab == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto err; + } + + puid = malloc(sizeof(* puid)); + if (puid == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto free_array; + } + * puid = uid; + + r = mailmbox_copy_msg_list(dest_folder, src_folder, tab); + res = r; + + free(puid); + free_array: + carray_free(tab); + err: + return res; +} + +static int mailmbox_expunge_to_file_no_lock(char * dest_filename, int dest_fd, + struct mailmbox_folder * folder, + size_t * result_size) +{ + int r; + int res; + size_t cur_offset; + char * dest; + size_t size; + unsigned int i; + + size = 0; + for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) { + struct mailmbox_msg_info * info; + + info = carray_get(folder->mb_tab, i); + + if (!info->msg_deleted) { + size += info->msg_size + info->msg_padding; + + if (!folder->mb_no_uid) { + if (!info->msg_written_uid) { + uint32_t uid; + +#ifdef CRLF_BADNESS + size += strlen(UID_HEADER " \r\n"); +#else + size += strlen(UID_HEADER " \n"); +#endif + + uid = info->msg_uid; + while (uid >= 10) { + uid /= 10; + size ++; + } + size ++; + } + } + } + } + + r = ftruncate(dest_fd, size); + if (r < 0) { + res = MAILMBOX_ERROR_FILE; + goto err; + } + + dest = (char *) mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, dest_fd, 0); + if (dest == (char *)MAP_FAILED) { + res = MAILMBOX_ERROR_FILE; + goto err; + } + + cur_offset = 0; + for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) { + struct mailmbox_msg_info * info; + + info = carray_get(folder->mb_tab, i); + + if (!info->msg_deleted) { + memcpy(dest + cur_offset, folder->mb_mapping + info->msg_start, + info->msg_headers_len + info->msg_start_len); + cur_offset += info->msg_headers_len + info->msg_start_len; + + if (!folder->mb_no_uid) { + if (!info->msg_written_uid) { + size_t numlen; + + memcpy(dest + cur_offset, UID_HEADER " ", strlen(UID_HEADER " ")); + cur_offset += strlen(UID_HEADER " "); +#ifdef CRLF_BADNESS + numlen = snprintf(dest + cur_offset, size - cur_offset, + "%lu\r\n", (unsigned long) info->msg_uid); +#else + numlen = snprintf(dest + cur_offset, size - cur_offset, + "%lu\n", (unsigned long) info->msg_uid); +#endif + cur_offset += numlen; + } + } + + memcpy(dest + cur_offset, + folder->mb_mapping + info->msg_headers + info->msg_headers_len, + info->msg_size - (info->msg_start_len + info->msg_headers_len) + + info->msg_padding); + + cur_offset += info->msg_size - + (info->msg_start_len + info->msg_headers_len) + + info->msg_padding; + } + } + fflush(stdout); + + msync(dest, size, MS_SYNC); + munmap(dest, size); + + * result_size = size; + + return MAILMBOX_NO_ERROR; + + err: + return res; +} + +static int copy_to_old_file(char * source_filename, + char * destination_filename, size_t size) +{ + int source_fd; + int dest_fd; + char * source; + char * dest; + int res; + int r; + + source_fd = open(source_filename, O_RDONLY); + if (source_fd < 0) { + res = MAILMBOX_ERROR_FILE; + goto err; + } + + source = (char *) mmap(0, size, PROT_READ, MAP_PRIVATE, source_fd, 0); + if (source == (char *)MAP_FAILED) { + res = MAILMBOX_ERROR_FILE; + goto close_source; + } + + dest_fd = open(destination_filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (dest_fd < 0) { + res = MAILMBOX_ERROR_FILE; + goto unmap_source; + } + + r = ftruncate(dest_fd, size); + if (r < 0) { + res = MAILMBOX_ERROR_FILE; + goto close_dest; + } + + dest = (char *) mmap(0, size, PROT_READ | PROT_WRITE, + MAP_SHARED, dest_fd, 0); + if (dest == (char *)MAP_FAILED) { + res = MAILMBOX_ERROR_FILE; + goto close_dest; + } + + memcpy(dest, source, size); + + munmap(dest, size); + close(dest_fd); + munmap(source, size); + close(source_fd); + + return MAILMBOX_NO_ERROR; + + close_dest: + close(dest_fd); + unmap_source: + munmap(source, size); + close_source: + close(source_fd); + err: + return res; +} + +int mailmbox_expunge_no_lock(struct mailmbox_folder * folder) +{ + char tmp_file[PATH_MAX]; + int r; + int res; + int dest_fd; + size_t size; + mode_t old_mask; + + if (folder->mb_read_only) + return MAILMBOX_ERROR_READONLY; + + if (((folder->mb_written_uid >= folder->mb_max_uid) || folder->mb_no_uid) && + (!folder->mb_changed)) { + /* no need to expunge */ + return MAILMBOX_NO_ERROR; + } + + snprintf(tmp_file, PATH_MAX, "%sXXXXXX", folder->mb_filename); + old_mask = umask(0077); + dest_fd = mkstemp(tmp_file); + umask(old_mask); + + if (dest_fd < 0) { + /* fallback to tmp dir */ + + snprintf(tmp_file, PATH_MAX, TMPDIR "/etpan-unsafe-XXXXXX"); + + old_mask = umask(0077); + dest_fd = mkstemp(tmp_file); + umask(old_mask); + + if (dest_fd < 0) { + res = MAILMBOX_ERROR_FILE; + goto err; + } + } + + r = mailmbox_expunge_to_file_no_lock(tmp_file, dest_fd, + folder, &size); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto unlink; + } + + close(dest_fd); + + r = rename(tmp_file, folder->mb_filename); + if (r < 0) { + mailmbox_unmap(folder); + mailmbox_close(folder); + + /* fallback on copy to old file */ + + r = copy_to_old_file(tmp_file, folder->mb_filename, size); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + unlink(tmp_file); + } + else { + mailmbox_unmap(folder); + mailmbox_close(folder); + } + + r = mailmbox_open(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + r = mailmbox_map(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + r = mailmbox_parse(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + mailmbox_timestamp(folder); + + folder->mb_changed = FALSE; + folder->mb_deleted_count = 0; + + return MAILMBOX_NO_ERROR; + + unlink: + close(dest_fd); + unlink(tmp_file); + err: + return res; +} + +int mailmbox_expunge(struct mailmbox_folder * folder) +{ + int r; + int res; + + r = mailmbox_validate_write_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + r = mailmbox_expunge_no_lock(folder); + res = r; + + mailmbox_write_unlock(folder); + err: + return res; +} + +int mailmbox_delete_msg(struct mailmbox_folder * folder, uint32_t uid) +{ + struct mailmbox_msg_info * info; + int res; + chashdatum key; + chashdatum data; + int r; + + if (folder->mb_read_only) { + res = MAILMBOX_ERROR_READONLY; + goto err; + } + + key.data = &uid; + key.len = sizeof(uid); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAILMBOX_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = data.data; + + if (info->msg_deleted) { + res = MAILMBOX_ERROR_MSG_NOT_FOUND; + goto err; + } + + info->msg_deleted = TRUE; + folder->mb_changed = TRUE; + folder->mb_deleted_count ++; + + return MAILMBOX_NO_ERROR; + + err: + return res; +} + + +/* + INIT of MBOX + + - open file + - map the file + + - lock the file + + - parse memory + + - unlock the file +*/ + +int mailmbox_init(const char * filename, + int force_readonly, + int force_no_uid, + uint32_t default_written_uid, + struct mailmbox_folder ** result_folder) +{ + struct mailmbox_folder * folder; + int r; + int res; + + folder = mailmbox_folder_new(filename); + if (folder == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto err; + } + folder->mb_no_uid = force_no_uid; + folder->mb_read_only = force_readonly; + folder->mb_written_uid = default_written_uid; + + folder->mb_changed = FALSE; + folder->mb_deleted_count = 0; + + r = mailmbox_open(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto free; + } + + r = mailmbox_map(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto close; + } + + r = mailmbox_validate_read_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto unmap; + } + + mailmbox_read_unlock(folder); + + * result_folder = folder; + + return MAILMBOX_NO_ERROR; + + unmap: + mailmbox_unmap(folder); + close: + mailmbox_close(folder); + free: + mailmbox_folder_free(folder); + err: + return res; +} + + +/* + when MBOX is DONE + + - check for changes + + - unmap the file + - close file +*/ + +void mailmbox_done(struct mailmbox_folder * folder) +{ + if (!folder->mb_read_only) + mailmbox_expunge(folder); + + mailmbox_unmap(folder); + mailmbox_close(folder); + + mailmbox_folder_free(folder); +} diff --git a/Sources/libetpan/low-level/mbox/mailmbox.h b/Sources/libetpan/low-level/mbox/mailmbox.h new file mode 100644 index 00000000..7b52da72 --- /dev/null +++ b/Sources/libetpan/low-level/mbox/mailmbox.h @@ -0,0 +1,144 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmbox.h,v 1.19 2004/11/21 21:53:38 hoa Exp $ + */ + +#ifndef MAILMBOX_H + +#define MAILMBOX_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +int +mailmbox_append_message_list(struct mailmbox_folder * folder, + carray * append_tab); + +int +mailmbox_append_message(struct mailmbox_folder * folder, + const char * data, size_t len); + +int +mailmbox_append_message_uid(struct mailmbox_folder * folder, + const char * data, size_t len, unsigned int * puid); + +int mailmbox_fetch_msg(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len); + +int mailmbox_fetch_msg_headers(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len); + +void mailmbox_fetch_result_free(char * msg); + +int mailmbox_copy_msg_list(struct mailmbox_folder * dest_folder, + struct mailmbox_folder * src_folder, + carray * tab); + +int mailmbox_copy_msg(struct mailmbox_folder * dest_folder, + struct mailmbox_folder * src_folder, + uint32_t uid); + +int mailmbox_expunge(struct mailmbox_folder * folder); + +int mailmbox_delete_msg(struct mailmbox_folder * folder, uint32_t uid); + +int mailmbox_init(const char * filename, + int force_readonly, + int force_no_uid, + uint32_t default_written_uid, + struct mailmbox_folder ** result_folder); + +void mailmbox_done(struct mailmbox_folder * folder); + +/* low-level access primitives */ + +int mailmbox_write_lock(struct mailmbox_folder * folder); + +int mailmbox_write_unlock(struct mailmbox_folder * folder); + +int mailmbox_read_lock(struct mailmbox_folder * folder); + +int mailmbox_read_unlock(struct mailmbox_folder * folder); + + +/* memory map */ + +int mailmbox_map(struct mailmbox_folder * folder); + +void mailmbox_unmap(struct mailmbox_folder * folder); + +void mailmbox_sync(struct mailmbox_folder * folder); + + +/* open & close file */ + +int mailmbox_open(struct mailmbox_folder * folder); + +void mailmbox_close(struct mailmbox_folder * folder); + + +/* validate cache */ + +int mailmbox_validate_write_lock(struct mailmbox_folder * folder); + +int mailmbox_validate_read_lock(struct mailmbox_folder * folder); + + +/* fetch message */ + +int mailmbox_fetch_msg_no_lock(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len); + +int mailmbox_fetch_msg_headers_no_lock(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len); + +/* append message */ + +int +mailmbox_append_message_list_no_lock(struct mailmbox_folder * folder, + carray * append_tab); + +int mailmbox_expunge_no_lock(struct mailmbox_folder * folder); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/mbox/mailmbox_parse.c b/Sources/libetpan/low-level/mbox/mailmbox_parse.c new file mode 100644 index 00000000..7e0972b3 --- /dev/null +++ b/Sources/libetpan/low-level/mbox/mailmbox_parse.c @@ -0,0 +1,623 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmbox_parse.c,v 1.16 2008/02/20 22:15:52 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailmbox_parse.h" + +#include "mailmbox.h" + +#include +#include +#include +#include + +#define UID_HEADER "X-LibEtPan-UID:" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +enum { + UNSTRUCTURED_START, + UNSTRUCTURED_CR, + UNSTRUCTURED_LF, + UNSTRUCTURED_WSP, + UNSTRUCTURED_OUT +}; + +static inline int +mailmbox_fields_parse(char * str, size_t length, + size_t * indx, + uint32_t * puid, + size_t * phlen) +{ + size_t cur_token; + int r; + size_t hlen; + uint32_t uid; + int end; + + cur_token = * indx; + + end = FALSE; + uid = 0; + while (!end) { + size_t begin; + + begin = cur_token; + + r = mailimf_ignore_field_parse(str, length, &cur_token); + switch (r) { + case MAILIMF_NO_ERROR: + if (str[begin] == 'X') { + + if (strncasecmp(str + begin, UID_HEADER, strlen(UID_HEADER)) == 0) { + begin += strlen(UID_HEADER); + + while (str[begin] == ' ') + begin ++; + + uid = (uint32_t) strtoul(str + begin, NULL, 10); + } + } + + break; + case MAILIMF_ERROR_PARSE: + default: + end = TRUE; + break; + } + } + + hlen = cur_token - * indx; + + * phlen = hlen; + * puid = uid; + * indx = cur_token; + + return MAILMBOX_NO_ERROR; +} + +enum { + IN_MAIL, + FIRST_CR, + FIRST_LF, + SECOND_CR, + SECOND_LF, + PARSING_F, + PARSING_R, + PARSING_O, + PARSING_M, + OUT_MAIL +}; + + + + +static inline int +mailmbox_single_parse(char * str, size_t length, + size_t * indx, + size_t * pstart, + size_t * pstart_len, + size_t * pheaders, + size_t * pheaders_len, + size_t * pbody, + size_t * pbody_len, + size_t * psize, + size_t * ppadding, + uint32_t * puid) +{ + size_t cur_token; + size_t start; + size_t start_len; + size_t headers; + size_t headers_len; + size_t body; + size_t end; + size_t next; + size_t message_length; + uint32_t uid; + int r; +#if 0 + int in_mail_data; +#endif +#if 0 + size_t begin; +#endif + + int state; + + cur_token = * indx; + + if (cur_token >= length) + return MAILMBOX_ERROR_PARSE; + + start = cur_token; + start_len = 0; + headers = cur_token; + + if (cur_token + 5 < length) { + if (strncmp(str + cur_token, "From ", 5) == 0) { + cur_token += 5; + while (str[cur_token] != '\n') { + cur_token ++; + if (cur_token >= length) + break; + } + if (cur_token < length) { + cur_token ++; + headers = cur_token; + start_len = headers - start; + } + } + } + + next = length; + + r = mailmbox_fields_parse(str, length, &cur_token, + &uid, &headers_len); + if (r != MAILMBOX_NO_ERROR) + return r; + + /* save position */ +#if 0 + begin = cur_token; +#endif + + mailimf_crlf_parse(str, length, &cur_token); + +#if 0 + if (str[cur_token] == 'F') { + printf("start !\n"); + printf("%50.50s\n", str + cur_token); + getchar(); + } +#endif + + body = cur_token; + + /* restore position */ + /* cur_token = begin; */ + + state = FIRST_LF; + + end = length; + +#if 0 + in_mail_data = 0; +#endif + while (state != OUT_MAIL) { + + if (cur_token >= length) { + if (state == IN_MAIL) + end = length; + next = length; + break; + } + + switch(state) { + case IN_MAIL: + switch(str[cur_token]) { + case '\r': + state = FIRST_CR; + break; + case '\n': + state = FIRST_LF; + break; + case 'F': + if (cur_token == body) { + end = cur_token; + next = cur_token; + state = PARSING_F; + } + break; +#if 0 + default: + in_mail_data = 1; + break; +#endif + } + break; + + case FIRST_CR: + end = cur_token; + switch(str[cur_token]) { + case '\r': + state = SECOND_CR; + break; + case '\n': + state = FIRST_LF; + break; + default: + state = IN_MAIL; +#if 0 + in_mail_data = 1; +#endif + break; + } + break; + + case FIRST_LF: + end = cur_token; + switch(str[cur_token]) { + case '\r': + state = SECOND_CR; + break; + case '\n': + state = SECOND_LF; + break; + default: + state = IN_MAIL; +#if 0 + in_mail_data = 1; +#endif + break; + } + break; + + case SECOND_CR: + switch(str[cur_token]) { + case '\r': + end = cur_token; + break; + case '\n': + state = SECOND_LF; + break; + case 'F': + next = cur_token; + state = PARSING_F; + break; + default: + state = IN_MAIL; +#if 0 + in_mail_data = 1; +#endif + break; + } + break; + + case SECOND_LF: + switch(str[cur_token]) { + case '\r': + state = SECOND_CR; + break; + case '\n': + end = cur_token; + break; + case 'F': + next = cur_token; + state = PARSING_F; + break; + default: + state = IN_MAIL; +#if 0 + in_mail_data = 1; +#endif + break; + } + break; + + case PARSING_F: + switch(str[cur_token]) { + case 'r': + state = PARSING_R; + break; + default: + state = IN_MAIL; +#if 0 + in_mail_data = 1; +#endif + break; + } + break; + + case PARSING_R: + switch(str[cur_token]) { + case 'o': + state = PARSING_O; + break; + default: + state = IN_MAIL; +#if 0 + in_mail_data = 1; +#endif + break; + } + break; + + case PARSING_O: + switch(str[cur_token]) { + case 'm': + state = PARSING_M; + break; + default: + state = IN_MAIL; +#if 0 + in_mail_data = 1; +#endif + break; + } + break; + + case PARSING_M: + switch(str[cur_token]) { + case ' ': + state = OUT_MAIL; + break; + default: + state = IN_MAIL; + break; + } + break; + } + + cur_token ++; + } + + message_length = end - start; + + * pstart = start; + * pstart_len = start_len; + * pheaders = headers; + * pheaders_len = headers_len; + * pbody = body; + * pbody_len = end - body; + * psize = message_length; + * ppadding = next - end; + * puid = uid; + + * indx = next; + + return MAILMBOX_NO_ERROR; +} + + +int +mailmbox_parse_additionnal(struct mailmbox_folder * folder, + size_t * indx) +{ + size_t cur_token; + + size_t start; + size_t start_len; + size_t headers; + size_t headers_len; + size_t body; + size_t body_len; + size_t size; + size_t padding; + uint32_t uid; + int r; + int res; + + uint32_t max_uid; + uint32_t first_index; + unsigned int i; + unsigned int j; + + cur_token = * indx; + + /* remove temporary UID that we will parse */ + + first_index = carray_count(folder->mb_tab); + + for(i = 0 ; i < carray_count(folder->mb_tab) ; i++) { + struct mailmbox_msg_info * info; + + info = carray_get(folder->mb_tab, i); + + if (info->msg_start < cur_token) { + continue; + } + + if (!info->msg_written_uid) { + chashdatum key; + + key.data = &info->msg_uid; + key.len = sizeof(info->msg_uid); + + chash_delete(folder->mb_hash, &key, NULL); + carray_delete_fast(folder->mb_tab, i); + mailmbox_msg_info_free(info); + if (i < first_index) + first_index = i; + } + } + + /* make a sequence in the table */ + + max_uid = folder->mb_written_uid; + + i = 0; + j = 0; + while (i < carray_count(folder->mb_tab)) { + struct mailmbox_msg_info * info; + + info = carray_get(folder->mb_tab, i); + if (info != NULL) { + carray_set(folder->mb_tab, j, info); + + if (info->msg_uid > max_uid) + max_uid = info->msg_uid; + + info->msg_index = j; + j ++; + } + i ++; + } + carray_set_size(folder->mb_tab, j); + + /* parse content */ + + first_index = j; + + while (1) { + struct mailmbox_msg_info * info; + chashdatum key; + chashdatum data; + + r = mailmbox_single_parse(folder->mb_mapping, folder->mb_mapping_size, + &cur_token, + &start, &start_len, + &headers, &headers_len, + &body, &body_len, + &size, &padding, &uid); + if (r != MAILMBOX_NO_ERROR) { + if (r == MAILMBOX_ERROR_PARSE) + break; + else { + res = r; + goto err; + } + } + + key.data = &uid; + key.len = sizeof(uid); + + r = chash_get(folder->mb_hash, &key, &data); + if (r == 0) { + info = data.data; + + if (!info->msg_written_uid) { + /* some new mail has been written and override an + existing temporary UID */ + + chash_delete(folder->mb_hash, &key, NULL); + info->msg_uid = 0; + + if (info->msg_index < first_index) + first_index = info->msg_index; + } + else + uid = 0; + } + + if (uid > max_uid) + max_uid = uid; + + r = mailmbox_msg_info_update(folder, + start, start_len, headers, headers_len, + body, body_len, size, padding, uid); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + } + + * indx = cur_token; + + folder->mb_written_uid = max_uid; + + /* attribute uid */ + + for(i = first_index ; i < carray_count(folder->mb_tab) ; i ++) { + struct mailmbox_msg_info * info; + chashdatum key; + chashdatum data; + + info = carray_get(folder->mb_tab, i); + + if (info->msg_uid != 0) { + continue; + } + + max_uid ++; + info->msg_uid = max_uid; + + key.data = &info->msg_uid; + key.len = sizeof(info->msg_uid); + data.data = info; + data.len = 0; + + r = chash_set(folder->mb_hash, &key, &data, NULL); + if (r < 0) { + res = MAILMBOX_ERROR_MEMORY; + goto err; + } + } + + folder->mb_max_uid = max_uid; + + return MAILMBOX_NO_ERROR; + + err: + return res; +} + +static void flush_uid(struct mailmbox_folder * folder) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(folder->mb_tab) ; i++) { + struct mailmbox_msg_info * info; + + info = carray_get(folder->mb_tab, i); + if (info != NULL) + mailmbox_msg_info_free(info); + } + + chash_clear(folder->mb_hash); + carray_set_size(folder->mb_tab, 0); +} + +int mailmbox_parse(struct mailmbox_folder * folder) +{ + int r; + int res; + size_t cur_token; + + flush_uid(folder); + + cur_token = 0; + + r = mailmbox_parse_additionnal(folder, &cur_token); + + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + return MAILMBOX_NO_ERROR; + + err: + return res; +} diff --git a/Sources/libetpan/low-level/mbox/mailmbox_parse.h b/Sources/libetpan/low-level/mbox/mailmbox_parse.h new file mode 100644 index 00000000..a7887503 --- /dev/null +++ b/Sources/libetpan/low-level/mbox/mailmbox_parse.h @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmbox_parse.h,v 1.4 2008/02/20 22:15:52 hoa Exp $ + */ + +#ifndef MAILMBOX_PARSE_H + +#define MAILMBOX_PARSE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailmbox_types.h" + +int mailmbox_parse(struct mailmbox_folder * folder); + +int +mailmbox_parse_additionnal(struct mailmbox_folder * folder, + size_t * indx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/mbox/mailmbox_types.c b/Sources/libetpan/low-level/mbox/mailmbox_types.c new file mode 100644 index 00000000..04eb27bf --- /dev/null +++ b/Sources/libetpan/low-level/mbox/mailmbox_types.c @@ -0,0 +1,252 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmbox_types.c,v 1.24 2008/02/20 22:35:48 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailmbox_types.h" + +#include +#include + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +/* *********************************************************************** */ + +int mailmbox_msg_info_update(struct mailmbox_folder * folder, + size_t msg_start, size_t msg_start_len, + size_t msg_headers, size_t msg_headers_len, + size_t msg_body, size_t msg_body_len, + size_t msg_size, size_t msg_padding, + uint32_t msg_uid) +{ + struct mailmbox_msg_info * info; + int res; + chashdatum key; + chashdatum data; + int r; + + key.data = &msg_uid; + key.len = sizeof(msg_uid); + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + unsigned int indx; + + info = mailmbox_msg_info_new(msg_start, msg_start_len, + msg_headers, msg_headers_len, + msg_body, msg_body_len, msg_size, msg_padding, msg_uid); + if (info == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto err; + } + + r = carray_add(folder->mb_tab, info, &indx); + if (r < 0) { + mailmbox_msg_info_free(info); + res = MAILMBOX_ERROR_MEMORY; + goto err; + } + + if (msg_uid != 0) { + key.data = &msg_uid; + key.len = sizeof(msg_uid); + data.data = info; + data.len = 0; + + r = chash_set(folder->mb_hash, &key, &data, NULL); + if (r < 0) { + mailmbox_msg_info_free(info); + carray_delete(folder->mb_tab, indx); + res = MAILMBOX_ERROR_MEMORY; + goto err; + } + } + + info->msg_index = indx; + } + else { + info = data.data; + + info->msg_start = msg_start; + info->msg_start_len = msg_start_len; + info->msg_headers = msg_headers; + info->msg_headers_len = msg_headers_len; + info->msg_body = msg_body; + info->msg_body_len = msg_body_len; + info->msg_size = msg_size; + info->msg_padding = msg_padding; + } + + return MAILMBOX_NO_ERROR; + + err: + return res; +} + + +struct mailmbox_msg_info * +mailmbox_msg_info_new(size_t msg_start, size_t msg_start_len, + size_t msg_headers, size_t msg_headers_len, + size_t msg_body, size_t msg_body_len, + size_t msg_size, size_t msg_padding, + uint32_t msg_uid) +{ + struct mailmbox_msg_info * info; + + info = malloc(sizeof(* info)); + if (info == NULL) + return NULL; + + info->msg_index = 0; + info->msg_uid = msg_uid; + if (msg_uid != 0) + info->msg_written_uid = TRUE; + else + info->msg_written_uid = FALSE; + info->msg_deleted = FALSE; + + info->msg_start = msg_start; + info->msg_start_len = msg_start_len; + + info->msg_headers = msg_headers; + info->msg_headers_len = msg_headers_len; + + info->msg_body = msg_body; + info->msg_body_len = msg_body_len; + + info->msg_size = msg_size; + + info->msg_padding = msg_padding; + + return info; +} + +void mailmbox_msg_info_free(struct mailmbox_msg_info * info) +{ + free(info); +} + + +/* append info */ + +struct mailmbox_append_info * +mailmbox_append_info_new(const char * ai_message, size_t ai_size) +{ + struct mailmbox_append_info * info; + + info = malloc(sizeof(* info)); + if (info == NULL) + return NULL; + + info->ai_message = ai_message; + info->ai_size = ai_size; + info->ai_uid = 0; + + return info; +} + +void mailmbox_append_info_free(struct mailmbox_append_info * info) +{ + free(info); +} + +struct mailmbox_folder * mailmbox_folder_new(const char * mb_filename) +{ + struct mailmbox_folder * folder; + + folder = malloc(sizeof(* folder)); + if (folder == NULL) + goto err; + + strncpy(folder->mb_filename, mb_filename, PATH_MAX); + + folder->mb_mtime = (time_t) -1; + + folder->mb_fd = -1; + folder->mb_read_only = TRUE; + folder->mb_no_uid = TRUE; + + folder->mb_changed = FALSE; + folder->mb_deleted_count = 0; + + folder->mb_mapping = NULL; + folder->mb_mapping_size = 0; + + folder->mb_written_uid = 0; + folder->mb_max_uid = 0; + + folder->mb_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + if (folder->mb_hash == NULL) + goto free; + + folder->mb_tab = carray_new(128); + if (folder->mb_tab == NULL) + goto free_hash; + + return folder; + + free_hash: + chash_free(folder->mb_hash); + free: + free(folder); + err: + return NULL; +} + +void mailmbox_folder_free(struct mailmbox_folder * folder) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(folder->mb_tab) ; i++) { + struct mailmbox_msg_info * info; + + info = carray_get(folder->mb_tab, i); + if (info != NULL) + mailmbox_msg_info_free(info); + } + + carray_free(folder->mb_tab); + + chash_free(folder->mb_hash); + + free(folder); +} diff --git a/Sources/libetpan/low-level/mbox/mailmbox_types.h b/Sources/libetpan/low-level/mbox/mailmbox_types.h new file mode 100644 index 00000000..b6875a90 --- /dev/null +++ b/Sources/libetpan/low-level/mbox/mailmbox_types.h @@ -0,0 +1,143 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmbox_types.h,v 1.27 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifndef MAILMBOX_TYPES_H + +#define MAILMBOX_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +#include +#include +#include + +enum { + MAILMBOX_NO_ERROR = 0, + MAILMBOX_ERROR_PARSE, + MAILMBOX_ERROR_INVAL, + MAILMBOX_ERROR_FILE_NOT_FOUND, + MAILMBOX_ERROR_MEMORY, + MAILMBOX_ERROR_TEMPORARY_FILE, + MAILMBOX_ERROR_FILE, + MAILMBOX_ERROR_MSG_NOT_FOUND, + MAILMBOX_ERROR_READONLY +}; + + +struct mailmbox_folder { + char mb_filename[PATH_MAX]; + + time_t mb_mtime; + + int mb_fd; + int mb_read_only; + int mb_no_uid; + + int mb_changed; + unsigned int mb_deleted_count; + + char * mb_mapping; + size_t mb_mapping_size; + + uint32_t mb_written_uid; + uint32_t mb_max_uid; + + chash * mb_hash; + carray * mb_tab; +}; + +struct mailmbox_folder * mailmbox_folder_new(const char * mb_filename); +void mailmbox_folder_free(struct mailmbox_folder * folder); + + +struct mailmbox_msg_info { + unsigned int msg_index; + uint32_t msg_uid; + int msg_written_uid; + int msg_deleted; + + size_t msg_start; + size_t msg_start_len; + + size_t msg_headers; + size_t msg_headers_len; + + size_t msg_body; + size_t msg_body_len; + + size_t msg_size; + + size_t msg_padding; +}; + + +int mailmbox_msg_info_update(struct mailmbox_folder * folder, + size_t msg_start, size_t msg_start_len, + size_t msg_headers, size_t msg_headers_len, + size_t msg_body, size_t msg_body_len, + size_t msg_size, size_t msg_padding, + uint32_t msg_uid); + +struct mailmbox_msg_info * +mailmbox_msg_info_new(size_t msg_start, size_t msg_start_len, + size_t msg_headers, size_t msg_headers_len, + size_t msg_body, size_t msg_body_len, + size_t msg_size, size_t msg_padding, + uint32_t msg_uid); + +void mailmbox_msg_info_free(struct mailmbox_msg_info * info); + +struct mailmbox_append_info { + const char * ai_message; + size_t ai_size; + unsigned int ai_uid; +}; + +struct mailmbox_append_info * +mailmbox_append_info_new(const char * ai_message, size_t ai_size); + +void mailmbox_append_info_free(struct mailmbox_append_info * info); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/mh/Makefile.am b/Sources/libetpan/low-level/mh/Makefile.am new file mode 100644 index 00000000..a65fee25 --- /dev/null +++ b/Sources/libetpan/low-level/mh/Makefile.am @@ -0,0 +1,41 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +etpaninclude_HEADERS = \ + mailmh.h + +AM_CPPFLAGS = -I$(top_builddir)/include \ + -I$(top_srcdir)/src/data-types + +noinst_LTLIBRARIES = libmh.la + +libmh_la_SOURCES = \ + mailmh.c diff --git a/Sources/libetpan/low-level/mh/mailmh.c b/Sources/libetpan/low-level/mh/mailmh.c new file mode 100644 index 00000000..e7984945 --- /dev/null +++ b/Sources/libetpan/low-level/mh/mailmh.c @@ -0,0 +1,915 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmh.c,v 1.35 2008/02/20 22:15:52 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailmh.h" + +/* +perfs : + +/net/home/dinh/Mail/inbox/sylpheed 686 + +2724 /net/home/dinh/Mail/inbox/sylpheed + +bart:~/LibEtPan/libetpan/tests> time ./mhtest >/dev/null + +real 0m0.385s +user 0m0.270s +sys 0m0.110s + +*/ + +#ifdef WIN32 +# include "win_etpan.h" +#else +# include +# include +# include +#endif +#include +#include +#include +#include +#include +#include + +#include "libetpan-config.h" + +struct mailmh * mailmh_new(const char * foldername) +{ + struct mailmh * f; + + f = malloc(sizeof(*f)); + if (f == NULL) + return NULL; + + f->mh_main = mailmh_folder_new(NULL, foldername); + if (f->mh_main == NULL) { + free(f); + return NULL; + } + + return f; +} + +void mailmh_free(struct mailmh * f) +{ + mailmh_folder_free(f->mh_main); + free(f); +} + + + +struct mailmh_msg_info * mailmh_msg_info_new(uint32_t indx, size_t size, + time_t mtime) +{ + struct mailmh_msg_info * msg_info; + + msg_info = malloc(sizeof(* msg_info)); + if (msg_info == NULL) + return NULL; + msg_info->msg_index = indx; + msg_info->msg_size = size; + msg_info->msg_mtime = mtime; + + msg_info->msg_array_index = 0; + + return msg_info; +} + +void mailmh_msg_info_free(struct mailmh_msg_info * msg_info) +{ + free(msg_info); +} + +struct mailmh_folder * mailmh_folder_new(struct mailmh_folder * parent, + const char * name) +{ + char * filename; + char * parent_filename; + + struct mailmh_folder * folder; + + folder = malloc(sizeof(* folder)); + if (folder == NULL) + goto err; + + if (parent == NULL) { + filename = strdup(name); + if (filename == NULL) + goto free_folder; + } + else { + parent_filename = parent->fl_filename; + filename = malloc(strlen(parent_filename) + strlen(name) + 2); + if (filename == NULL) + goto free_folder; + + strcpy(filename, parent_filename); + strcat(filename, MAIL_DIR_SEPARATOR_S); + strcat(filename, name); + } + + folder->fl_filename = filename; + + folder->fl_name = strdup(name); + if (folder->fl_name == NULL) + goto free_filename; + + folder->fl_msgs_tab = carray_new(128); + if (folder->fl_msgs_tab == NULL) + goto free_name; + + folder->fl_msgs_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + if (folder->fl_msgs_hash == NULL) + goto free_msgs_tab; + + folder->fl_subfolders_tab = carray_new(128); + if (folder->fl_subfolders_tab == NULL) + goto free_msgs_hash; + + folder->fl_subfolders_hash = chash_new(128, CHASH_COPYNONE); + if (folder->fl_subfolders_hash == NULL) + goto free_subfolders_tab; + + folder->fl_mtime = 0; + folder->fl_parent = parent; + folder->fl_max_index = 0; + + return folder; + + free_subfolders_tab: + carray_free(folder->fl_subfolders_tab); + free_msgs_hash: + chash_free(folder->fl_msgs_hash); + free_msgs_tab: + carray_free(folder->fl_msgs_tab); + free_name: + free(folder->fl_name); + free_filename: + free(folder->fl_filename); + free_folder: + free(folder); + err: + return NULL; +} + +void mailmh_folder_free(struct mailmh_folder * folder) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(folder->fl_subfolders_tab) ; i++) { + struct mailmh_folder * subfolder; + + subfolder = carray_get(folder->fl_subfolders_tab, i); + if (subfolder != NULL) + mailmh_folder_free(subfolder); + } + carray_free(folder->fl_subfolders_tab); + chash_free(folder->fl_subfolders_hash); + + for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) { + struct mailmh_msg_info * msg_info; + + msg_info = carray_get(folder->fl_msgs_tab, i); + if (msg_info != NULL) + mailmh_msg_info_free(msg_info); + } + carray_free(folder->fl_msgs_tab); + chash_free(folder->fl_msgs_hash); + + free(folder->fl_filename); + free(folder->fl_name); + + free(folder); +} + +struct mailmh_folder * mailmh_folder_find(struct mailmh_folder * root, + const char * filename) +{ + int r; + char pathname[PATH_MAX]; + char * p; + chashdatum key; + chashdatum data; + struct mailmh_folder * folder; + char * start; + + if (strcmp(root->fl_filename, filename) == 0) + return root; + + strncpy(pathname, filename, PATH_MAX); + pathname[PATH_MAX - 1] = 0; + start = pathname + strlen(root->fl_filename) + 1; + + p = strchr(start, MAIL_DIR_SEPARATOR); + if (p != NULL) { + * p = 0; + + root = mailmh_folder_find(root, pathname); + if (root != NULL) { + folder = mailmh_folder_find(root, filename); + if (folder == NULL) + return NULL; + return folder; + } + + return NULL; + } + else { + key.data = pathname; + key.len = (unsigned int) strlen(pathname); + r = chash_get(root->fl_subfolders_hash, &key, &data); + if (r < 0) + return NULL; + + return data.data; + } +} + +int mailmh_folder_update(struct mailmh_folder * folder) +{ + DIR * d; + struct dirent * ent; + struct stat buf; + char * mh_seq; + char filename[PATH_MAX]; + int res; + int r; + uint32_t max_index; + unsigned int i; + + if (stat(folder->fl_filename, &buf) == -1) { + res = MAILMH_ERROR_FOLDER; + goto err; + } + + if (folder->fl_mtime == buf.st_mtime) { + res = MAILMH_NO_ERROR; + goto err; + } + + folder->fl_mtime = buf.st_mtime; + + d = opendir(folder->fl_filename); + if (d == NULL) { + res = MAILMH_ERROR_FOLDER; + goto err; + } + + max_index = 0; + + /* clear the message list */ + + for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++) { + struct mailmh_msg_info * msg_info; + chashdatum key; + + msg_info = carray_get(folder->fl_msgs_tab, i); + if (msg_info == NULL) + continue; + + key.data = &msg_info->msg_index; + key.len = sizeof(msg_info->msg_index); + chash_delete(folder->fl_msgs_hash, &key, NULL); + + mailmh_msg_info_free(msg_info); + } + + carray_set_size(folder->fl_msgs_tab, 0); + + do { + uint32_t indx; + + ent = readdir(d); + + if (ent != NULL) { + + snprintf(filename, PATH_MAX, + "%s%c%s", folder->fl_filename, MAIL_DIR_SEPARATOR, ent->d_name); + + if (stat(filename, &buf) == -1) + continue; + + if (S_ISREG(buf.st_mode)) { + indx = (uint32_t) strtoul(ent->d_name, NULL, 10); + if (indx != 0) { + struct mailmh_msg_info * msg_info; + unsigned int array_index; + chashdatum key; + chashdatum data; + + msg_info = mailmh_msg_info_new(indx, buf.st_size, buf.st_mtime); + if (msg_info == NULL) { + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + + r = carray_add(folder->fl_msgs_tab, msg_info, &array_index); + if (r < 0) { + mailmh_msg_info_free(msg_info); + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + msg_info->msg_array_index = array_index; + + if (indx > max_index) + max_index = indx; + + key.data = &msg_info->msg_index; + key.len = sizeof(msg_info->msg_index); + data.data = msg_info; + data.len = 0; + + r = chash_set(folder->fl_msgs_hash, &key, &data, NULL); + if (r < 0) { + carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index); + mailmh_msg_info_free(msg_info); + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + } + } + else if (S_ISDIR(buf.st_mode)) { + struct mailmh_folder * subfolder; + unsigned int array_index; + chashdatum key; + chashdatum data; + + if (ent->d_name[0] == '.') { + if (ent->d_name[1] == 0) + continue; + if ((ent->d_name[1] == '.') && (ent->d_name[2] == 0)) + continue; + } + + key.data = ent->d_name; + key.len = (unsigned int) strlen(ent->d_name); + r = chash_get(folder->fl_subfolders_hash, &key, &data); + if (r < 0) { + subfolder = mailmh_folder_new(folder, ent->d_name); + if (subfolder == NULL) { + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + + r = carray_add(folder->fl_subfolders_tab, subfolder, &array_index); + if (r < 0) { + mailmh_folder_free(subfolder); + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + subfolder->fl_array_index = array_index; + + key.data = subfolder->fl_filename; + key.len = (unsigned int) strlen(subfolder->fl_filename); + data.data = subfolder; + data.len = 0; + r = chash_set(folder->fl_subfolders_hash, &key, &data, NULL); + if (r < 0) { + carray_delete_fast(folder->fl_subfolders_tab, subfolder->fl_array_index); + mailmh_folder_free(subfolder); + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + } + } + } + } + while (ent != NULL); + + folder->fl_max_index = max_index; + + mh_seq = malloc(strlen(folder->fl_filename) + 2 + sizeof(".mh_sequences")); + if (mh_seq == NULL) { + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + strcpy(mh_seq, folder->fl_filename); + strcat(mh_seq, MAIL_DIR_SEPARATOR_S); + strcat(mh_seq, ".mh_sequences"); + + if (stat(mh_seq, &buf) == -1) { + int fd; + + fd = creat(mh_seq, S_IRUSR | S_IWUSR); + if (fd != -1) + close(fd); + } + free(mh_seq); + + closedir(d); + + return MAILMH_NO_ERROR; + + closedir: + closedir(d); + err: + return res; +} + +int mailmh_folder_add_subfolder(struct mailmh_folder * parent, + const char * name) +{ + char * foldername; + int r; + struct mailmh_folder * folder; + unsigned int array_index; + chashdatum key; + chashdatum data; + + foldername = malloc(strlen(parent->fl_filename) + strlen(name) + 2); + if (foldername == NULL) + return MAILMH_ERROR_MEMORY; + strcpy(foldername, parent->fl_filename); + strcat(foldername, MAIL_DIR_SEPARATOR_S); + strcat(foldername, name); + +#ifdef WIN32 + r = mkdir(foldername); +#else + r = mkdir(foldername, 0700); +#endif + free(foldername); + + if (r < 0) + return MAILMH_ERROR_FOLDER; + + folder = mailmh_folder_new(parent, name); + if (folder == NULL) + return MAILMH_ERROR_MEMORY; + + r = carray_add(parent->fl_subfolders_tab, folder, &array_index); + if (r < 0) { + mailmh_folder_free(folder); + return MAILMH_ERROR_MEMORY; + } + folder->fl_array_index = array_index; + + key.data = folder->fl_filename; + key.len = (unsigned int) strlen(folder->fl_filename); + data.data = folder; + data.len = 0; + + r = chash_set(parent->fl_subfolders_hash, &key, &data, NULL); + if (r < 0) { + carray_delete_fast(folder->fl_subfolders_tab, folder->fl_array_index); + mailmh_folder_free(folder); + return MAILMH_ERROR_MEMORY; + } + + return MAILMH_NO_ERROR; +} + +int mailmh_folder_remove_subfolder(struct mailmh_folder * folder) +{ + struct mailmh_folder * parent; + chashdatum key; + chashdatum data; + int r; + + parent = folder->fl_parent; + + key.data = folder->fl_filename; + key.len = (unsigned int) strlen(folder->fl_filename); + + r = chash_get(parent->fl_subfolders_hash, &key, &data); + if (r < 0) + return MAILMH_ERROR_FOLDER; + + chash_delete(parent->fl_subfolders_hash, &key, NULL); + carray_delete_fast(parent->fl_subfolders_tab, folder->fl_array_index); + + mailmh_folder_free(folder); + + return MAILMH_NO_ERROR; + +} + +int mailmh_folder_rename_subfolder(struct mailmh_folder * src_folder, + struct mailmh_folder * dst_folder, + const char * new_name) +{ + int r; + struct mailmh_folder * folder; + struct mailmh_folder * parent; + char * new_foldername; + + parent = src_folder->fl_parent; + if (parent == NULL) + return MAILMH_ERROR_RENAME; + + new_foldername = malloc(strlen(dst_folder->fl_filename) + 2 + strlen(new_name)); + if (new_foldername == NULL) + return MAILMH_ERROR_MEMORY; + + strcpy(new_foldername, dst_folder->fl_filename); + strcat(new_foldername, MAIL_DIR_SEPARATOR_S); + strcat(new_foldername, new_name); + + r = rename(src_folder->fl_filename, new_foldername); + free(new_foldername); + if (r < 0) + return MAILMH_ERROR_RENAME; + + r = mailmh_folder_remove_subfolder(src_folder); + if (r != MAILMH_NO_ERROR) + return r; + + folder = mailmh_folder_new(dst_folder, new_name); + if (folder == NULL) + return MAILMH_ERROR_MEMORY; + + r = carray_add(parent->fl_subfolders_tab, folder, NULL); + if (r < 0) { + mailmh_folder_free(folder); + return MAILMH_ERROR_MEMORY; + } + + return MAILMH_NO_ERROR; +} + +#define MAX_TRY_ALLOC 32 + +/* initial file MUST be in the same directory */ + +static int mailmh_folder_alloc_msg(struct mailmh_folder * folder, + char * filename, uint32_t * result) +{ + uint32_t max; + uint32_t k; + char * new_filename; + size_t len; + int got_file; + + len = strlen(folder->fl_filename) + 20; + new_filename = malloc(len); + if (new_filename == NULL) + return MAILMH_ERROR_MEMORY; + + max = folder->fl_max_index + 1; + + got_file = 0; + k = 0; + while (k < MAX_TRY_ALLOC) { + snprintf(new_filename, len, "%s%c%lu", folder->fl_filename, + MAIL_DIR_SEPARATOR, (unsigned long) (max + k)); + +/* SEB */ +#ifdef WIN32 + if (rename( filename, new_filename) == 0) { + got_file = 1; + } +#else + if (link(filename, new_filename) == 0) { + unlink(filename); + got_file = 1; + } +#endif /* WIN32 */ + else if (errno == EXDEV) { + free(new_filename); + return MAILMH_ERROR_FOLDER; + } + else if (errno == EPERM) { + rename(filename, new_filename); + got_file = 1; + } + + if (got_file) { + free(new_filename); + + if (k > MAX_TRY_ALLOC / 2) { + mailmh_folder_update(folder); + /* ignore errors */ + } + + * result = max + k; + + folder->fl_max_index = max + k; + + return MAILMH_NO_ERROR; + } + k ++; + } + + free(new_filename); + + return MAILMH_ERROR_FOLDER; +} + +int mailmh_folder_get_message_filename(struct mailmh_folder * folder, + uint32_t indx, char ** result) +{ + char * filename; + size_t len; + + len = strlen(folder->fl_filename) + 20; + filename = malloc(len); + if (filename == NULL) + return MAILMH_ERROR_MEMORY; + + snprintf(filename, len, "%s%c%lu", folder->fl_filename, MAIL_DIR_SEPARATOR, + (unsigned long) indx); + + * result = filename; + + return MAILMH_NO_ERROR;; +} + + +int mailmh_folder_get_message_fd(struct mailmh_folder * folder, + uint32_t indx, int flags, int * result) +{ + char * filename; + int fd; + int r; + + r = mailmh_folder_get_message_filename(folder, indx, &filename); + if (r != MAILMH_NO_ERROR) + return r; + + fd = open(filename, flags); + free(filename); + if (fd == -1) + return MAILMH_ERROR_MSG_NOT_FOUND; + + * result = fd; + + return MAILMH_NO_ERROR; +} + +int mailmh_folder_get_message_size(struct mailmh_folder * folder, + uint32_t indx, size_t * result) +{ + int r; + char * filename; + struct stat buf; + + r = mailmh_folder_get_message_filename(folder, indx, &filename); + if (r != MAILMH_NO_ERROR) + return r; + + r = stat(filename, &buf); + free(filename); + if (r < 0) + return MAILMH_ERROR_FILE; + + * result = buf.st_size; + + return MAILMH_NO_ERROR; +} + +int mailmh_folder_add_message_uid(struct mailmh_folder * folder, + const char * message, size_t size, + uint32_t * pindex) +{ + char * tmpname; + int fd; + size_t namesize; + size_t left; + ssize_t res; + struct mailmh_msg_info * msg_info; + uint32_t indx; + int error; + int r; + unsigned int array_index; + struct stat buf; + chashdatum key; + chashdatum data; + + namesize = strlen(folder->fl_filename) + 20; + tmpname = malloc(namesize); + snprintf(tmpname, namesize, "%s%ctmpXXXXXX", + folder->fl_filename, MAIL_DIR_SEPARATOR); + fd = mkstemp(tmpname); + if (fd < 0) { + error = MAILMH_ERROR_FILE; + goto free; + } + + left = size; + while (left > 0) { + res = write(fd, message, left); + if (res == -1) { + close(fd); + error = MAILMH_ERROR_FILE; + goto free; + } + + left -= res; + } + close(fd); + + r = stat(tmpname, &buf); + if (r < 0) { + error = MAILMH_ERROR_FILE; + goto free; + } + + r = mailmh_folder_alloc_msg(folder, tmpname, &indx); + if (r != MAILMH_NO_ERROR) { + unlink(tmpname); + error = MAILMH_ERROR_COULD_NOT_ALLOC_MSG; + goto free; + } + free(tmpname); + + msg_info = mailmh_msg_info_new(indx, size, buf.st_mtime); + if (msg_info == NULL) { + mailmh_folder_remove_message(folder, indx); + error = MAILMH_ERROR_MEMORY; + goto err; + } + + r = carray_add(folder->fl_msgs_tab, msg_info, &array_index); + if (r < 0) { + mailmh_folder_remove_message(folder, indx); + mailmh_msg_info_free(msg_info); + error = MAILMH_ERROR_MEMORY; + goto err; + } + msg_info->msg_array_index = array_index; + + key.data = &indx; + key.len = sizeof(indx); + data.data = msg_info; + data.len = 0; + + if (pindex != NULL) + * pindex = indx; + + r = chash_set(folder->fl_msgs_hash, &key, &data, NULL); + if (r < 0) { + carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index); + mailmh_msg_info_free(msg_info); + error = MAILMH_ERROR_MEMORY; + goto err; + } + + return MAILMH_NO_ERROR; + + free: + free(tmpname); + err: + return error; +} + +int mailmh_folder_add_message(struct mailmh_folder * folder, + const char * message, size_t size) +{ + return mailmh_folder_add_message_uid(folder, message, size, NULL); +} + +int mailmh_folder_add_message_file_uid(struct mailmh_folder * folder, + int fd, uint32_t * pindex) +{ + char * message; + struct stat buf; + int r; + + if (fstat(fd, &buf) == -1) + return MAILMH_ERROR_FILE; + + message = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (message == (const char *)MAP_FAILED) + return MAILMH_ERROR_FILE; + + r = mailmh_folder_add_message_uid(folder, message, buf.st_size, pindex); + + munmap(message, buf.st_size); + + return r; +} + +int mailmh_folder_add_message_file(struct mailmh_folder * folder, + int fd) +{ + return mailmh_folder_add_message_file_uid(folder, fd, NULL); +} + +int mailmh_folder_remove_message(struct mailmh_folder * folder, + uint32_t indx) +{ + char * filename; + struct mailmh_msg_info * msg_info; + int res; + int r; + chashdatum key; + chashdatum data; + + filename = NULL; + r = mailmh_folder_get_message_filename(folder, indx, &filename); + if (filename == NULL) { + res = r; + goto err; + } + + if (unlink(filename) == -1) { + res = MAILMH_ERROR_FILE; + goto free; + } + + key.data = &indx; + key.len = sizeof(indx); + r = chash_get(folder->fl_msgs_hash, &key, &data); + if (r == 0) { + msg_info = data.data; + + carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index); + chash_delete(folder->fl_msgs_hash, &key, NULL); + } + + return MAILMH_NO_ERROR; + + free: + free(filename); + err: + return res; +} + + +int mailmh_folder_move_message(struct mailmh_folder * dest_folder, + struct mailmh_folder * src_folder, + uint32_t indx) +{ + int fd; + char * filename; + int r; + + /* move on the same filesystem */ + r = mailmh_folder_get_message_filename(src_folder, indx, &filename); + if (r != MAILMH_NO_ERROR) + return r; + + r = mailmh_folder_alloc_msg(dest_folder, filename, &indx); + free(filename); + if (r == MAILMH_NO_ERROR) + return MAILMH_NO_ERROR; + + /* move on the different filesystems */ + r = mailmh_folder_get_message_fd(src_folder, indx, O_RDONLY, &fd); + if (r != MAILMH_NO_ERROR) + return r; + + r = mailmh_folder_add_message_file(dest_folder, fd); + if (r != MAILMH_NO_ERROR) { + close(fd); + return r; + } + + close(fd); + + r = mailmh_folder_remove_message(src_folder, indx); + if (r != MAILMH_NO_ERROR) + printf("Cannot remove message from %s at index %u", src_folder->fl_name, indx); + + return r; +} + +unsigned int mailmh_folder_get_message_number(struct mailmh_folder * folder) +{ + unsigned int i; + unsigned int count; + + count = 0; + for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++) + if (carray_get(folder->fl_msgs_tab, i) != NULL) + count ++; + + return count; +} diff --git a/Sources/libetpan/low-level/mh/mailmh.h b/Sources/libetpan/low-level/mh/mailmh.h new file mode 100644 index 00000000..3487f86c --- /dev/null +++ b/Sources/libetpan/low-level/mh/mailmh.h @@ -0,0 +1,147 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmh.h,v 1.27 2008/02/20 22:15:52 hoa Exp $ + */ + +#ifndef MAILMH_H + +#define MAILMH_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include +#include +#include + +enum { + MAILMH_NO_ERROR = 0, + MAILMH_ERROR_FOLDER, + MAILMH_ERROR_MEMORY, + MAILMH_ERROR_FILE, + MAILMH_ERROR_COULD_NOT_ALLOC_MSG, + MAILMH_ERROR_RENAME, + MAILMH_ERROR_MSG_NOT_FOUND +}; + +struct mailmh { + struct mailmh_folder * mh_main; +}; + +struct mailmh_msg_info { + unsigned int msg_array_index; + uint32_t msg_index; + size_t msg_size; + time_t msg_mtime; +}; + +struct mailmh_folder { + char * fl_filename; + unsigned int fl_array_index; + + char * fl_name; + time_t fl_mtime; + struct mailmh_folder * fl_parent; + uint32_t fl_max_index; + + carray * fl_msgs_tab; + chash * fl_msgs_hash; + + carray * fl_subfolders_tab; + chash * fl_subfolders_hash; +}; + +struct mailmh * mailmh_new(const char * foldername); +void mailmh_free(struct mailmh * f); + +struct mailmh_msg_info * +mailmh_msg_info_new(uint32_t indx, size_t size, time_t mtime); +void mailmh_msg_info_free(struct mailmh_msg_info * msg_info); + +struct mailmh_folder * mailmh_folder_new(struct mailmh_folder * parent, + const char * name); +void mailmh_folder_free(struct mailmh_folder * folder); + +int mailmh_folder_add_subfolder(struct mailmh_folder * parent, + const char * name); + +struct mailmh_folder * mailmh_folder_find(struct mailmh_folder * root, + const char * filename); + +int mailmh_folder_remove_subfolder(struct mailmh_folder * folder); + +int mailmh_folder_rename_subfolder(struct mailmh_folder * src_folder, + struct mailmh_folder * dst_folder, + const char * new_name); + +int mailmh_folder_get_message_filename(struct mailmh_folder * folder, + uint32_t indx, char ** result); + +int mailmh_folder_get_message_fd(struct mailmh_folder * folder, + uint32_t indx, int flags, int * result); + +int mailmh_folder_get_message_size(struct mailmh_folder * folder, + uint32_t indx, size_t * result); + +int mailmh_folder_add_message_uid(struct mailmh_folder * folder, + const char * message, size_t size, + uint32_t * pindex); + +int mailmh_folder_add_message(struct mailmh_folder * folder, + const char * message, size_t size); + +int mailmh_folder_add_message_file_uid(struct mailmh_folder * folder, + int fd, uint32_t * pindex); + +int mailmh_folder_add_message_file(struct mailmh_folder * folder, + int fd); + +int mailmh_folder_remove_message(struct mailmh_folder * folder, + uint32_t indx); + +int mailmh_folder_move_message(struct mailmh_folder * dest_folder, + struct mailmh_folder * src_folder, + uint32_t indx); + +int mailmh_folder_update(struct mailmh_folder * folder); + +unsigned int mailmh_folder_get_message_number(struct mailmh_folder * folder); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/mime/Makefile.am b/Sources/libetpan/low-level/mime/Makefile.am new file mode 100644 index 00000000..1d7d83e5 --- /dev/null +++ b/Sources/libetpan/low-level/mime/Makefile.am @@ -0,0 +1,50 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +EXTRA_DIST = TODO + +etpaninclude_HEADERS = \ + mailmime.h mailmime_types.h mailmime_content.h mailmime_decode.h \ + mailmime_disposition.h mailmime_write_file.h \ + mailmime_types_helper.h mailmime_write_generic.h \ + mailmime_write_mem.h + +AM_CPPFLAGS = -I$(top_builddir)/include \ + -I$(top_srcdir)/src/low-level/imf \ + -I$(top_srcdir)/src/data-types + +noinst_LTLIBRARIES = libmime.la + +libmime_la_SOURCES = \ + mailmime.c mailmime_types.c mailmime_content.c mailmime_decode.c \ + mailmime_disposition.c mailmime_write_file.c \ + mailmime_types_helper.c mailmime_write_generic.c \ + mailmime_write_mem.c mailmime_write.h diff --git a/Sources/libetpan/low-level/mime/TODO b/Sources/libetpan/low-level/mime/TODO new file mode 100644 index 00000000..df02810f --- /dev/null +++ b/Sources/libetpan/low-level/mime/TODO @@ -0,0 +1,10 @@ +- see about the RFC2047, beginning in mailmime_decode.[ch] +- content-langage +- single mime_field +- RFC 2048 +- RFC 2049 +- RFC 2231 +- RFC 2387 +- RFC 2424 +- RFC 2557 + diff --git a/Sources/libetpan/low-level/mime/mailmime.c b/Sources/libetpan/low-level/mime/mailmime.c new file mode 100644 index 00000000..db0ffc3e --- /dev/null +++ b/Sources/libetpan/low-level/mime/mailmime.c @@ -0,0 +1,1474 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime.c,v 1.29 2011/01/06 00:09:52 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailmime.h" + +/* + RFC 2045 + RFC 2046 + RFC 2047 + RFC 2048 + RFC 2049 + RFC 2231 + RFC 2387 + RFC 2424 + RFC 2557 + + RFC 2183 Content-Disposition + + RFC 1766 Language + */ + +#include +#include +#include + +#include "mailmime_types.h" +#include "mailmime_disposition.h" +#include "mailimf.h" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +static int mailmime_attribute_parse(const char * message, size_t length, + size_t * indx, + char ** result); +static int +mailmime_composite_type_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_composite_type ** result); + +static int is_text(char ch); + +static int +mailmime_discrete_type_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_discrete_type ** result); + +static int mailmime_mechanism_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_mechanism ** result); + +static int mailmime_subtype_parse(const char * message, size_t length, + size_t * indx, char ** result); + +static int is_token(char ch); + +static int mailmime_token_parse(const char * message, size_t length, + size_t * indx, + char ** token); + +static int is_tspecials(char ch); + +static int mailmime_type_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_type ** result); + +/* +int mailmime_version_parse(const char * message, guint32 length, + guint32 * indx, + guint32 * result); +*/ + +/* +static gboolean mailmime_x_token_parse(gconst char * message, guint32 length, + guint32 * indx, + gchar ** result); +*/ + +/* ********************************************************************** */ + +/* +x attribute := token + ; Matching of attributes + ; is ALWAYS case-insensitive. +*/ + +static int mailmime_attribute_parse(const char * message, size_t length, + size_t * indx, + char ** result) +{ + return mailmime_token_parse(message, length, indx, result); +} + +/* +x composite-type := "message" / "multipart" / extension-token +*/ + +static int +mailmime_composite_type_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_composite_type ** result) +{ + char * extension_token; + int type; + struct mailmime_composite_type * ct; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + extension_token = NULL; + + type = MAILMIME_COMPOSITE_TYPE_ERROR; /* XXX - removes a gcc warning */ + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "message"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_COMPOSITE_TYPE_MESSAGE; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "multipart"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_COMPOSITE_TYPE_MULTIPART; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + ct = mailmime_composite_type_new(type, extension_token); + if (ct == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_extension; + } + + * result = ct; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_extension: + if (extension_token != NULL) + mailmime_extension_token_free(extension_token); + err: + return res; +} + +/* +x content := "Content-Type" ":" type "/" subtype + *(";" parameter) + ; Matching of media type and subtype + ; is ALWAYS case-insensitive. +*/ + +LIBETPAN_EXPORT +int mailmime_content_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_content ** result) +{ + size_t cur_token; + struct mailmime_type * type; + char * subtype; + clist * parameters_list; + struct mailmime_content * content; + int r; + int res; + + cur_token = * indx; + + mailimf_cfws_parse(message, length, &cur_token); + + type = NULL; + r = mailmime_type_parse(message, length, &cur_token, &type); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '/'); + switch (r) { + case MAILIMF_NO_ERROR: + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free_type; + } + + r = mailmime_subtype_parse(message, length, &cur_token, &subtype); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_type; + } + break; + + case MAILIMF_ERROR_PARSE: + subtype = strdup("unknown"); + break; + + default: + res = r; + goto free_type; + } + + parameters_list = clist_new(); + if (parameters_list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_subtype; + } + + while (1) { + size_t final_token; + struct mailmime_parameter * parameter; + + final_token = cur_token; + r = mailimf_unstrict_char_parse(message, length, &cur_token, ';'); + if (r != MAILIMF_NO_ERROR) { + cur_token = final_token; + break; + } + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free_subtype; + } + + r = mailmime_parameter_parse(message, length, &cur_token, ¶meter); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + cur_token = final_token; + break; + } + else { + res = r; + goto free_subtype; + } + + r = clist_append(parameters_list, parameter); + if (r < 0) { + mailmime_parameter_free(parameter); + res = MAILIMF_ERROR_MEMORY; + goto free_parameters; + } + } + + content = mailmime_content_new(type, subtype, parameters_list); + if (content == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_parameters; + } + + * result = content; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_parameters: + clist_foreach(parameters_list, (clist_func) mailmime_parameter_free, NULL); + clist_free(parameters_list); + free_subtype: + mailmime_subtype_free(subtype); + free_type: + mailmime_type_free(type); + err: + return res; +} + +/* +x description := "Content-Description" ":" *text +*/ + +static int is_text(char ch) +{ + unsigned char uch = (unsigned char) ch; + + if (uch < 1) + return FALSE; + + if ((uch == 10) || (uch == 13)) + return FALSE; + + return TRUE; +} + +LIBETPAN_EXPORT +int mailmime_description_parse(const char * message, size_t length, + size_t * indx, + char ** result) +{ + return mailimf_custom_string_parse(message, length, + indx, result, + is_text); +} + +LIBETPAN_EXPORT +int mailmime_location_parse(const char * message, size_t length, + size_t * indx, + char ** result) +{ + return mailimf_custom_string_parse(message, length, + indx, result, + is_text); +} + +/* +x discrete-type := "text" / "image" / "audio" / "video" / + "application" / extension-token +*/ + +/* currently porting */ + +static int +mailmime_discrete_type_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_discrete_type ** result) +{ + char * extension; + int type; + struct mailmime_discrete_type * discrete_type; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + extension = NULL; + + type = MAILMIME_DISCRETE_TYPE_ERROR; /* XXX - removes a gcc warning */ + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "text"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISCRETE_TYPE_TEXT; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "image"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISCRETE_TYPE_IMAGE; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "audio"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISCRETE_TYPE_AUDIO; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "video"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISCRETE_TYPE_VIDEO; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "application"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISCRETE_TYPE_APPLICATION; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailmime_extension_token_parse(message, length, + &cur_token, &extension); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISCRETE_TYPE_EXTENSION; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + discrete_type = mailmime_discrete_type_new(type, extension); + if (discrete_type == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = discrete_type; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free: + mailmime_extension_token_free(extension); + err: + return res; +} + +/* +x encoding := "Content-Transfer-Encoding" ":" mechanism +*/ + +LIBETPAN_EXPORT +int mailmime_encoding_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_mechanism ** result) +{ + return mailmime_mechanism_parse(message, length, indx, result); +} + +/* +x entity-headers := [ content CRLF ] + [ encoding CRLF ] + [ id CRLF ] + [ description CRLF ] + *( MIME-extension-field CRLF ) + */ + +enum { + FIELD_STATE_START, + FIELD_STATE_T, + FIELD_STATE_D, + FIELD_STATE_L +}; + +static int guess_field_type(char * name) +{ + int state; + + if (* name == 'M') + return MAILMIME_FIELD_VERSION; + + if (strncasecmp(name, "Content-", 8) != 0) + return MAILMIME_FIELD_NONE; + + name += 8; + + state = FIELD_STATE_START; + + while (1) { + + switch (state) { + + case FIELD_STATE_START: + switch ((char) toupper((unsigned char) * name)) { + case 'T': + state = FIELD_STATE_T; + break; + case 'I': + return MAILMIME_FIELD_ID; + case 'D': + state = FIELD_STATE_D; + break; + case 'L': + state = FIELD_STATE_L; + break; + default: + return MAILMIME_FIELD_NONE; + } + break; + + case FIELD_STATE_T: + switch ((char) toupper((unsigned char) * name)) { + case 'Y': + return MAILMIME_FIELD_TYPE; + case 'R': + return MAILMIME_FIELD_TRANSFER_ENCODING; + default: + return MAILMIME_FIELD_NONE; + } + break; + + case FIELD_STATE_D: + switch ((char) toupper((unsigned char) * name)) { + case 'E': + return MAILMIME_FIELD_DESCRIPTION; + case 'I': + return MAILMIME_FIELD_DISPOSITION; + default: + return MAILMIME_FIELD_NONE; + } + break; + + case FIELD_STATE_L: + switch ((char) toupper((unsigned char) * name)) { + case 'A': + return MAILMIME_FIELD_LANGUAGE; + case 'O': + return MAILMIME_FIELD_LOCATION; + default: + return MAILMIME_FIELD_NONE; + } + break; + } + name ++; + } +} + +LIBETPAN_EXPORT +int +mailmime_field_parse(struct mailimf_optional_field * field, + struct mailmime_field ** result) +{ + char * name; + char * value; + int guessed_type; + size_t cur_token; + struct mailmime_content * content; + struct mailmime_mechanism * encoding; + char * id; + char * description; + uint32_t version; + struct mailmime_field * mime_field; + struct mailmime_language * language; + struct mailmime_disposition * disposition; + char * location; + int res; + int r; + + name = field->fld_name; + value = field->fld_value; + cur_token = 0; + + content = NULL; + encoding = NULL; + id = NULL; + description = NULL; + version = 0; + disposition = NULL; + language = NULL; + location = NULL; + + guessed_type = guess_field_type(name); + + switch (guessed_type) { + case MAILMIME_FIELD_TYPE: + if (strcasecmp(name, "Content-Type") != 0) + return MAILIMF_ERROR_PARSE; + { + size_t cur_token = 0; + char * decoded_value; + r = mailmime_encoded_phrase_parse("us-ascii", + value, strlen(value), + &cur_token, "utf-8", &decoded_value); + if (r != MAILIMF_NO_ERROR) { + cur_token = 0; + r = mailmime_content_parse(value, strlen(value), &cur_token, &content); + } + else { + cur_token = 0; + r = mailmime_content_parse(decoded_value, strlen(decoded_value), &cur_token, &content); + free(decoded_value); + } + if (r != MAILIMF_NO_ERROR) + return r; + } + break; + + case MAILMIME_FIELD_TRANSFER_ENCODING: + if (strcasecmp(name, "Content-Transfer-Encoding") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_encoding_parse(value, strlen(value), &cur_token, &encoding); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_FIELD_ID: + if (strcasecmp(name, "Content-ID") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_id_parse(value, strlen(value), &cur_token, &id); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_FIELD_DESCRIPTION: + if (strcasecmp(name, "Content-Description") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_description_parse(value, strlen(value), + &cur_token, &description); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_FIELD_VERSION: + if (strcasecmp(name, "MIME-Version") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_version_parse(value, strlen(value), &cur_token, &version); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_FIELD_DISPOSITION: + if (strcasecmp(name, "Content-Disposition") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_disposition_parse(value, strlen(value), + &cur_token, &disposition); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_FIELD_LANGUAGE: + if (strcasecmp(name, "Content-Language") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_language_parse(value, strlen(value), &cur_token, &language); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_FIELD_LOCATION: + if (strcasecmp(name, "Content-Location") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_location_parse(value, strlen(value), &cur_token, &location); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + default: + return MAILIMF_ERROR_PARSE; + } + + mime_field = mailmime_field_new(guessed_type, content, encoding, + id, description, version, disposition, + language, location); + if (mime_field == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = mime_field; + + return MAILIMF_NO_ERROR; + + free: + if (location != NULL) + mailmime_location_free(location); + if (language != NULL) + mailmime_language_free(language); + if (content != NULL) + mailmime_content_free(content); + if (encoding != NULL) + mailmime_encoding_free(encoding); + if (id != NULL) + mailmime_id_free(id); + if (description != NULL) + mailmime_description_free(description); + return res; +} + +/* +x extension-token := ietf-token / x-token +*/ + +LIBETPAN_EXPORT +int +mailmime_extension_token_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + return mailmime_token_parse(message, length, indx, result); +} + +/* + hex-octet := "=" 2(DIGIT / "A" / "B" / "C" / "D" / "E" / "F") + ; Octet must be used for characters > 127, =, + ; SPACEs or TABs at the ends of lines, and is + ; recommended for any character not listed in + ; RFC 2049 as "mail-safe". +*/ + +/* +x iana-token := +*/ + +/* +x ietf-token := +*/ + +/* +x id := "Content-ID" ":" msg-id +*/ + +LIBETPAN_EXPORT +int mailmime_id_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + return mailimf_msg_id_parse(message, length, indx, result); +} + +/* +x mechanism := "7bit" / "8bit" / "binary" / + "quoted-printable" / "base64" / + ietf-token / x-token +*/ + +static int mailmime_mechanism_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_mechanism ** result) +{ + char * token; + int type; + struct mailmime_mechanism * mechanism; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + type = MAILMIME_MECHANISM_ERROR; /* XXX - removes a gcc warning */ + + token = NULL; + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "7bit"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_MECHANISM_7BIT; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "8bit"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_MECHANISM_8BIT; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "binary"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_MECHANISM_BINARY; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "quoted-printable"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_MECHANISM_QUOTED_PRINTABLE; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "base64"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_MECHANISM_BASE64; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailmime_token_parse(message, length, &cur_token, &token); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_MECHANISM_TOKEN; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + mechanism = mailmime_mechanism_new(type, token); + if (mechanism == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = mechanism; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (token != NULL) + mailmime_token_free(token); + err: + return res; +} + +/* +x MIME-extension-field := +*/ + +/* +in headers + +x MIME-message-headers := entity-headers + fields + version CRLF + ; The ordering of the header + ; fields implied by this BNF + ; definition should be ignored. +*/ + +/* +in message + +x MIME-part-headers := entity-headers + [fields] + ; Any field not beginning with + ; "content-" can have no defined + ; meaning and may be ignored. + ; The ordering of the header + ; fields implied by this BNF + ; definition should be ignored. +*/ + +#if 0 +LIBETPAN_EXPORT +int +mailmime_unparsed_fields_parse(struct mailimf_unparsed_fields * + fields, + struct mailmime_fields ** + result) +{ + clistiter * cur; + struct mailmime_fields * mime_fields; + clist * list; + int r; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + if (fields->list == NULL) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + for(cur = clist_begin(fields->list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_optional_field * field = cur->data; + struct mailmime_field * mime_field; + + r = mailmime_field_parse(field, &mime_field); + if (r == MAILIMF_NO_ERROR) { + r = clist_append(list, mime_field); + if (r < 0) { + mailmime_field_free(mime_field); + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + } + } + + if (clist_begin(list) == NULL) { + res = MAILIMF_ERROR_PARSE; + goto free_list; + } + + mime_fields = mailmime_fields_new(list); + if (mime_fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = mime_fields; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailmime_field_free, NULL); + clist_free(list); + err: + return res; +} +#endif + +LIBETPAN_EXPORT +int +mailmime_fields_parse(struct mailimf_fields * + fields, + struct mailmime_fields ** + result) +{ + clistiter * cur; + struct mailmime_fields * mime_fields; + clist * list; + int r; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_field * field; + struct mailmime_field * mime_field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + r = mailmime_field_parse(field->fld_data.fld_optional_field, + &mime_field); + if (r == MAILIMF_NO_ERROR) { + r = clist_append(list, mime_field); + if (r < 0) { + mailmime_field_free(mime_field); + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto free_list; + } + } + } + + if (clist_begin(list) == NULL) { + res = MAILIMF_ERROR_PARSE; + goto free_list; + } + + mime_fields = mailmime_fields_new(list); + if (mime_fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = mime_fields; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailmime_field_free, NULL); + clist_free(list); + err: + return res; +} + +/* +x parameter := attribute "=" value +*/ + +LIBETPAN_EXPORT +int mailmime_parameter_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_parameter ** result) +{ + char * attribute; + char * value; + struct mailmime_parameter * parameter; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + + r = mailmime_attribute_parse(message, length, &cur_token, &attribute); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_attr; + } + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free_attr; + } + + r = mailmime_value_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_attr; + } + + parameter = mailmime_parameter_new(attribute, value); + if (parameter == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_value; + } + + * result = parameter; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_value: + mailmime_value_free(value); + free_attr: + mailmime_attribute_free(attribute); + err: + return res; +} + +/* + ptext := hex-octet / safe-char +*/ + +/* + qp-line := *(qp-segment transport-padding CRLF) + qp-part transport-padding +*/ + +/* + qp-part := qp-section + ; Maximum length of 76 characters +*/ + +/* + qp-section := [*(ptext / SPACE / TAB) ptext] +*/ + +/* + qp-segment := qp-section *(SPACE / TAB) "=" + ; Maximum length of 76 characters +*/ + +/* + quoted-printable := qp-line *(CRLF qp-line) +*/ + +/* + safe-char := + ; Characters not listed as "mail-safe" in + ; RFC 2049 are also not recommended. +*/ + +/* +x subtype := extension-token / iana-token +*/ + +static int mailmime_subtype_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + return mailmime_extension_token_parse(message, length, indx, result); +} + +/* +x token := 1* +*/ + +static int is_token(char ch) +{ + unsigned char uch = (unsigned char) ch; + + if (uch > 0x7F) + return FALSE; + + if (uch == ' ') + return FALSE; + + if (is_tspecials(ch)) + return FALSE; + + return TRUE; +} + + +static int mailmime_token_parse(const char * message, size_t length, + size_t * indx, + char ** token) +{ + return mailimf_custom_string_parse(message, length, + indx, token, + is_token); +} + +/* + transport-padding := *LWSP-char + ; Composers MUST NOT generate + ; non-zero length transport + ; padding, but receivers MUST + ; be able to handle padding + ; added by message transports. +*/ + +/* +enum { + LWSP_1, + LWSP_2, + LWSP_3, + LWSP_4, + LWSP_OK +}; + +gboolean mailmime_transport_padding_parse(gconst char * message, guint32 length, + guint32 * indx) +{ + guint32 cur_token; + gint state; + guint32 last_valid_pos; + + cur_token = * indx; + + if (cur_token >= length) + return FALSE; + + state = LWSP_1; + + while (state != LWSP_OUT) { + + if (cur_token >= length) + return FALSE; + + switch (state) { + case LWSP_1: + last_valid_pos = cur_token; + + switch (message[cur_token]) { + case '\r': + state = LWSP_2; + break; + case '\n': + state = LWSP_3; + break; + case ' ': + case '\t': + state = LWSP_4; + break; + default: + state = LWSP_OK; + break; + } + case LWSP_2: + switch (message[cur_token]) { + case '\n': + state = LWSP_3; + break; + default: + state = LWSP_OUT; + cur_token = last_valid_pos; + break; + } + case LWSP_3: + switch (message[cur_token]) { + case ' ': + case '\t': + state = LWSP_1; + break; + default: + state = LWSP_OUT; + cur_token = last_valid_pos; + break; + } + + cur_token ++; + } + } + + * indx = cur_token; + + return TRUE; +} +*/ + +/* +x tspecials := "(" / ")" / "<" / ">" / "@" / + "," / ";" / ":" / "\" / <"> + "/" / "[" / "]" / "?" / "=" + ; Must be in quoted-string, + ; to use within parameter values +*/ + +static int is_tspecials(char ch) +{ + switch (ch) { + case '(': + case ')': + case '<': + case '>': + case '@': + case ',': + case ';': + case ':': + case '\\': + case '\"': + case '/': + case '[': + case ']': + case '?': + case '=': + return TRUE; + default: + return FALSE; + } +} + +/* +x type := discrete-type / composite-type +*/ + +static int mailmime_type_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_type ** result) +{ + struct mailmime_discrete_type * discrete_type; + struct mailmime_composite_type * composite_type; + size_t cur_token; + struct mailmime_type * mime_type; + int type; + int res; + int r; + + cur_token = * indx; + + discrete_type = NULL; + composite_type = NULL; + + type = MAILMIME_TYPE_ERROR; /* XXX - removes a gcc warning */ + + r = mailmime_composite_type_parse(message, length, &cur_token, + &composite_type); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_TYPE_COMPOSITE_TYPE; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailmime_discrete_type_parse(message, length, &cur_token, + &discrete_type); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_TYPE_DISCRETE_TYPE; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + mime_type = mailmime_type_new(type, discrete_type, composite_type); + if (mime_type == NULL) { + res = r; + goto free; + } + + * result = mime_type; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (discrete_type != NULL) + mailmime_discrete_type_free(discrete_type); + if (composite_type != NULL) + mailmime_composite_type_free(composite_type); + err: + return res; +} + +/* +x value := token / quoted-string +*/ + +LIBETPAN_EXPORT +int mailmime_value_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + int r; + + r = mailimf_atom_parse(message, length, indx, result); + + if (r == MAILIMF_ERROR_PARSE) + r = mailimf_quoted_string_parse(message, length, indx, result); + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +/* +x version := "MIME-Version" ":" 1*DIGIT "." 1*DIGIT +*/ + +LIBETPAN_EXPORT +int mailmime_version_parse(const char * message, size_t length, + size_t * indx, + uint32_t * result) +{ + size_t cur_token; + uint32_t hi; + uint32_t low; + uint32_t version; + int r; + + cur_token = * indx; + + r = mailimf_number_parse(message, length, &cur_token, &hi); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '.'); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_number_parse(message, length, &cur_token, &low); + if (r != MAILIMF_NO_ERROR) + return r; + + version = (hi << 16) + low; + + * result = version; + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +x x-token := +*/ + +/* +static gboolean mailmime_x_token_parse(gconst char * message, guint32 length, + guint32 * indx, + gchar ** result) +{ + guint32 cur_token; + gchar * token; + gchar * x_token; + gboolean min_x; + + cur_token = * indx; + + if (!mailimf_char_parse(message, length, &cur_token, 'x')) { + if (!mailimf_char_parse(message, length, &cur_token, 'X')) + return FALSE; + min_x = FALSE; + } + else + min_x = TRUE; + + if (!mailimf_char_parse(message, length, &cur_token, '-')) + return FALSE; + + if (!mailmime_token_parse(message, length, &cur_token, &token)) + return FALSE; + + if (min_x) + x_token = g_strconcat("x-", token, NULL); + else + x_token = g_strconcat("X-", token, NULL); + mailmime_token_free(token); + + if (x_token == NULL) + return FALSE; + + * result = x_token; + * indx = cur_token; + + return TRUE; +} +*/ + + +LIBETPAN_EXPORT +int mailmime_language_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_language ** result) +{ + size_t cur_token; + int r; + int res; + clist * list; + struct mailmime_language * language; + + cur_token = * indx; + + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + while (1) { + char * atom; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, ','); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + res = r; + goto err; + } + + r = mailimf_atom_parse(message, length, &cur_token, &atom); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + res = r; + goto err; + } + + r = clist_append(list, atom); + if (r < 0) { + mailimf_atom_free(atom); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + + language = mailmime_language_new(list); + if (language == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = language; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimf_atom_free, NULL); + clist_free(list); + err: + return res; +} diff --git a/Sources/libetpan/low-level/mime/mailmime.h b/Sources/libetpan/low-level/mime/mailmime.h new file mode 100644 index 00000000..452c86dc --- /dev/null +++ b/Sources/libetpan/low-level/mime/mailmime.h @@ -0,0 +1,118 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime.h,v 1.18 2011/01/06 00:09:52 hoa Exp $ + */ + +#ifndef MAILMIME_H + +#define MAILMIME_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LIBETPAN_EXPORT +int mailmime_content_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_content ** result); + +LIBETPAN_EXPORT +int mailmime_description_parse(const char * message, size_t length, + size_t * indx, + char ** result); + +LIBETPAN_EXPORT +int mailmime_location_parse(const char * message, size_t length, + size_t * indx, + char ** result); + +LIBETPAN_EXPORT +int mailmime_encoding_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_mechanism ** result); + +LIBETPAN_EXPORT +int +mailmime_field_parse(struct mailimf_optional_field * field, + struct mailmime_field ** result); + +LIBETPAN_EXPORT +int mailmime_id_parse(const char * message, size_t length, + size_t * indx, char ** result); + +LIBETPAN_EXPORT +int +mailmime_fields_parse(struct mailimf_fields * + fields, + struct mailmime_fields ** + result); + +LIBETPAN_EXPORT +int mailmime_version_parse(const char * message, size_t length, + size_t * indx, + uint32_t * result); + +LIBETPAN_EXPORT +int +mailmime_extension_token_parse(const char * message, size_t length, + size_t * indx, char ** result); + +LIBETPAN_EXPORT +int mailmime_parameter_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_parameter ** result); + +LIBETPAN_EXPORT +int mailmime_value_parse(const char * message, size_t length, + size_t * indx, char ** result); + +LIBETPAN_EXPORT +int mailmime_language_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_language ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/mime/mailmime_content.c b/Sources/libetpan/low-level/mime/mailmime_content.c new file mode 100644 index 00000000..e8d838f9 --- /dev/null +++ b/Sources/libetpan/low-level/mime/mailmime_content.c @@ -0,0 +1,2267 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_content.c,v 1.47 2011/06/28 22:13:36 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailimf.h" + +#include +#include + +#include "mailmime.h" +#include "mailmime_types.h" +#include "mmapstring.h" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +/* + RFC 2045 + RFC 2046 + RFC 2047 + + RFC 2231 +*/ + + +static int mailmime_parse_with_default(const char * message, size_t length, + size_t * indx, int default_type, + struct mailmime_content * content_type, + struct mailmime_fields * mime_fields, + struct mailmime ** result); + + + +LIBETPAN_EXPORT +char * mailmime_content_charset_get(struct mailmime_content * content) +{ + char * charset; + + charset = mailmime_content_param_get(content, "charset"); + if (charset == NULL) + return "us-ascii"; + else + return charset; +} + +LIBETPAN_EXPORT +char * mailmime_content_param_get(struct mailmime_content * content, + char * name) +{ + clistiter * cur; + + for(cur = clist_begin(content->ct_parameters) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = clist_content(cur); + + if (strcasecmp(param->pa_name, name) == 0) + return param->pa_value; + } + + return NULL; +} + + +/* + boundary := 0*69 bcharsnospace +*/ + +/* + bchars := bcharsnospace / " " +*/ + +/* + bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" / + "+" / "_" / "," / "-" / "." / + "/" / ":" / "=" / "?" +*/ + +/* + body-part := <"message" as defined in RFC 822, with all + header fields optional, not starting with the + specified dash-boundary, and with the + delimiter not occurring anywhere in the + body part. Note that the semantics of a + part differ from the semantics of a message, + as described in the text.> +*/ + +/* + close-delimiter := delimiter "--" +*/ + +/* + dash-boundary := "--" boundary + ; boundary taken from the value of + ; boundary parameter of the + ; Content-Type field. +*/ + +/* + delimiter := CRLF dash-boundary +*/ + +/* + discard-text := *(*text CRLF) + ; May be ignored or discarded. +*/ + +/* + encapsulation := delimiter transport-padding + CRLF body-part +*/ + +/* + epilogue := discard-text +*/ + +/* + multipart-body := [preamble CRLF] + dash-boundary transport-padding CRLF + body-part *encapsulation + close-delimiter transport-padding + [CRLF epilogue] +*/ + +/* + preamble := discard-text +*/ + +/* + transport-padding := *LWSP-char + ; Composers MUST NOT generate + ; non-zero length transport + ; padding, but receivers MUST + ; be able to handle padding + ; added by message transports. +*/ + + +/* + ACCESS-TYPE + EXPIRATION + SIZE + PERMISSION +*/ + +/* + 5.2.3.2. The 'ftp' and 'tftp' Access-Types + NAME + SITE + + (3) Before any data are retrieved, using FTP, the user will + generally need to be asked to provide a login id and a + password for the machine named by the site parameter. + For security reasons, such an id and password are not + specified as content-type parameters, but must be + obtained from the user. + + optional : + DIRECTORY + MODE +*/ + +/* +5.2.3.3. The 'anon-ftp' Access-Type +*/ + +/* +5.2.3.4. The 'local-file' Access-Type +NAME +SITE +*/ + +/* +5.2.3.5. The 'mail-server' Access-Type +SERVER +SUBJECT +*/ + + +enum { + PREAMBLE_STATE_A0, + PREAMBLE_STATE_A, + PREAMBLE_STATE_A1, + PREAMBLE_STATE_B, + PREAMBLE_STATE_C, + PREAMBLE_STATE_D, + PREAMBLE_STATE_E +}; + +static int mailmime_preamble_parse(const char * message, size_t length, + size_t * indx, int beol) +{ + int state; + size_t cur_token; + + cur_token = * indx; + if (beol) + state = PREAMBLE_STATE_A0; + else + state = PREAMBLE_STATE_A; + + while (state != PREAMBLE_STATE_E) { + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch (state) { + case PREAMBLE_STATE_A0: + switch (message[cur_token]) { + case '-': + state = PREAMBLE_STATE_A1; + break; + case '\r': + state = PREAMBLE_STATE_B; + break; + case '\n': + state = PREAMBLE_STATE_C; + break; + default: + state = PREAMBLE_STATE_A; + break; + } + break; + + case PREAMBLE_STATE_A: + switch (message[cur_token]) { + case '\r': + state = PREAMBLE_STATE_B; + break; + case '\n': + state = PREAMBLE_STATE_C; + break; + default: + state = PREAMBLE_STATE_A; + break; + } + break; + + case PREAMBLE_STATE_A1: + switch (message[cur_token]) { + case '-': + state = PREAMBLE_STATE_E; + break; + case '\r': + state = PREAMBLE_STATE_B; + break; + case '\n': + state = PREAMBLE_STATE_C; + break; + default: + state = PREAMBLE_STATE_A; + break; + } + break; + + case PREAMBLE_STATE_B: + switch (message[cur_token]) { + case '\r': + state = PREAMBLE_STATE_B; + break; + case '\n': + state = PREAMBLE_STATE_C; + break; + case '-': + state = PREAMBLE_STATE_D; + break; + default: + state = PREAMBLE_STATE_A0; + break; + } + break; + + case PREAMBLE_STATE_C: + switch (message[cur_token]) { + case '-': + state = PREAMBLE_STATE_D; + break; + case '\r': + state = PREAMBLE_STATE_B; + break; + case '\n': + state = PREAMBLE_STATE_C; + break; + default: + state = PREAMBLE_STATE_A0; + break; + } + break; + + case PREAMBLE_STATE_D: + switch (message[cur_token]) { + case '-': + state = PREAMBLE_STATE_E; + break; + default: + state = PREAMBLE_STATE_A; + break; + } + break; + } + + cur_token ++; + } + + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +static int mailmime_boundary_parse(const char * message, size_t length, + size_t * indx, char * boundary) +{ + size_t cur_token; + size_t len; + + cur_token = * indx; + + len = strlen(boundary); + + if (cur_token + len >= length) + return MAILIMF_ERROR_PARSE; + + if (strncmp(message + cur_token, boundary, len) != 0) + return MAILIMF_ERROR_PARSE; + + cur_token += len; + + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +static int is_wsp(char ch) +{ + if ((ch == ' ') || (ch == '\t')) + return TRUE; + + return FALSE; +} + +static int mailmime_lwsp_parse(const char * message, size_t length, + size_t * indx) +{ + size_t cur_token; + + cur_token = * indx; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + while (is_wsp(message[cur_token])) { + cur_token ++; + if (cur_token >= length) + break; + } + + if (cur_token == * indx) + return MAILIMF_ERROR_PARSE; + + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +gboolean mailimf_crlf_parse(gchar * message, guint32 length, guint32 * indx) +*/ + +enum { + BODY_PART_DASH2_STATE_0, + BODY_PART_DASH2_STATE_1, + BODY_PART_DASH2_STATE_2, + BODY_PART_DASH2_STATE_3, + BODY_PART_DASH2_STATE_4, + BODY_PART_DASH2_STATE_5, + BODY_PART_DASH2_STATE_6 +}; + +static int +mailmime_body_part_dash2_parse(const char * message, size_t length, + size_t * indx, char * boundary, + const char ** result, size_t * result_size) +{ + int state; + size_t cur_token; + size_t size; + size_t begin_text; + size_t end_text; + int r; + + cur_token = * indx; + state = BODY_PART_DASH2_STATE_0; + + begin_text = cur_token; + end_text = length; + + while (state != BODY_PART_DASH2_STATE_5) { + + if (cur_token >= length) + break; + + switch(state) { + + case BODY_PART_DASH2_STATE_0: + switch (message[cur_token]) { + case '\r': + state = BODY_PART_DASH2_STATE_1; + break; + case '\n': + state = BODY_PART_DASH2_STATE_2; + break; + default: + state = BODY_PART_DASH2_STATE_0; + break; + } + break; + + case BODY_PART_DASH2_STATE_1: + switch (message[cur_token]) { + case '\n': + state = BODY_PART_DASH2_STATE_2; + break; + default: + state = BODY_PART_DASH2_STATE_0; + break; + } + break; + + case BODY_PART_DASH2_STATE_2: + switch (message[cur_token]) { + case '-': + end_text = cur_token; + state = BODY_PART_DASH2_STATE_3; + break; + case '\r': + state = BODY_PART_DASH2_STATE_1; + break; + case '\n': + state = BODY_PART_DASH2_STATE_2; + break; + default: + state = BODY_PART_DASH2_STATE_0; + break; + } + break; + + case BODY_PART_DASH2_STATE_3: + switch (message[cur_token]) { + case '\r': + state = BODY_PART_DASH2_STATE_1; + break; + case '\n': + state = BODY_PART_DASH2_STATE_2; + break; + case '-': + state = BODY_PART_DASH2_STATE_4; + break; + default: + state = BODY_PART_DASH2_STATE_0; + break; + } + break; + + case BODY_PART_DASH2_STATE_4: + r = mailmime_boundary_parse(message, length, &cur_token, boundary); + if (r == MAILIMF_NO_ERROR) + state = BODY_PART_DASH2_STATE_5; + else + state = BODY_PART_DASH2_STATE_6; + + break; + } + + if ((state != BODY_PART_DASH2_STATE_5) && + (state != BODY_PART_DASH2_STATE_6)) + cur_token ++; + + if (state == BODY_PART_DASH2_STATE_6) + state = BODY_PART_DASH2_STATE_0; + } + + size = end_text - begin_text; + + if (size >= 1) { + if (message[end_text - 1] == '\r') { + end_text --; + size --; + } + else if (size >= 1) { + if (message[end_text - 1] == '\n') { + end_text --; + size --; + if (size >= 1) { + if (message[end_text - 1] == '\r') { + end_text --; + size --; + } + } + } + } + } + + size = end_text - begin_text; + if (size == 0) + return MAILIMF_ERROR_PARSE; + + * result = message + begin_text; + * result_size = size; + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +static int +mailmime_body_part_dash2_transport_crlf_parse(const char * message, + size_t length, + size_t * indx, char * boundary, + const char ** result, size_t * result_size) +{ + size_t cur_token; + int r; + const char * data_str; + size_t data_size; + const char * begin_text; + const char * end_text; + + cur_token = * indx; + + begin_text = message + cur_token; + end_text = message + cur_token; + + while (1) { + r = mailmime_body_part_dash2_parse(message, length, &cur_token, + boundary, &data_str, &data_size); + if (r == MAILIMF_NO_ERROR) { + end_text = data_str + data_size; + } + else { + return r; + } + + /* parse transport-padding */ + while (1) { + r = mailmime_lwsp_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + return r; + } + } + + r = mailimf_crlf_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + break; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + return r; + } + } + + * indx = cur_token; + * result = begin_text; + * result_size = end_text - begin_text; + + return MAILIMF_NO_ERROR; +} + +static int mailmime_multipart_close_parse(const char * message, size_t length, + size_t * indx); + +static int +mailmime_body_part_dash2_close_parse(const char * message, + size_t length, + size_t * indx, char * boundary, + const char ** result, size_t * result_size) +{ + size_t cur_token; + int r; + const char * data_str; + size_t data_size; + const char * begin_text; + const char * end_text; + + cur_token = * indx; + + begin_text = message + cur_token; + end_text = message + cur_token; + + while (1) { + r = mailmime_body_part_dash2_parse(message, length, + &cur_token, boundary, &data_str, &data_size); + if (r == MAILIMF_NO_ERROR) { + end_text = data_str + data_size; + } + else { + return r; + } + + /* + There's no MIME multipart close bounary. + Ignore the issue and succeed. + https://github.com/MailCore/mailcore2/issues/122 + */ + if (cur_token >= length) { + break; + } + + r = mailmime_multipart_close_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + break; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + return r; + } + } + + * indx = cur_token; + * result = begin_text; + * result_size = end_text - begin_text; + + return MAILIMF_NO_ERROR; +} + +enum { + MULTIPART_CLOSE_STATE_0, + MULTIPART_CLOSE_STATE_1, + MULTIPART_CLOSE_STATE_2, + MULTIPART_CLOSE_STATE_3, + MULTIPART_CLOSE_STATE_4 +}; + +static int mailmime_multipart_close_parse(const char * message, size_t length, + size_t * indx) +{ + int state; + size_t cur_token; + + cur_token = * indx; + state = MULTIPART_CLOSE_STATE_0; + + while (state != MULTIPART_CLOSE_STATE_4) { + + switch(state) { + + case MULTIPART_CLOSE_STATE_0: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch (message[cur_token]) { + case '-': + state = MULTIPART_CLOSE_STATE_1; + break; + default: + return MAILIMF_ERROR_PARSE; + } + break; + + case MULTIPART_CLOSE_STATE_1: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch (message[cur_token]) { + case '-': + state = MULTIPART_CLOSE_STATE_2; + break; + default: + return MAILIMF_ERROR_PARSE; + } + break; + + case MULTIPART_CLOSE_STATE_2: + if (cur_token >= length) { + state = MULTIPART_CLOSE_STATE_4; + break; + } + + switch (message[cur_token]) { + case ' ': + state = MULTIPART_CLOSE_STATE_2; + break; + case '\t': + state = MULTIPART_CLOSE_STATE_2; + break; + case '\r': + state = MULTIPART_CLOSE_STATE_3; + break; + case '\n': + state = MULTIPART_CLOSE_STATE_4; + break; + default: + state = MULTIPART_CLOSE_STATE_4; + break; + } + break; + + case MULTIPART_CLOSE_STATE_3: + if (cur_token >= length) { + state = MULTIPART_CLOSE_STATE_4; + break; + } + + switch (message[cur_token]) { + case '\n': + state = MULTIPART_CLOSE_STATE_4; + break; + default: + state = MULTIPART_CLOSE_STATE_4; + break; + } + break; + } + + cur_token ++; + } + + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +enum { + MULTIPART_NEXT_STATE_0, + MULTIPART_NEXT_STATE_1, + MULTIPART_NEXT_STATE_2 +}; + +LIBETPAN_EXPORT +int mailmime_multipart_next_parse(const char * message, size_t length, + size_t * indx) +{ + int state; + size_t cur_token; + + cur_token = * indx; + state = MULTIPART_NEXT_STATE_0; + + while (state != MULTIPART_NEXT_STATE_2) { + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch(state) { + + case MULTIPART_NEXT_STATE_0: + switch (message[cur_token]) { + case ' ': + state = MULTIPART_NEXT_STATE_0; + break; + case '\t': + state = MULTIPART_NEXT_STATE_0; + break; + case '\r': + state = MULTIPART_NEXT_STATE_1; + break; + case '\n': + state = MULTIPART_NEXT_STATE_2; + break; + default: + return MAILIMF_ERROR_PARSE; + } + break; + + case MULTIPART_NEXT_STATE_1: + switch (message[cur_token]) { + case '\n': + state = MULTIPART_NEXT_STATE_2; + break; + default: + return MAILIMF_ERROR_PARSE; + } + break; + } + + cur_token ++; + } + + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +static int +mailmime_multipart_body_parse(const char * message, size_t length, + size_t * indx, char * boundary, + int default_subtype, + clist ** result, + struct mailmime_data ** p_preamble, + struct mailmime_data ** p_epilogue) +{ + size_t cur_token; + clist * list; + int r; + int res; +#if 0 + size_t begin; +#endif + size_t preamble_begin; + size_t preamble_length; + size_t preamble_end; + size_t epilogue_begin; + size_t epilogue_length; + struct mailmime_data * preamble; + struct mailmime_data * epilogue; + size_t part_begin; + int final_part; + + preamble = NULL; + epilogue = NULL; + + cur_token = * indx; + preamble_begin = cur_token; + + preamble_end = preamble_begin; + + r = mailmime_preamble_parse(message, length, &cur_token, 1); + if (r == MAILIMF_NO_ERROR) { + while (1) { + + preamble_end = cur_token; + r = mailmime_boundary_parse(message, length, &cur_token, boundary); + if (r == MAILIMF_NO_ERROR) { + break; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + + r = mailmime_preamble_parse(message, length, &cur_token, 0); + if (r == MAILIMF_NO_ERROR) { + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + res = r; + goto err; + } + } + } + + preamble_end -= 2; + if (preamble_end != preamble_begin) { + /* try to find the real end of the preamble (strip CR LF) */ + if (message[preamble_end - 1] == '\n') { + preamble_end --; + if (preamble_end - 1 >= preamble_begin) { + if (message[preamble_end - 1] == '\r') + preamble_end --; + } + } + else if (message[preamble_end - 1] == '\r') { + preamble_end --; + } + } + if (preamble_end > preamble_begin) { + preamble_length = preamble_end - preamble_begin; + } else { + preamble_length = 0; + } + + part_begin = cur_token; + while (1) { + r = mailmime_lwsp_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_crlf_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + part_begin = cur_token; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + break; + } + else { + res = r; + goto err; + } + } + + cur_token = part_begin; + + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + final_part = 0; + + while (!final_part) { + size_t bp_token; + struct mailmime * mime_bp; + const char * data_str; + size_t data_size; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + + r = mailmime_body_part_dash2_transport_crlf_parse(message, length, + &cur_token, boundary, &data_str, &data_size); + if (r == MAILIMF_ERROR_PARSE) { + r = mailmime_body_part_dash2_close_parse(message, length, + &cur_token, boundary, &data_str, &data_size); + if (r == MAILIMF_NO_ERROR) { + final_part = 1; + } + } + + if (r == MAILIMF_NO_ERROR) { + bp_token = 0; + + r = mailimf_optional_fields_parse(data_str, data_size, + &bp_token, &fields); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free; + } + + r = mailimf_crlf_parse(data_str, data_size, &bp_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + mailimf_fields_free(fields); + res = r; + goto free; + } + + mime_fields = NULL; + r = mailmime_fields_parse(fields, &mime_fields); + mailimf_fields_free(fields); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free; + } + + r = mailmime_parse_with_default(data_str, data_size, + &bp_token, default_subtype, NULL, + mime_fields, &mime_bp); + if (r == MAILIMF_NO_ERROR) { + r = clist_append(list, mime_bp); + if (r < 0) { + mailmime_free(mime_bp); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + else if (r == MAILIMF_ERROR_PARSE) { + mailmime_fields_free(mime_fields); + break; + } + else { + mailmime_fields_free(mime_fields); + res = r; + goto free; + } + + r = mailmime_multipart_next_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + } + else { + res = r; + goto free; + } + } + + epilogue_begin = length; + /* parse transport-padding */ + while (1) { + r = mailmime_lwsp_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free; + } + + if (r == MAILIMF_ERROR_PARSE) + break; + } + + r = mailimf_crlf_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + epilogue_begin = cur_token; + } + else if (r != MAILIMF_ERROR_PARSE) { + res = r; + goto free; + } + + /* add preamble and epilogue */ + + epilogue_length = length - epilogue_begin; + + if (preamble_length != 0) { + preamble = mailmime_data_new(MAILMIME_DATA_TEXT, + MAILMIME_MECHANISM_8BIT, 1, + message + preamble_begin, preamble_length, + NULL); + if (preamble == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + + if (epilogue_length != 0) { + epilogue = mailmime_data_new(MAILMIME_DATA_TEXT, + MAILMIME_MECHANISM_8BIT, 1, + message + epilogue_begin, epilogue_length, + NULL); + if (epilogue == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + + /* end of preamble and epilogue */ + + cur_token = length; + + * result = list; + * p_preamble = preamble; + * p_epilogue = epilogue; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (epilogue != NULL) + mailmime_data_free(epilogue); + if (preamble != NULL) + mailmime_data_free(preamble); + clist_foreach(list, (clist_func) mailmime_free, NULL); + clist_free(list); + err: + return res; +} + +enum { + MAILMIME_DEFAULT_TYPE_TEXT_PLAIN, + MAILMIME_DEFAULT_TYPE_MESSAGE +}; + + +LIBETPAN_EXPORT +int mailmime_parse(const char * message, size_t length, + size_t * indx, struct mailmime ** result) +{ + struct mailmime * mime; + int r; + int res; + struct mailmime_content * content_message; + size_t cur_token; + struct mailmime_fields * mime_fields; + const char * data_str; + size_t data_size; + size_t bp_token; + + cur_token = * indx; + + content_message = mailmime_get_content_message(); + if (content_message == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + +#if 0 + mime_fields = mailmime_fields_new_with_data(content_message, + NULL, + NULL, + NULL, + NULL, + NULL); + if (mime_fields == NULL) { + mailmime_content_free(content_message); + res = MAILIMF_ERROR_MEMORY; + goto err; + } +#endif + mime_fields = mailmime_fields_new_empty(); + if (mime_fields == NULL) { + mailmime_content_free(content_message); + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + data_str = message + cur_token; + data_size = length - cur_token; + + bp_token = 0; + r = mailmime_parse_with_default(data_str, data_size, + &bp_token, MAILMIME_DEFAULT_TYPE_TEXT_PLAIN, + content_message, mime_fields, &mime); + cur_token += bp_token; + if (r != MAILIMF_NO_ERROR) { + mailmime_fields_free(mime_fields); + res = r; + goto free; + } + + * indx = cur_token; + * result = mime; + + return MAILIMF_NO_ERROR; + + free: + mailmime_fields_free(mime_fields); + err: + return res; +} + + +LIBETPAN_EXPORT +char * mailmime_extract_boundary(struct mailmime_content * content_type) +{ + char * boundary; + + boundary = mailmime_content_param_get(content_type, "boundary"); + + /* XXX - this should be unquoted properly, should use + mailimf_quoted_string_parse() */ + if (boundary != NULL) { + size_t len; + char * new_boundary; + + len = strlen(boundary); + new_boundary = malloc(len + 1); + if (new_boundary == NULL) + return NULL; + + if (boundary[0] == '"') { + strncpy(new_boundary, boundary + 1, len - 2); + new_boundary[len - 2] = 0; + } + else + strcpy(new_boundary, boundary); + + boundary = new_boundary; + } + + return boundary; +} + +static void remove_unparsed_mime_headers(struct mailimf_fields * fields) +{ + clistiter * cur; + + cur = clist_begin(fields->fld_list); + while (cur != NULL) { + struct mailimf_field * field; + int delete; + + field = clist_content(cur); + + switch (field->fld_type) { + case MAILIMF_FIELD_OPTIONAL_FIELD: + delete = 0; + if (strncasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-", 8) == 0) { + char * name; + + name = field->fld_data.fld_optional_field->fld_name + 8; + if ((strcasecmp(name, "Type") == 0) + || (strcasecmp(name, "Transfer-Encoding") == 0) + || (strcasecmp(name, "ID") == 0) + || (strcasecmp(name, "Description") == 0) + || (strcasecmp(name, "Disposition") == 0) + || (strcasecmp(name, "Language") == 0)) { + delete = 1; + } + } + else if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "MIME-Version") == 0) { + delete = 1; + } + + if (delete) { + cur = clist_delete(fields->fld_list, cur); + mailimf_field_free(field); + } + else { + cur = clist_next(cur); + } + break; + + default: + cur = clist_next(cur); + } + } +} + +static int mailmime_parse_with_default(const char * message, size_t length, + size_t * indx, int default_type, + struct mailmime_content * content_type, + struct mailmime_fields * mime_fields, + struct mailmime ** result) +{ + size_t cur_token; + + int body_type; + + int encoding; + struct mailmime_data * body; + char * boundary; + struct mailimf_fields * fields; + clist * list; + struct mailmime * msg_mime; + + struct mailmime * mime; + + int r; + int res; + struct mailmime_data * preamble; + struct mailmime_data * epilogue; + + /* + note that when this function is called, content type is always detached, + even if the function fails + */ + + preamble = NULL; + epilogue = NULL; + + cur_token = * indx; + + /* get content type */ + + if (content_type == NULL) { + if (mime_fields != NULL) { + clistiter * cur; + + for(cur = clist_begin(mime_fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + if (field->fld_type == MAILMIME_FIELD_TYPE) { + content_type = field->fld_data.fld_content; + + /* detach content type from list */ + field->fld_data.fld_content = NULL; + clist_delete(mime_fields->fld_list, cur); + mailmime_field_free(field); + /* + there may be a leak due to the detached content type + in case the function fails + */ + break; + } + } + } + } + + /* set default type if no content type */ + + if (content_type == NULL) { + /* content_type is detached, in any case, we will have to free it */ + if (default_type == MAILMIME_DEFAULT_TYPE_TEXT_PLAIN) { + content_type = mailmime_get_content_text(); + if (content_type == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + } + else /* message */ { + body_type = MAILMIME_MESSAGE; + + content_type = mailmime_get_content_message(); + if (content_type == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + } + } + + /* get the body type */ + + boundary = NULL; /* XXX - removes a gcc warning */ + + switch (content_type->ct_type->tp_type) { + case MAILMIME_TYPE_COMPOSITE_TYPE: + switch (content_type->ct_type->tp_data.tp_composite_type->ct_type) { + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + boundary = mailmime_extract_boundary(content_type); + + if (boundary == NULL) + body_type = MAILMIME_SINGLE; + else + body_type = MAILMIME_MULTIPLE; + break; + + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + + if (strcasecmp(content_type->ct_subtype, "rfc822") == 0) + body_type = MAILMIME_MESSAGE; + else + body_type = MAILMIME_SINGLE; + break; + + default: + res = MAILIMF_ERROR_INVAL; + goto free_content; + } + break; + + default: /* MAILMIME_TYPE_DISCRETE_TYPE */ + body_type = MAILMIME_SINGLE; + break; + } + + /* set body */ + + if (mime_fields != NULL) + encoding = mailmime_transfer_encoding_get(mime_fields); + else + encoding = MAILMIME_MECHANISM_8BIT; + + if (body_type == MAILMIME_MESSAGE) { + switch (encoding) { + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + case MAILMIME_MECHANISM_BASE64: + body_type = MAILMIME_SINGLE; + break; + } + } + + cur_token = * indx; + body = mailmime_data_new(MAILMIME_DATA_TEXT, encoding, 1, + message + cur_token, length - cur_token, + NULL); + if (body == NULL) { + free(boundary); + res = MAILIMF_ERROR_MEMORY; + goto free_content; + } + + /* in case of composite, parse the sub-part(s) */ + + list = NULL; + msg_mime = NULL; + fields = NULL; + + switch (body_type) { + case MAILMIME_MESSAGE: + { + struct mailmime_fields * submime_fields; + + r = mailimf_envelope_and_optional_fields_parse(message, length, + &cur_token, &fields); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free_content; + } + + r = mailimf_crlf_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + mailimf_fields_free(fields); + res = r; + goto free_content; + } + + submime_fields = NULL; + r = mailmime_fields_parse(fields, &submime_fields); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + mailimf_fields_free(fields); + res = r; + goto free_content; + } + + remove_unparsed_mime_headers(fields); + + r = mailmime_parse_with_default(message, length, + &cur_token, MAILMIME_DEFAULT_TYPE_TEXT_PLAIN, + NULL, submime_fields, &msg_mime); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + mailmime_fields_free(mime_fields); + msg_mime = NULL; + } + else { + mailmime_fields_free(mime_fields); + res = r; + goto free_content; + } + } + + break; + + case MAILMIME_MULTIPLE: + { + int default_subtype; + + default_subtype = MAILMIME_DEFAULT_TYPE_TEXT_PLAIN; + if (content_type != NULL) + if (strcasecmp(content_type->ct_subtype, "digest") == 0) + default_subtype = MAILMIME_DEFAULT_TYPE_MESSAGE; + + cur_token = * indx; + r = mailmime_multipart_body_parse(message, length, + &cur_token, boundary, + default_subtype, + &list, &preamble, &epilogue); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_content; + } + } + else { + res = r; + goto free_content; + } + + free(boundary); + } + break; + + default: /* MAILMIME_SINGLE */ + /* do nothing */ + break; + } + + mime = mailmime_new(body_type, message, length, + mime_fields, content_type, + body, preamble, /* preamble */ + epilogue, /* epilogue */ + list, fields, msg_mime); + if (mime == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = mime; + * indx = length; + + return MAILIMF_NO_ERROR; + + free: + if (epilogue != NULL) + mailmime_data_free(epilogue); + if (preamble != NULL) + mailmime_data_free(preamble); + if (msg_mime != NULL) + mailmime_free(msg_mime); + if (list != NULL) { + clist_foreach(list, (clist_func) mailmime_free, NULL); + clist_free(list); + } + free_content: + mailmime_content_free(content_type); + err: + return res; +} + +static int mailmime_get_section_list(struct mailmime * mime, + clistiter * list, struct mailmime ** result) +{ + uint32_t id; + struct mailmime * data; + struct mailmime * submime; + + if (list == NULL) { + * result = mime; + return MAILIMF_NO_ERROR; + } + + id = * ((uint32_t *) clist_content(list)); + + data = NULL; + switch (mime->mm_type) { + case MAILMIME_SINGLE: + return MAILIMF_ERROR_INVAL; + + case MAILMIME_MULTIPLE: + data = clist_nth_data(mime->mm_data.mm_multipart.mm_mp_list, id - 1); + if (data == NULL) + return MAILIMF_ERROR_INVAL; + + if (clist_next(list) != NULL) + return mailmime_get_section_list(data, clist_next(list), result); + else { + * result = data; + return MAILIMF_NO_ERROR; + } + + case MAILMIME_MESSAGE: + submime = mime->mm_data.mm_message.mm_msg_mime; + switch (submime->mm_type) { + case MAILMIME_MULTIPLE: + data = clist_nth_data(submime->mm_data.mm_multipart.mm_mp_list, id - 1); + if (data == NULL) + return MAILIMF_ERROR_INVAL; + return mailmime_get_section_list(data, clist_next(list), result); + + default: + if (id != 1) + return MAILIMF_ERROR_INVAL; + + data = submime; + if (data == NULL) + return MAILIMF_ERROR_INVAL; + + return mailmime_get_section_list(data, clist_next(list), result); + } + break; + + default: + return MAILIMF_ERROR_INVAL; + } +} + +LIBETPAN_EXPORT +int mailmime_get_section(struct mailmime * mime, + struct mailmime_section * section, + struct mailmime ** result) +{ + return mailmime_get_section_list(mime, + clist_begin(section->sec_list), result); +} + + + + + + + + + + + + + + + +/* ************************************************************************* */ +/* MIME part decoding */ + +static inline signed char get_base64_value(char ch) +{ + if ((ch >= 'A') && (ch <= 'Z')) + return ch - 'A'; + if ((ch >= 'a') && (ch <= 'z')) + return ch - 'a' + 26; + if ((ch >= '0') && (ch <= '9')) + return ch - '0' + 52; + switch (ch) { + case '+': + return 62; + case '/': + return 63; + case '=': /* base64 padding */ + return -1; + default: + return -1; + } +} + +static int mailmime_base64_body_parse_impl( + const char * message, size_t length, + size_t * indx, char ** result, + size_t * result_len, int partial) +{ + size_t cur_token, last_full_token_end; + char chunk[4]; + int chunk_index; + char out[3]; + MMAPString * mmapstr; + int res; + int r; + size_t written; + + chunk[0] = 0; + chunk[1] = 0; + chunk[2] = 0; + chunk[3] = 0; + + cur_token = * indx; + last_full_token_end = * indx; + chunk_index = 0; + written = 0; + + mmapstr = mmap_string_sized_new((length - cur_token) * 3 / 4); + if (mmapstr == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + while (1) { + signed char value; + + value = -1; + while (value == -1) { + + if (cur_token >= length) + break; + + value = get_base64_value(message[cur_token]); + cur_token ++; + } + + if (value == -1) + break; + + chunk[chunk_index] = value; + chunk_index ++; + + if (chunk_index == 4) { + out[0] = (chunk[0] << 2) | (chunk[1] >> 4); + out[1] = (chunk[1] << 4) | (chunk[2] >> 2); + out[2] = (chunk[2] << 6) | (chunk[3]); + + chunk[0] = 0; + chunk[1] = 0; + chunk[2] = 0; + chunk[3] = 0; + + chunk_index = 0; + last_full_token_end = cur_token; + + if (mmap_string_append_len(mmapstr, out, 3) == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + written += 3; + } + } + + if (chunk_index != 0 && !partial) { + size_t len; + + len = 0; + out[0] = (chunk[0] << 2) | (chunk[1] >> 4); + len ++; + + if (chunk_index >= 3) { + out[1] = (chunk[1] << 4) | (chunk[2] >> 2); + len ++; + } + + if (mmap_string_append_len(mmapstr, out, len) == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + written += len; + } + + if (partial) { + cur_token = last_full_token_end; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * indx = cur_token; + * result = mmapstr->str; + * result_len = written; + + return MAILIMF_NO_ERROR; + + free: + mmap_string_free(mmapstr); + err: + return res; +} + +int mailmime_base64_body_parse(const char * message, size_t length, + size_t * indx, char ** result, + size_t * result_len) +{ + return mailmime_base64_body_parse_impl(message, length, indx, result, result_len, 0); +} + + + +static inline int hexa_to_char(char hexdigit) +{ + if ((hexdigit >= '0') && (hexdigit <= '9')) + return hexdigit - '0'; + if ((hexdigit >= 'a') && (hexdigit <= 'f')) + return hexdigit - 'a' + 10; + if ((hexdigit >= 'A') && (hexdigit <= 'F')) + return hexdigit - 'A' + 10; + return 0; +} + +static inline char to_char(const char * hexa) +{ + return (hexa_to_char(hexa[0]) << 4) | hexa_to_char(hexa[1]); +} + +enum { + STATE_NORMAL, + STATE_CODED, + STATE_OUT, + STATE_CR +}; + + +static int write_decoded_qp(MMAPString * mmapstr, + const char * start, size_t count) +{ + if (mmap_string_append_len(mmapstr, start, count) == NULL) + return MAILIMF_ERROR_MEMORY; + + return MAILIMF_NO_ERROR; +} + + +#define WRITE_MAX_QP 512 + +static int mailmime_quoted_printable_body_parse_impl( + const char * message, size_t length, + size_t * indx, char ** result, + size_t * result_len, int in_header, + int partial) +{ + size_t cur_token; + int state; + int r; + char ch; + size_t count; + const char * start; + MMAPString * mmapstr; + int res; + size_t written; + + state = STATE_NORMAL; + cur_token = * indx; + + count = 0; + start = message + cur_token; + written = 0; + + mmapstr = mmap_string_sized_new(length - cur_token); + if (mmapstr == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + +#if 0 + if (length >= 1) { + if (message[length - 1] == '\n') { + length --; + if (length >= 1) + if (message[length - 1] == '\r') { + length --; + } + } + } +#endif + + while (state != STATE_OUT) { + + if (cur_token >= length) { + state = STATE_OUT; + if (partial) { + cur_token = length; + } + break; + } + + switch (state) { + + case STATE_CODED: + + if (count > 0) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; + } + + switch (message[cur_token]) { + case '=': + if (cur_token + 1 >= length) { + if (partial) { + state = STATE_OUT; + break; + } + /* error but ignore it */ + state = STATE_NORMAL; + start = message + cur_token; + cur_token ++; + count ++; + break; + } + + switch (message[cur_token + 1]) { + + case '\n': + cur_token += 2; + + start = message + cur_token; + + state = STATE_NORMAL; + break; + + case '\r': + if (cur_token + 2 >= length) { + state = STATE_OUT; + break; + } + + if (message[cur_token + 2] == '\n') + cur_token += 3; + else + cur_token += 2; + + start = message + cur_token; + + state = STATE_NORMAL; + + break; + + default: + if (cur_token + 2 >= length) { + if (partial) { + state = STATE_OUT; + break; + } + /* error but ignore it */ + cur_token ++; + + start = message + cur_token; + + count ++; + state = STATE_NORMAL; + break; + } + +#if 0 + /* flush before writing additionnal information */ + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; +#endif + + ch = to_char(message + cur_token + 1); + + if (mmap_string_append_c(mmapstr, ch) == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + cur_token += 3; + written ++; + + start = message + cur_token; + + state = STATE_NORMAL; + break; + } + break; + } + break; /* end of STATE_ENCODED */ + + case STATE_NORMAL: + + switch (message[cur_token]) { + + case '=': + state = STATE_CODED; + break; + + case '\n': + /* flush before writing additionnal information */ + if (count > 0) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + + count = 0; + } + + r = write_decoded_qp(mmapstr, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += 2; + cur_token ++; + start = message + cur_token; + break; + + case '\r': + state = STATE_CR; + cur_token ++; + break; + + case '_': + if (in_header) { + if (count > 0) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; + } + + if (mmap_string_append_c(mmapstr, ' ') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + written ++; + cur_token ++; + start = message + cur_token; + + break; + } + /* WARINING : must be followed by switch default action */ + + default: + if (count >= WRITE_MAX_QP) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; + start = message + cur_token; + } + + count ++; + cur_token ++; + break; + } + break; /* end of STATE_NORMAL */ + + case STATE_CR: + switch (message[cur_token]) { + + case '\n': + /* flush before writing additionnal information */ + if (count > 0) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; + } + + r = write_decoded_qp(mmapstr, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += 2; + cur_token ++; + start = message + cur_token; + state = STATE_NORMAL; + break; + + default: + /* flush before writing additionnal information */ + if (count > 0) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; + } + + start = message + cur_token; + + r = write_decoded_qp(mmapstr, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += 2; + state = STATE_NORMAL; + } + break; /* end of STATE_CR */ + } + } + + if (count > 0) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * indx = cur_token; + * result = mmapstr->str; + * result_len = written; + + return MAILIMF_NO_ERROR; + + free: + mmap_string_free(mmapstr); + err: + return res; +} + +int mailmime_quoted_printable_body_parse(const char * message, size_t length, + size_t * indx, char ** result, + size_t * result_len, int in_header) +{ + return mailmime_quoted_printable_body_parse_impl(message, length, indx, + result, result_len, in_header, FALSE); +} + +int mailmime_binary_body_parse(const char * message, size_t length, + size_t * indx, char ** result, + size_t * result_len) +{ + MMAPString * mmapstr; + size_t cur_token; + int r; + int res; + + cur_token = * indx; + +#if 0 /* preserve CR LF at the end of parts */ + if (length >= 1) { + if (message[length - 1] == '\n') { + length --; + if (length >= 1) + if (message[length - 1] == '\r') + length --; + } + } +#endif + + mmapstr = mmap_string_new_len(message + cur_token, length - cur_token); + if (mmapstr == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * indx = length; + * result = mmapstr->str; + * result_len = length - cur_token; + + return MAILIMF_NO_ERROR; + + free: + mmap_string_free(mmapstr); + err: + return res; +} + + +static int mailmime_part_parse_impl(const char * message, size_t length, + size_t * indx, + int encoding, char ** result, size_t * result_len, int partial) +{ + switch (encoding) { + case MAILMIME_MECHANISM_BASE64: + return mailmime_base64_body_parse_impl(message, length, indx, + result, result_len, partial); + + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + return mailmime_quoted_printable_body_parse_impl(message, length, indx, + result, result_len, FALSE, partial); + + case MAILMIME_MECHANISM_7BIT: + case MAILMIME_MECHANISM_8BIT: + case MAILMIME_MECHANISM_BINARY: + default: + return mailmime_binary_body_parse(message, length, indx, + result, result_len); + } +} + +int mailmime_part_parse(const char * message, size_t length, + size_t * indx, + int encoding, char ** result, size_t * result_len) +{ + return mailmime_part_parse_impl(message, length, indx, + encoding, result, result_len, FALSE); +} + +int mailmime_part_parse_partial(const char * message, size_t length, + size_t * indx, + int encoding, char ** result, size_t * result_len) +{ + return mailmime_part_parse_impl(message, length, indx, + encoding, result, result_len, TRUE); +} + +int mailmime_get_section_id(struct mailmime * mime, + struct mailmime_section ** result) +{ + clist * list; + int res; + struct mailmime_section * section_id; + int r; + + if (mime->mm_parent == NULL) { + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + section_id = mailmime_section_new(list); + if (section_id == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + } + else { + uint32_t id; + uint32_t * p_id; + clistiter * cur; + struct mailmime * parent; + + r = mailmime_get_section_id(mime->mm_parent, §ion_id); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + parent = mime->mm_parent; + switch (parent->mm_type) { + case MAILMIME_MULTIPLE: + id = 1; + for(cur = clist_begin(parent->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + if (clist_content(cur) == mime) + break; + id ++; + } + + p_id = malloc(sizeof(* p_id)); + if (p_id == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + * p_id = id; + + r = clist_append(section_id->sec_list, p_id); + if (r < 0) { + free(p_id); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + break; + + case MAILMIME_MESSAGE: + if ((mime->mm_type == MAILMIME_SINGLE) || + (mime->mm_type == MAILMIME_MESSAGE)) { + p_id = malloc(sizeof(* p_id)); + if (p_id == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + * p_id = 1; + + r = clist_append(section_id->sec_list, p_id); + if (r < 0) { + free(p_id); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + } + } + + * result = section_id; + + return MAILIMF_NO_ERROR; + + free: + mailmime_section_free(section_id); + err: + return res; +} diff --git a/Sources/libetpan/low-level/mime/mailmime_content.h b/Sources/libetpan/low-level/mime/mailmime_content.h new file mode 100644 index 00000000..c82c6cf1 --- /dev/null +++ b/Sources/libetpan/low-level/mime/mailmime_content.h @@ -0,0 +1,173 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_content.h,v 1.16 2008/02/20 22:15:52 hoa Exp $ + */ + +#ifndef MAILMIME_CONTENT_H + +#define MAILMIME_CONTENT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +LIBETPAN_EXPORT +char * mailmime_content_charset_get(struct mailmime_content * content); + +LIBETPAN_EXPORT +char * mailmime_content_param_get(struct mailmime_content * content, + char * name); + +LIBETPAN_EXPORT +int mailmime_parse(const char * message, size_t length, + size_t * indx, struct mailmime ** result); + +LIBETPAN_EXPORT +int mailmime_get_section(struct mailmime * mime, + struct mailmime_section * section, + struct mailmime ** result); + + +LIBETPAN_EXPORT +char * mailmime_extract_boundary(struct mailmime_content * content_type); + + +/* decode */ + +LIBETPAN_EXPORT +int mailmime_base64_body_parse(const char * message, size_t length, + size_t * indx, char ** result, + size_t * result_len); + +LIBETPAN_EXPORT +int mailmime_quoted_printable_body_parse(const char * message, size_t length, + size_t * indx, char ** result, + size_t * result_len, int in_header); + + +LIBETPAN_EXPORT +int mailmime_binary_body_parse(const char * message, size_t length, + size_t * indx, char ** result, + size_t * result_len); + +/* + mailmime_part_parse() + + This function gets full MIME part for parsing at once. + It is not suitable, if we want parse incomplete message in a stream mode. + + @return the return code is one of MAILIMF_ERROR_XXX or + MAILIMF_NO_ERROR codes + */ +LIBETPAN_EXPORT +int mailmime_part_parse(const char * message, size_t length, + size_t * indx, + int encoding, char ** result, size_t * result_len); + + +/* + mailmime_part_parse_partial() + + This function may parse incomplete MIME part (i.e. in streaming mode). + It stops when detect incomplete encoding unit at the end of data. + Position of the first unparsed byte will be returned in (*indx) value. + + For parsing last portion of data must be used mailmime_part_parse() version. + + @param message Message for unparsed data. + @param length Length of the unparsed data. + @param INOUT indx Index of first unparsed symbol in the message. + @param encoding Encoding of the input data. + @param result Parsed MIME part content. Must be freed with mmap_string_unref(). + @param result_len Length of parsed data. + + @return the return code is one of MAILIMF_ERROR_XXX or + MAILIMF_NO_ERROR codes + + Example Usage: + @code + uint32_t received = 0; + uint32_t partLength = bodystructure[partId]->length; + for (;;) { + bool isThisRangeLast; + struct imap_range_t range = { received, 1024*1024 }; + char *result; + size_t result_len; + int error = imap_fetch_part_range(uid, partId, range, &result, &result_len); + if (error != NoError) { + // handle network error + break; + } + + if (result_len == 0) { + // requested range is empty. part is completely fetched + break; + } + + isThisRangeLast = (received + result_len >= partLength); // determine that the received data is the last, + // may be more difficult (in case of invalid metadata on the server). + + char *decoded; + size_t decoded_len; + if (isThisRangeLast) { + uint32_t index = 0; + mailmime_part_parse(result, result_len, encoding, &index, &decoded, &decoded_len); + break; + } + else { + uint32_t index = 0; + mailmime_part_parse_partial(result, result_len, encoding, &index, &decoded, &decoded_len); + // we may have some non-decoded bytes at the end of chunk. + // in this case we just request it in the next chunk + received += index; + } + } + @endcode + */ +LIBETPAN_EXPORT +int mailmime_part_parse_partial(const char * message, size_t length, + size_t * indx, + int encoding, char ** result, size_t * result_len); + + +LIBETPAN_EXPORT +int mailmime_get_section_id(struct mailmime * mime, + struct mailmime_section ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/mime/mailmime_decode.c b/Sources/libetpan/low-level/mime/mailmime_decode.c new file mode 100644 index 00000000..1b0349df --- /dev/null +++ b/Sources/libetpan/low-level/mime/mailmime_decode.c @@ -0,0 +1,733 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_decode.c,v 1.37 2010/11/16 20:52:28 hoa Exp $ + */ + +/* + RFC 2047 : MIME (Multipurpose Internet Mail Extensions) Part Three: + Message Header Extensions for Non-ASCII Text +*/ +#define HAVE_CONFIG_H 1 + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailmime_decode.h" + +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_SYS_MMAN_H +# include +#endif +#include +#include + +#include "mailmime_content.h" + +#include "charconv.h" +#include "mmapstring.h" +#include "mailimf.h" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +static int mailmime_charset_parse(const char * message, size_t length, + size_t * indx, char ** charset); + +enum { + MAILMIME_ENCODING_B, + MAILMIME_ENCODING_Q +}; + +static int mailmime_encoding_parse(const char * message, size_t length, + size_t * indx, int * result); + +static int mailmime_etoken_parse(const char * message, size_t length, + size_t * indx, char ** result); + +static int +mailmime_non_encoded_word_parse(const char * message, size_t length, + size_t * indx, + char ** result, int * p_has_fwd); + + + +enum { + TYPE_ERROR, + TYPE_WORD, + TYPE_ENCODED_WORD +}; + +LIBETPAN_EXPORT +int mailmime_encoded_phrase_parse(const char * default_fromcode, + const char * message, size_t length, + size_t * indx, const char * tocode, + char ** result) +{ + MMAPString * gphrase; + struct mailmime_encoded_word * word; + int first; + size_t cur_token; + int r; + int res; + char * str; + char * wordutf8; + int type; + int missing_closing_quote; + + cur_token = * indx; + + gphrase = mmap_string_new(""); + if (gphrase == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + first = TRUE; + + type = TYPE_ERROR; /* XXX - removes a gcc warning */ + + while (1) { + int has_fwd; + + word = NULL; + r = mailmime_encoded_word_parse(message, length, &cur_token, &word, &has_fwd, &missing_closing_quote); + if (r == MAILIMF_NO_ERROR) { + if ((!first) && has_fwd) { + if (type != TYPE_ENCODED_WORD) { + if (mmap_string_append_c(gphrase, ' ') == NULL) { + mailmime_encoded_word_free(word); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + } + type = TYPE_ENCODED_WORD; + wordutf8 = NULL; + r = charconv(tocode, word->wd_charset, word->wd_text, + strlen(word->wd_text), &wordutf8); + switch (r) { + case MAIL_CHARCONV_ERROR_MEMORY: + mailmime_encoded_word_free(word); + res = MAILIMF_ERROR_MEMORY; + goto free; + + case MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET: + r = charconv(tocode, "iso-8859-1", word->wd_text, + strlen(word->wd_text), &wordutf8); + break; + case MAIL_CHARCONV_ERROR_CONV: + mailmime_encoded_word_free(word); + res = MAILIMF_ERROR_PARSE; + goto free; + } + + switch (r) { + case MAIL_CHARCONV_ERROR_MEMORY: + mailmime_encoded_word_free(word); + res = MAILIMF_ERROR_MEMORY; + goto free; + case MAIL_CHARCONV_ERROR_CONV: + mailmime_encoded_word_free(word); + res = MAILIMF_ERROR_PARSE; + goto free; + } + + if (wordutf8 != NULL) { + if (mmap_string_append(gphrase, wordutf8) == NULL) { + mailmime_encoded_word_free(word); + free(wordutf8); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + free(wordutf8); + } + mailmime_encoded_word_free(word); + first = FALSE; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto free; + } + + if (r == MAILIMF_ERROR_PARSE) { + char * raw_word; + + raw_word = NULL; + r = mailmime_non_encoded_word_parse(message, length, + &cur_token, &raw_word, &has_fwd); + if (r == MAILIMF_NO_ERROR) { + if ((!first) && has_fwd) { + if (mmap_string_append_c(gphrase, ' ') == NULL) { + free(raw_word); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + type = TYPE_WORD; + + wordutf8 = NULL; + r = charconv(tocode, default_fromcode, raw_word, + strlen(raw_word), &wordutf8); + + switch (r) { + case MAIL_CHARCONV_ERROR_MEMORY: + free(raw_word); + res = MAILIMF_ERROR_MEMORY; + goto free; + + case MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET: + case MAIL_CHARCONV_ERROR_CONV: + free(raw_word); + res = MAILIMF_ERROR_PARSE; + goto free; + } + + if (mmap_string_append(gphrase, wordutf8) == NULL) { + free(wordutf8); + free(raw_word); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + free(wordutf8); + free(raw_word); + first = FALSE; + } + else if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_fws_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + break; + } + + if (mmap_string_append_c(gphrase, ' ') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + first = FALSE; + break; + } + else { + res = r; + goto free; + } + } + } + + if (first) { + if (cur_token != length) { + res = MAILIMF_ERROR_PARSE; + goto free; + } + } + + str = strdup(gphrase->str); + if (str == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + mmap_string_free(gphrase); + + * result = str; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + +free: + mmap_string_free(gphrase); +err: + return res; +} + +static int +mailmime_non_encoded_word_parse(const char * message, size_t length, + size_t * indx, + char ** result, int * p_has_fwd) +{ + int end; + size_t cur_token; + int res; + char * text; + int r; + size_t begin; + int state; + int has_fwd; + + cur_token = * indx; + + has_fwd = 0; + r = mailimf_fws_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + has_fwd = 1; + } + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + begin = cur_token; + + state = 0; + end = FALSE; + while (1) { + if (cur_token >= length) + break; + + switch (message[cur_token]) { + case ' ': + case '\t': + case '\r': + case '\n': + state = 0; + end = TRUE; + break; + case '=': + state = 1; + break; + case '?': + if (state == 1) { + cur_token --; + end = TRUE; + } + default: + state = 0; + break; + } + + if (end) + break; + + cur_token ++; + } + + if (cur_token - begin == 0) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + text = malloc(cur_token - begin + 1); + if (text == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + memcpy(text, message + begin, cur_token - begin); + text[cur_token - begin] = '\0'; + + * indx = cur_token; + * result = text; + * p_has_fwd = has_fwd; + + return MAILIMF_NO_ERROR; + + err: + return res; +} + +int mailmime_encoded_word_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_encoded_word ** result, + int * p_has_fwd, int * p_missing_closing_quote) +{ + /* + Parse the following, when a unicode character encoding is split. + =?UTF-8?B?4Lij4Liw4LmA4Lia4Li04LiU4LiE4Lin4Liy4Lih4Lih4Lix4LiZ4Liq4LmM?= + =?UTF-8?B?4LmA4LiV4LmH4Lih4Lie4Li04LiB4Lix4LiUIFRSQU5TRk9STUVSUyA0IOC4?= + =?UTF-8?B?oeC4seC4meC4quC5jOC4hOC4o+C4muC4l+C4uOC4geC4o+C4sOC4muC4miDg?= + =?UTF-8?B?uJfguLXguYjguYDguJTguLXguKLguKfguYPguJnguYDguKHguLfguK3guIfg?= + =?UTF-8?B?uYTguJfguKI=?= + Expected result: + ระเบิดความมันส์เต็มพิà¸à¸±à¸” TRANSFORMERS 4 มันส์ครบทุà¸à¸£à¸°à¸šà¸š ที่เดียวในเมืองไทย + libetpan result: + ระเบิดความมันส์เต็มพิà¸à¸±à¸” TRANSFORMERS 4 ?ันส์ครบทุà¸à¸£à¸°à¸šà¸š ??ี่เดียวในเมือง??ทย + + See https://github.com/dinhviethoa/libetpan/pull/211 + */ + size_t cur_token; + char * charset; + int encoding; + char * body; + size_t old_body_len; + char * text; + size_t end_encoding; + size_t lookfwd_cur_token; + char * lookfwd_charset; + int lookfwd_encoding; + size_t copy_len; + size_t decoded_token; + char * decoded; + size_t decoded_len; + struct mailmime_encoded_word * ew; + int r; + int res; + int opening_quote; + int end; + int has_fwd; + int missing_closing_quote; + + cur_token = * indx; + + text = NULL; + lookfwd_charset = NULL; + missing_closing_quote = 0; + has_fwd = 0; + r = mailimf_fws_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + has_fwd = 1; + } + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + opening_quote = FALSE; + r = mailimf_char_parse(message, length, &cur_token, '\"'); + if (r == MAILIMF_NO_ERROR) { + opening_quote = TRUE; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + + /* Parse first charset and encoding. */ + r = mailimf_token_case_insensitive_parse(message, length, &cur_token, "=?"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailmime_charset_parse(message, length, &cur_token, &charset); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_char_parse(message, length, &cur_token, '?'); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_charset; + } + + r = mailmime_encoding_parse(message, length, &cur_token, &encoding); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_charset; + } + + r = mailimf_char_parse(message, length, &cur_token, '?'); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_charset; + } + + lookfwd_cur_token = cur_token; + body = NULL; + old_body_len = 0; + while (1) { + int has_base64_padding; + + end = FALSE; + has_base64_padding = FALSE; + end_encoding = cur_token; + while (1) { + if (end_encoding >= length) + break; + + if (end_encoding + 1 < length) { + if ((message[end_encoding] == '?') && (message[end_encoding + 1] == '=')) { + end = TRUE; + } + } + + if (end) + break; + + end_encoding ++; + } + + copy_len = end_encoding - lookfwd_cur_token; + if (copy_len > 0) { + if (encoding == MAILMIME_ENCODING_B) { + if (end_encoding >= 1) { + if (message[end_encoding - 1] == '=') { + has_base64_padding = TRUE; + } + } + } + + body = realloc(body, old_body_len + copy_len + 1); + if (body == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_body; + } + + memcpy(body + old_body_len, &message[cur_token], copy_len); + body[old_body_len + copy_len] = '\0'; + + old_body_len += copy_len; + } + cur_token = end_encoding; + + r = mailimf_token_case_insensitive_parse(message, length, &cur_token, "?="); + if (r != MAILIMF_NO_ERROR) { + break; + } + + if (has_base64_padding) { + break; + } + + lookfwd_cur_token = cur_token; + + r = mailimf_fws_parse(message, length, &lookfwd_cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + break; + } + + /* Parse following charset and encoding to check if they're matching. */ + r = mailimf_token_case_insensitive_parse(message, length, &lookfwd_cur_token, "=?"); + if (r != MAILIMF_NO_ERROR) { + break; + } + + r = mailmime_charset_parse(message, length, &lookfwd_cur_token, &lookfwd_charset); + if (r != MAILIMF_NO_ERROR) { + break; + } + + r = mailimf_char_parse(message, length, &lookfwd_cur_token, '?'); + if (r != MAILIMF_NO_ERROR) { + break; + } + + r = mailmime_encoding_parse(message, length, &lookfwd_cur_token, &lookfwd_encoding); + if (r != MAILIMF_NO_ERROR) { + break; + } + + r = mailimf_char_parse(message, length, &lookfwd_cur_token, '?'); + if (r != MAILIMF_NO_ERROR) { + break; + } + + if ((strcasecmp(charset, lookfwd_charset) == 0) && (encoding == lookfwd_encoding)) { + cur_token = lookfwd_cur_token; + } else { + /* the next charset is not matched with the current one, + therefore exit the loop to decode the body appended so far */ + break; + } + + mailmime_charset_free(lookfwd_charset); + lookfwd_charset = NULL; + } + + if (lookfwd_charset != NULL) { + mailmime_charset_free(lookfwd_charset); + lookfwd_charset = NULL; + } + + if (body == NULL) { + body = strdup(""); + if (body == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_body; + } + } + + decoded_token = 0; + decoded_len = 0; + decoded = NULL; + switch (encoding) { + case MAILMIME_ENCODING_B: + r = mailmime_base64_body_parse(body, strlen(body), + &decoded_token, &decoded, + &decoded_len); + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_body; + } + break; + case MAILMIME_ENCODING_Q: + r = mailmime_quoted_printable_body_parse(body, strlen(body), + &decoded_token, &decoded, + &decoded_len, TRUE); + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_body; + } + + break; + } + + text = malloc(decoded_len + 1); + if (text == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_decoded; + } + + if (decoded_len > 0) + memcpy(text, decoded, decoded_len); + text[decoded_len] = '\0'; + + if (opening_quote) { + r = mailimf_char_parse(message, length, &cur_token, '\"'); + if (r == MAILIMF_ERROR_PARSE) { + missing_closing_quote = 1; + } + } + + /* fix charset */ + if (strcasecmp(charset, "utf8") == 0) { + free(charset); + charset = strdup("utf-8"); + } + ew = mailmime_encoded_word_new(charset, text); + if (ew == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_decoded; + } + + * result = ew; + * indx = cur_token; + * p_has_fwd = has_fwd; + * p_missing_closing_quote = missing_closing_quote; + + mailmime_decoded_part_free(decoded); + free(body); + + return MAILIMF_NO_ERROR; + +free_decoded: + mailmime_decoded_part_free(decoded); +free_body: + free(body); + mailmime_encoded_text_free(text); +free_charset: + mailmime_charset_free(charset); +err: + return res; +} + +static int mailmime_charset_parse(const char * message, size_t length, + size_t * indx, char ** charset) +{ + return mailmime_etoken_parse(message, length, indx, charset); +} + +static int mailmime_encoding_parse(const char * message, size_t length, + size_t * indx, int * result) +{ + size_t cur_token; + int encoding; + + cur_token = * indx; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch ((char) toupper((unsigned char) message[cur_token])) { + case 'Q': + encoding = MAILMIME_ENCODING_Q; + break; + case 'B': + encoding = MAILMIME_ENCODING_B; + break; + default: + return MAILIMF_ERROR_INVAL; + } + + cur_token ++; + + * result = encoding; + * indx = cur_token; + + return MAILIMF_NO_ERROR; +} + +int is_etoken_char(char ch) +{ + unsigned char uch = ch; + + if (uch < 31) + return FALSE; + + switch (uch) { + case ' ': + case '(': + case ')': + case '<': + case '>': + case '@': + case ',': + case ';': + case ':': + case '"': + case '/': + case '[': + case ']': + case '?': +#if 0 + case '.': +#endif + case '=': + return FALSE; + } + + return TRUE; +} + +static int mailmime_etoken_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + return mailimf_custom_string_parse(message, length, + indx, result, + is_etoken_char); +} diff --git a/Sources/libetpan/low-level/mime/mailmime_decode.h b/Sources/libetpan/low-level/mime/mailmime_decode.h new file mode 100644 index 00000000..973ac667 --- /dev/null +++ b/Sources/libetpan/low-level/mime/mailmime_decode.h @@ -0,0 +1,62 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_decode.h,v 1.14 2008/02/20 22:15:52 hoa Exp $ + */ + +#ifndef MAILMIME_DECODE_H + +#define MAILMIME_DECODE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +LIBETPAN_EXPORT +int mailmime_encoded_phrase_parse(const char * default_fromcode, + const char * message, size_t length, + size_t * indx, const char * tocode, + char ** result); + +int +mailmime_encoded_word_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_encoded_word ** result, + int * p_has_fwd, int * p_missing_closing_quote); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/mime/mailmime_disposition.c b/Sources/libetpan/low-level/mime/mailmime_disposition.c new file mode 100644 index 00000000..2ddc60a2 --- /dev/null +++ b/Sources/libetpan/low-level/mime/mailmime_disposition.c @@ -0,0 +1,621 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_disposition.c,v 1.17 2011/05/03 16:30:22 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailmime_disposition.h" +#include "mailmime.h" + +#include +#include +#include + +static int +mailmime_disposition_parm_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_disposition_parm ** + result); + +static int +mailmime_creation_date_parm_parse(const char * message, size_t length, + size_t * indx, char ** result); + +static int +mailmime_filename_parm_parse(const char * message, size_t length, + size_t * indx, char ** result); + +static int +mailmime_modification_date_parm_parse(const char * message, size_t length, + size_t * indx, char ** result); + +static int +mailmime_read_date_parm_parse(const char * message, size_t length, + size_t * indx, char ** result); + +static int +mailmime_size_parm_parse(const char * message, size_t length, + size_t * indx, size_t * result); + +static int +mailmime_quoted_date_time_parse(const char * message, size_t length, + size_t * indx, char ** result); + +/* + disposition := "Content-Disposition" ":" + disposition-type + *(";" disposition-parm) + +*/ + + +int mailmime_disposition_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_disposition ** result) +{ + size_t final_token; + size_t cur_token; + struct mailmime_disposition_type * dsp_type; + clist * list; + struct mailmime_disposition * dsp; + int r; + int res; + + cur_token = * indx; + + r = mailmime_disposition_type_parse(message, length, &cur_token, + &dsp_type); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_type; + } + + while (1) { + struct mailmime_disposition_parm * param; + + final_token = cur_token; + r = mailimf_unstrict_char_parse(message, length, &cur_token, ';'); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + res = r; + goto free_list; + } + + param = NULL; + r = mailmime_disposition_parm_parse(message, length, &cur_token, ¶m); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + cur_token = final_token; + break; + } + else { + res = r; + goto free_list; + } + + r = clist_append(list, param); + if (r < 0) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + } + + dsp = mailmime_disposition_new(dsp_type, list); + if (dsp == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = dsp; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailmime_disposition_parm_free, NULL); + clist_free(list); + free_type: + mailmime_disposition_type_free(dsp_type); + err: + return res; +} + +/* + disposition-type := "inline" + / "attachment" + / extension-token + ; values are not case-sensitive + +*/ + + + +int +mailmime_disposition_type_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_disposition_type ** result) +{ + size_t cur_token; + int type; + char * extension; + struct mailmime_disposition_type * dsp_type; + int r; + int res; + + cur_token = * indx; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + type = MAILMIME_DISPOSITION_TYPE_ERROR; /* XXX - removes a gcc warning */ + + extension = NULL; + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "inline"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISPOSITION_TYPE_INLINE; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "attachment"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISPOSITION_TYPE_ATTACHMENT; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailmime_extension_token_parse(message, length, &cur_token, + &extension); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISPOSITION_TYPE_EXTENSION; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + dsp_type = mailmime_disposition_type_new(type, extension); + if (dsp_type == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = dsp_type; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (extension != NULL) + free(extension); + err: + return res; +} + +/* + disposition-parm := filename-parm + / creation-date-parm + / modification-date-parm + / read-date-parm + / size-parm + / parameter +*/ + + +int mailmime_disposition_guess_type(const char * message, size_t length, + size_t indx) +{ + if (indx >= length) + return MAILMIME_DISPOSITION_PARM_PARAMETER; + + switch ((char) toupper((unsigned char) message[indx])) { + case 'F': + return MAILMIME_DISPOSITION_PARM_FILENAME; + case 'C': + return MAILMIME_DISPOSITION_PARM_CREATION_DATE; + case 'M': + return MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE; + case 'R': + return MAILMIME_DISPOSITION_PARM_READ_DATE; + case 'S': + return MAILMIME_DISPOSITION_PARM_SIZE; + default: + return MAILMIME_DISPOSITION_PARM_PARAMETER; + } +} + +static int +mailmime_disposition_parm_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_disposition_parm ** + result) +{ + char * filename; + char * creation_date; + char * modification_date; + char * read_date; + size_t size; + struct mailmime_parameter * parameter; + size_t cur_token; + struct mailmime_disposition_parm * dsp_parm; + int type; + int guessed_type; + int r; + int res; + + cur_token = * indx; + + filename = NULL; + creation_date = NULL; + modification_date = NULL; + read_date = NULL; + size = 0; + parameter = NULL; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + guessed_type = mailmime_disposition_guess_type(message, length, cur_token); + + type = MAILMIME_DISPOSITION_PARM_PARAMETER; + + switch (guessed_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + r = mailmime_filename_parm_parse(message, length, &cur_token, + &filename); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + r = mailmime_creation_date_parm_parse(message, length, &cur_token, + &creation_date); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + r = mailmime_modification_date_parm_parse(message, length, &cur_token, + &modification_date); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + + case MAILMIME_DISPOSITION_PARM_READ_DATE: + r = mailmime_read_date_parm_parse(message, length, &cur_token, + &read_date); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + + case MAILMIME_DISPOSITION_PARM_SIZE: + r = mailmime_size_parm_parse(message, length, &cur_token, + &size); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + } + + if (type == MAILMIME_DISPOSITION_PARM_PARAMETER) { + r = mailmime_parameter_parse(message, length, &cur_token, + ¶meter); + if (r != MAILIMF_NO_ERROR) { + type = guessed_type; + res = r; + goto err; + } + } + + dsp_parm = mailmime_disposition_parm_new(type, filename, creation_date, + modification_date, read_date, + size, parameter); + + if (dsp_parm == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = dsp_parm; + * indx = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (filename != NULL) + mailmime_filename_parm_free(filename); + if (creation_date != NULL) + mailmime_creation_date_parm_free(creation_date); + if (modification_date != NULL) + mailmime_modification_date_parm_free(modification_date); + if (read_date != NULL) + mailmime_read_date_parm_free(read_date); + if (parameter != NULL) + mailmime_parameter_free(parameter); + err: + return res; +} + +/* + filename-parm := "filename" "=" value +*/ + +static int +mailmime_filename_parm_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + char * value; + int r; + size_t cur_token; + + cur_token = * indx; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "filename"); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailmime_value_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) + return r; + + * indx = cur_token; + * result = value; + + return MAILIMF_NO_ERROR; +} + +/* + creation-date-parm := "creation-date" "=" quoted-date-time +*/ + +static int +mailmime_creation_date_parm_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + char * value; + int r; + size_t cur_token; + + cur_token = * indx; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "creation-date"); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailmime_quoted_date_time_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) + return r; + + * indx = cur_token; + * result = value; + + return MAILIMF_NO_ERROR; +} + +/* + modification-date-parm := "modification-date" "=" quoted-date-time +*/ + +static int +mailmime_modification_date_parm_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + char * value; + size_t cur_token; + int r; + + cur_token = * indx; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "modification-date"); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailmime_quoted_date_time_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) + return r; + + * indx = cur_token; + * result = value; + + return MAILIMF_NO_ERROR; +} + +/* + read-date-parm := "read-date" "=" quoted-date-time +*/ + +static int +mailmime_read_date_parm_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + char * value; + size_t cur_token; + int r; + + cur_token = * indx; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "read-date"); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailmime_quoted_date_time_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) + return r; + + * indx = cur_token; + * result = value; + + return MAILIMF_NO_ERROR; +} + +/* + size-parm := "size" "=" 1*DIGIT +*/ + +static int +mailmime_size_parm_parse(const char * message, size_t length, + size_t * indx, size_t * result) +{ + uint32_t value; + size_t cur_token; + int r; + + cur_token = * indx; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "size"); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_number_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) + return r; + + * indx = cur_token; + * result = value; + + return MAILIMF_NO_ERROR; +} + +/* + quoted-date-time := quoted-string + ; contents MUST be an RFC 822 `date-time' + ; numeric timezones (+HHMM or -HHMM) MUST be used +*/ + +static int +mailmime_quoted_date_time_parse(const char * message, size_t length, + size_t * indx, char ** result) +{ + return mailimf_quoted_string_parse(message, length, indx, result); +} diff --git a/Sources/libetpan/low-level/mime/mailmime_disposition.h b/Sources/libetpan/low-level/mime/mailmime_disposition.h new file mode 100644 index 00000000..689f9816 --- /dev/null +++ b/Sources/libetpan/low-level/mime/mailmime_disposition.h @@ -0,0 +1,62 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_disposition.h,v 1.11 2008/02/20 22:15:52 hoa Exp $ + */ + +#ifndef MAILMIME_DISPOSITION_H + +#define MAILMIME_DISPOSITION_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +int mailmime_disposition_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_disposition ** result); + +int +mailmime_disposition_type_parse(const char * message, size_t length, + size_t * indx, + struct mailmime_disposition_type ** result); + +int mailmime_disposition_guess_type(const char * message, size_t length, + size_t indx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/mime/mailmime_types.c b/Sources/libetpan/low-level/mime/mailmime_types.c new file mode 100644 index 00000000..2493500b --- /dev/null +++ b/Sources/libetpan/low-level/mime/mailmime_types.c @@ -0,0 +1,770 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_types.c,v 1.21 2011/01/06 00:09:52 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailmime_types.h" +#include "mmapstring.h" + +#include +#include + +void mailmime_attribute_free(char * attribute) +{ + mailmime_token_free(attribute); +} + + + +struct mailmime_composite_type * +mailmime_composite_type_new(int ct_type, char * ct_token) +{ + struct mailmime_composite_type * ct; + + ct = malloc(sizeof(* ct)); + if (ct == NULL) + return NULL; + + ct->ct_type = ct_type; + ct->ct_token = ct_token; + + return ct; +} + +void mailmime_composite_type_free(struct mailmime_composite_type * ct) +{ + if (ct->ct_token != NULL) + mailmime_extension_token_free(ct->ct_token); + free(ct); +} + + +struct mailmime_content * +mailmime_content_new(struct mailmime_type * ct_type, + char * ct_subtype, + clist * ct_parameters) +{ + struct mailmime_content * content; + + content = malloc(sizeof(* content)); + if (content == NULL) + return NULL; + + content->ct_type = ct_type; + content->ct_subtype = ct_subtype; + content->ct_parameters = ct_parameters; + + return content; +} + +void mailmime_content_free(struct mailmime_content * content) +{ + mailmime_type_free(content->ct_type); + mailmime_subtype_free(content->ct_subtype); + if (content->ct_parameters != NULL) { + clist_foreach(content->ct_parameters, + (clist_func) mailmime_parameter_free, NULL); + clist_free(content->ct_parameters); + } + + free(content); +} + + +void mailmime_description_free(char * description) +{ + free(description); +} + +void mailmime_location_free(char * location) +{ + free(location); +} + +struct mailmime_discrete_type * +mailmime_discrete_type_new(int dt_type, char * dt_extension) +{ + struct mailmime_discrete_type * discrete_type; + + discrete_type = malloc(sizeof(* discrete_type)); + if (discrete_type == NULL) + return NULL; + + discrete_type->dt_type = dt_type; + discrete_type->dt_extension = dt_extension; + + return discrete_type; +} + +void mailmime_discrete_type_free(struct mailmime_discrete_type * discrete_type) +{ + if (discrete_type->dt_extension != NULL) + mailmime_extension_token_free(discrete_type->dt_extension); + free(discrete_type); +} + +void mailmime_encoding_free(struct mailmime_mechanism * encoding) +{ + mailmime_mechanism_free(encoding); +} + +void mailmime_extension_token_free(char * extension) +{ + mailmime_token_free(extension); +} + +void mailmime_id_free(char * id) +{ + mailimf_msg_id_free(id); +} + +struct mailmime_mechanism * mailmime_mechanism_new(int enc_type, char * enc_token) +{ + struct mailmime_mechanism * mechanism; + + mechanism = malloc(sizeof(* mechanism)); + if (mechanism == NULL) + return NULL; + + mechanism->enc_type = enc_type; + mechanism->enc_token = enc_token; + + return mechanism; +} + +void mailmime_mechanism_free(struct mailmime_mechanism * mechanism) +{ + if (mechanism->enc_token != NULL) + mailmime_token_free(mechanism->enc_token); + free(mechanism); +} + +struct mailmime_parameter * +mailmime_parameter_new(char * pa_name, char * pa_value) +{ + struct mailmime_parameter * parameter; + + parameter = malloc(sizeof(* parameter)); + if (parameter == NULL) + return NULL; + + parameter->pa_name = pa_name; + parameter->pa_value = pa_value; + + return parameter; +} + +void mailmime_parameter_free(struct mailmime_parameter * parameter) +{ + mailmime_attribute_free(parameter->pa_name); + mailmime_value_free(parameter->pa_value); + free(parameter); +} + + +void mailmime_subtype_free(char * subtype) +{ + mailmime_extension_token_free(subtype); +} + + +void mailmime_token_free(char * token) +{ + free(token); +} + + +struct mailmime_type * +mailmime_type_new(int tp_type, + struct mailmime_discrete_type * tp_discrete_type, + struct mailmime_composite_type * tp_composite_type) +{ + struct mailmime_type * mime_type; + + mime_type = malloc(sizeof(* mime_type)); + if (mime_type == NULL) + return NULL; + + mime_type->tp_type = tp_type; + switch (tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + mime_type->tp_data.tp_discrete_type = tp_discrete_type; + break; + case MAILMIME_TYPE_COMPOSITE_TYPE: + mime_type->tp_data.tp_composite_type = tp_composite_type; + break; + } + + return mime_type; +} + +void mailmime_type_free(struct mailmime_type * type) +{ + switch (type->tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + mailmime_discrete_type_free(type->tp_data.tp_discrete_type); + break; + case MAILMIME_TYPE_COMPOSITE_TYPE: + mailmime_composite_type_free(type->tp_data.tp_composite_type); + break; + } + free(type); +} + +void mailmime_value_free(char * value) +{ + free(value); +} + + +/* +void mailmime_x_token_free(gchar * x_token) +{ + g_free(x_token); +} +*/ + +struct mailmime_field * +mailmime_field_new(int fld_type, + struct mailmime_content * fld_content, + struct mailmime_mechanism * fld_encoding, + char * fld_id, + char * fld_description, + uint32_t fld_version, + struct mailmime_disposition * fld_disposition, + struct mailmime_language * fld_language, + char * fld_location) +{ + struct mailmime_field * field; + + field = malloc(sizeof(* field)); + if (field == NULL) + return NULL; + field->fld_type = fld_type; + + switch (fld_type) { + case MAILMIME_FIELD_TYPE: + field->fld_data.fld_content = fld_content; + break; + case MAILMIME_FIELD_TRANSFER_ENCODING: + field->fld_data.fld_encoding = fld_encoding; + break; + case MAILMIME_FIELD_ID: + field->fld_data.fld_id = fld_id; + break; + case MAILMIME_FIELD_DESCRIPTION: + field->fld_data.fld_description = fld_description; + break; + case MAILMIME_FIELD_VERSION: + field->fld_data.fld_version = fld_version; + break; + case MAILMIME_FIELD_DISPOSITION: + field->fld_data.fld_disposition = fld_disposition; + break; + case MAILMIME_FIELD_LANGUAGE: + field->fld_data.fld_language = fld_language; + break; + case MAILMIME_FIELD_LOCATION: + field->fld_data.fld_location = fld_location; + break; + } + return field; +} + +void mailmime_field_free(struct mailmime_field * field) +{ + switch (field->fld_type) { + case MAILMIME_FIELD_TYPE: + if (field->fld_data.fld_content != NULL) + mailmime_content_free(field->fld_data.fld_content); + break; + case MAILMIME_FIELD_TRANSFER_ENCODING: + if (field->fld_data.fld_encoding != NULL) + mailmime_encoding_free(field->fld_data.fld_encoding); + break; + case MAILMIME_FIELD_ID: + if (field->fld_data.fld_id != NULL) + mailmime_id_free(field->fld_data.fld_id); + break; + case MAILMIME_FIELD_DESCRIPTION: + if (field->fld_data.fld_description != NULL) + mailmime_description_free(field->fld_data.fld_description); + break; + case MAILMIME_FIELD_DISPOSITION: + if (field->fld_data.fld_disposition != NULL) + mailmime_disposition_free(field->fld_data.fld_disposition); + break; + case MAILMIME_FIELD_LANGUAGE: + if (field->fld_data.fld_language != NULL) + mailmime_language_free(field->fld_data.fld_language); + break; + case MAILMIME_FIELD_LOCATION: + if (field->fld_data.fld_location != NULL) + mailmime_location_free(field->fld_data.fld_location); + break; + } + + free(field); +} + +struct mailmime_fields * mailmime_fields_new(clist * fld_list) +{ + struct mailmime_fields * fields; + + fields = malloc(sizeof(* fields)); + if (fields == NULL) + return NULL; + + fields->fld_list = fld_list; + + return fields; +} + +void mailmime_fields_free(struct mailmime_fields * fields) +{ + clist_foreach(fields->fld_list, (clist_func) mailmime_field_free, NULL); + clist_free(fields->fld_list); + free(fields); +} + + +/* +struct mailmime_body_part * +mailmime_body_part_new(gchar * text, guint32 size) +{ + struct mailmime_body_part * body_part; + + body_part = g_new(struct mailmime_body_part, 1); + if (body_part == NULL) + return NULL; + + body_part->text = text; + body_part->size = size; + + return body_part; +} + +void mailmime_body_part_free(struct mailmime_body_part * body_part) +{ + g_free(body_part); +} +*/ + +struct mailmime_multipart_body * +mailmime_multipart_body_new(clist * bd_list) +{ + struct mailmime_multipart_body * mp_body; + + mp_body = malloc(sizeof(* mp_body)); + if (mp_body == NULL) + return NULL; + + mp_body->bd_list = bd_list; + + return mp_body; +} + +void mailmime_multipart_body_free(struct mailmime_multipart_body * mp_body) +{ + clist_foreach(mp_body->bd_list, (clist_func) mailimf_body_free, NULL); + clist_free(mp_body->bd_list); + free(mp_body); +} + + + + +struct mailmime * mailmime_new(int mm_type, + const char * mm_mime_start, size_t mm_length, + struct mailmime_fields * mm_mime_fields, + struct mailmime_content * mm_content_type, + struct mailmime_data * mm_body, + struct mailmime_data * mm_preamble, + struct mailmime_data * mm_epilogue, + clist * mm_mp_list, + struct mailimf_fields * mm_fields, + struct mailmime * mm_msg_mime) +{ + struct mailmime * mime; + clistiter * cur; + + mime = malloc(sizeof(* mime)); + if (mime == NULL) + return NULL; + + mime->mm_parent = NULL; + mime->mm_parent_type = MAILMIME_NONE; + mime->mm_multipart_pos = NULL; + + mime->mm_type = mm_type; + mime->mm_mime_start = mm_mime_start; + mime->mm_length = mm_length; + mime->mm_mime_fields = mm_mime_fields; + mime->mm_content_type = mm_content_type; + + mime->mm_body = mm_body; + + switch (mm_type) { + case MAILMIME_SINGLE: + mime->mm_data.mm_single = mm_body; + break; + + case MAILMIME_MULTIPLE: + mime->mm_data.mm_multipart.mm_preamble = mm_preamble; + mime->mm_data.mm_multipart.mm_epilogue = mm_epilogue; + mime->mm_data.mm_multipart.mm_mp_list = mm_mp_list; + + for(cur = clist_begin(mm_mp_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime * submime; + + submime = clist_content(cur); + submime->mm_parent = mime; + submime->mm_parent_type = MAILMIME_MULTIPLE; + submime->mm_multipart_pos = cur; + } + break; + + case MAILMIME_MESSAGE: + mime->mm_data.mm_message.mm_fields = mm_fields; + mime->mm_data.mm_message.mm_msg_mime = mm_msg_mime; + if (mm_msg_mime != NULL) { + mm_msg_mime->mm_parent = mime; + mm_msg_mime->mm_parent_type = MAILMIME_MESSAGE; + } + break; + + } + + return mime; +} + +void mailmime_free(struct mailmime * mime) +{ + switch (mime->mm_type) { + case MAILMIME_SINGLE: + if ((mime->mm_body == NULL) && (mime->mm_data.mm_single != NULL)) + mailmime_data_free(mime->mm_data.mm_single); + /* do nothing */ + break; + + case MAILMIME_MULTIPLE: + if (mime->mm_data.mm_multipart.mm_preamble != NULL) + mailmime_data_free(mime->mm_data.mm_multipart.mm_preamble); + if (mime->mm_data.mm_multipart.mm_epilogue != NULL) + mailmime_data_free(mime->mm_data.mm_multipart.mm_epilogue); + clist_foreach(mime->mm_data.mm_multipart.mm_mp_list, + (clist_func) mailmime_free, NULL); + clist_free(mime->mm_data.mm_multipart.mm_mp_list); + break; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_fields != NULL) + mailimf_fields_free(mime->mm_data.mm_message.mm_fields); + if (mime->mm_data.mm_message.mm_msg_mime != NULL) + mailmime_free(mime->mm_data.mm_message.mm_msg_mime); + break; + + } + if (mime->mm_body != NULL) + mailmime_data_free(mime->mm_body); + + if (mime->mm_mime_fields != NULL) + mailmime_fields_free(mime->mm_mime_fields); + if (mime->mm_content_type != NULL) + mailmime_content_free(mime->mm_content_type); + free(mime); +} + + + +struct mailmime_encoded_word * +mailmime_encoded_word_new(char * wd_charset, char * wd_text) +{ + struct mailmime_encoded_word * ew; + + ew = malloc(sizeof(* ew)); + if (ew == NULL) + return NULL; + ew->wd_charset = wd_charset; + ew->wd_text = wd_text; + + return ew; +} + +void mailmime_charset_free(char * charset) +{ + free(charset); +} + +void mailmime_encoded_text_free(char * text) +{ + free(text); +} + +void mailmime_encoded_word_free(struct mailmime_encoded_word * ew) +{ + mailmime_charset_free(ew->wd_charset); + mailmime_encoded_text_free(ew->wd_text); + free(ew); +} + + + +/* mailmime_disposition */ + + +struct mailmime_disposition * +mailmime_disposition_new(struct mailmime_disposition_type * dsp_type, + clist * dsp_parms) +{ + struct mailmime_disposition * dsp; + + dsp = malloc(sizeof(* dsp)); + if (dsp == NULL) + return NULL; + dsp->dsp_type = dsp_type; + dsp->dsp_parms = dsp_parms; + + return dsp; +} + +void mailmime_disposition_free(struct mailmime_disposition * dsp) +{ + mailmime_disposition_type_free(dsp->dsp_type); + clist_foreach(dsp->dsp_parms, + (clist_func) mailmime_disposition_parm_free, NULL); + clist_free(dsp->dsp_parms); + free(dsp); +} + + + +struct mailmime_disposition_type * +mailmime_disposition_type_new(int dsp_type, char * dsp_extension) +{ + struct mailmime_disposition_type * m_dsp_type; + + m_dsp_type = malloc(sizeof(* m_dsp_type)); + if (m_dsp_type == NULL) + return NULL; + + m_dsp_type->dsp_type = dsp_type; + m_dsp_type->dsp_extension = dsp_extension; + + return m_dsp_type; +} + +void mailmime_disposition_type_free(struct mailmime_disposition_type * dsp_type) +{ + if (dsp_type->dsp_extension != NULL) + free(dsp_type->dsp_extension); + free(dsp_type); +} + + +struct mailmime_disposition_parm * +mailmime_disposition_parm_new(int pa_type, + char * pa_filename, + char * pa_creation_date, + char * pa_modification_date, + char * pa_read_date, + size_t pa_size, + struct mailmime_parameter * pa_parameter) +{ + struct mailmime_disposition_parm * dsp_parm; + + dsp_parm = malloc(sizeof(* dsp_parm)); + if (dsp_parm == NULL) + return NULL; + + dsp_parm->pa_type = pa_type; + switch (pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + dsp_parm->pa_data.pa_filename = pa_filename; + break; + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + dsp_parm->pa_data.pa_creation_date = pa_creation_date; + break; + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + dsp_parm->pa_data.pa_modification_date = pa_modification_date; + break; + case MAILMIME_DISPOSITION_PARM_READ_DATE: + dsp_parm->pa_data.pa_read_date = pa_read_date; + break; + case MAILMIME_DISPOSITION_PARM_SIZE: + dsp_parm->pa_data.pa_size = pa_size; + break; + case MAILMIME_DISPOSITION_PARM_PARAMETER: + dsp_parm->pa_data.pa_parameter = pa_parameter; + break; + } + + return dsp_parm; +} + +void mailmime_disposition_parm_free(struct mailmime_disposition_parm * + dsp_parm) +{ + switch (dsp_parm->pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + mailmime_filename_parm_free(dsp_parm->pa_data.pa_filename); + break; + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + mailmime_creation_date_parm_free(dsp_parm->pa_data.pa_creation_date); + break; + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + mailmime_modification_date_parm_free(dsp_parm->pa_data.pa_modification_date); + break; + case MAILMIME_DISPOSITION_PARM_READ_DATE: + mailmime_read_date_parm_free(dsp_parm->pa_data.pa_read_date); + break; + case MAILMIME_DISPOSITION_PARM_PARAMETER: + mailmime_parameter_free(dsp_parm->pa_data.pa_parameter); + break; + } + + free(dsp_parm); +} + + +void mailmime_filename_parm_free(char * filename) +{ + mailmime_value_free(filename); +} + +void mailmime_creation_date_parm_free(char * date) +{ + mailmime_quoted_date_time_free(date); +} + +void mailmime_modification_date_parm_free(char * date) +{ + mailmime_quoted_date_time_free(date); +} + +void mailmime_read_date_parm_free(char * date) +{ + mailmime_quoted_date_time_free(date); +} + +void mailmime_quoted_date_time_free(char * date) +{ + mailimf_quoted_string_free(date); +} + +struct mailmime_section * mailmime_section_new(clist * sec_list) +{ + struct mailmime_section * section; + + section = malloc(sizeof(* section)); + if (section == NULL) + return NULL; + + section->sec_list = sec_list; + + return section; +} + +void mailmime_section_free(struct mailmime_section * section) +{ + clist_foreach(section->sec_list, (clist_func) free, NULL); + clist_free(section->sec_list); + free(section); +} + + + +struct mailmime_language * mailmime_language_new(clist * lg_list) +{ + struct mailmime_language * lang; + + lang = malloc(sizeof(* lang)); + if (lang == NULL) + return NULL; + + lang->lg_list = lg_list; + + return lang; +} + +void mailmime_language_free(struct mailmime_language * lang) +{ + clist_foreach(lang->lg_list, (clist_func) mailimf_atom_free, NULL); + clist_free(lang->lg_list); + free(lang); +} + +void mailmime_decoded_part_free(char * part) +{ + mmap_string_unref(part); +} + +struct mailmime_data * mailmime_data_new(int dt_type, int dt_encoding, + int dt_encoded, const char * dt_data, size_t dt_length, char * dt_filename) +{ + struct mailmime_data * mime_data; + + mime_data = malloc(sizeof(* mime_data)); + if (mime_data == NULL) + return NULL; + + mime_data->dt_type = dt_type; + mime_data->dt_encoding = dt_encoding; + mime_data->dt_encoded = dt_encoded; + switch (dt_type) { + case MAILMIME_DATA_TEXT: + mime_data->dt_data.dt_text.dt_data = dt_data; + mime_data->dt_data.dt_text.dt_length = dt_length; + break; + case MAILMIME_DATA_FILE: + mime_data->dt_data.dt_filename = dt_filename; + break; + } + + return mime_data; +} + +void mailmime_data_free(struct mailmime_data * mime_data) +{ + switch (mime_data->dt_type) { + case MAILMIME_DATA_FILE: + free(mime_data->dt_data.dt_filename); + break; + } + free(mime_data); +} diff --git a/Sources/libetpan/low-level/mime/mailmime_types.h b/Sources/libetpan/low-level/mime/mailmime_types.h new file mode 100644 index 00000000..664211d9 --- /dev/null +++ b/Sources/libetpan/low-level/mime/mailmime_types.h @@ -0,0 +1,503 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_types.h,v 1.33 2011/01/06 00:09:52 hoa Exp $ + */ + +#ifndef MAILMIME_TYPES_H + +#define MAILMIME_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef LIBETPAN_CONFIG_H +#include +#endif + +#ifdef HAVE_INTTYPES_H +# include +#endif +#include +#include + +enum { + MAILMIME_COMPOSITE_TYPE_ERROR, + MAILMIME_COMPOSITE_TYPE_MESSAGE, + MAILMIME_COMPOSITE_TYPE_MULTIPART, + MAILMIME_COMPOSITE_TYPE_EXTENSION +}; + +struct mailmime_composite_type { + int ct_type; + char * ct_token; +}; + + +struct mailmime_content { + struct mailmime_type * ct_type; + char * ct_subtype; + clist * ct_parameters; /* elements are (struct mailmime_parameter *) */ +}; + + +enum { + MAILMIME_DISCRETE_TYPE_ERROR, + MAILMIME_DISCRETE_TYPE_TEXT, + MAILMIME_DISCRETE_TYPE_IMAGE, + MAILMIME_DISCRETE_TYPE_AUDIO, + MAILMIME_DISCRETE_TYPE_VIDEO, + MAILMIME_DISCRETE_TYPE_APPLICATION, + MAILMIME_DISCRETE_TYPE_EXTENSION +}; + +struct mailmime_discrete_type { + int dt_type; + char * dt_extension; +}; + +enum { + MAILMIME_FIELD_NONE, + MAILMIME_FIELD_TYPE, + MAILMIME_FIELD_TRANSFER_ENCODING, + MAILMIME_FIELD_ID, + MAILMIME_FIELD_DESCRIPTION, + MAILMIME_FIELD_VERSION, + MAILMIME_FIELD_DISPOSITION, + MAILMIME_FIELD_LANGUAGE, + MAILMIME_FIELD_LOCATION +}; + +struct mailmime_field { + int fld_type; + union { + struct mailmime_content * fld_content; + struct mailmime_mechanism * fld_encoding; + char * fld_id; + char * fld_description; + uint32_t fld_version; + struct mailmime_disposition * fld_disposition; + struct mailmime_language * fld_language; + char * fld_location; + } fld_data; +}; + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +struct mailmime_mechanism { + int enc_type; + char * enc_token; +}; + + +struct mailmime_fields { + clist * fld_list; /* list of (struct mailmime_field *) */ +}; + + +struct mailmime_parameter { + char * pa_name; + char * pa_value; +}; + +enum { + MAILMIME_TYPE_ERROR, + MAILMIME_TYPE_DISCRETE_TYPE, + MAILMIME_TYPE_COMPOSITE_TYPE +}; + +struct mailmime_type { + int tp_type; + union { + struct mailmime_discrete_type * tp_discrete_type; + struct mailmime_composite_type * tp_composite_type; + } tp_data; +}; + +LIBETPAN_EXPORT +void mailmime_attribute_free(char * attribute); + +LIBETPAN_EXPORT +struct mailmime_composite_type * +mailmime_composite_type_new(int ct_type, char * ct_token); + +LIBETPAN_EXPORT +void mailmime_composite_type_free(struct mailmime_composite_type * ct); + +LIBETPAN_EXPORT +struct mailmime_content * +mailmime_content_new(struct mailmime_type * ct_type, + char * ct_subtype, + clist * ct_parameters); + +LIBETPAN_EXPORT +void mailmime_content_free(struct mailmime_content * content); + +LIBETPAN_EXPORT +void mailmime_description_free(char * description); + +LIBETPAN_EXPORT +void mailmime_location_free(char * location); + +LIBETPAN_EXPORT +struct mailmime_discrete_type * +mailmime_discrete_type_new(int dt_type, char * dt_extension); + +LIBETPAN_EXPORT +void mailmime_discrete_type_free(struct mailmime_discrete_type * + discrete_type); + +LIBETPAN_EXPORT +void mailmime_encoding_free(struct mailmime_mechanism * encoding); + +LIBETPAN_EXPORT +void mailmime_extension_token_free(char * extension); + +LIBETPAN_EXPORT +void mailmime_id_free(char * id); + +LIBETPAN_EXPORT +struct mailmime_mechanism * mailmime_mechanism_new(int enc_type, char * enc_token); + +LIBETPAN_EXPORT +void mailmime_mechanism_free(struct mailmime_mechanism * mechanism); + +LIBETPAN_EXPORT +struct mailmime_parameter * +mailmime_parameter_new(char * pa_name, char * pa_value); + +LIBETPAN_EXPORT +void mailmime_parameter_free(struct mailmime_parameter * parameter); + +LIBETPAN_EXPORT +void mailmime_subtype_free(char * subtype); + +LIBETPAN_EXPORT +void mailmime_token_free(char * token); + +LIBETPAN_EXPORT +struct mailmime_type * +mailmime_type_new(int tp_type, + struct mailmime_discrete_type * tp_discrete_type, + struct mailmime_composite_type * tp_composite_type); + +LIBETPAN_EXPORT +void mailmime_type_free(struct mailmime_type * type); + +LIBETPAN_EXPORT +void mailmime_value_free(char * value); + + + +struct mailmime_language { + clist * lg_list; /* atom (char *) */ +}; + +LIBETPAN_EXPORT +struct mailmime_language * mailmime_language_new(clist * lg_list); + +LIBETPAN_EXPORT +void mailmime_language_free(struct mailmime_language * lang); + + +/* +void mailmime_x_token_free(gchar * x_token); +*/ + +LIBETPAN_EXPORT +struct mailmime_field * +mailmime_field_new(int fld_type, + struct mailmime_content * fld_content, + struct mailmime_mechanism * fld_encoding, + char * fld_id, + char * fld_description, + uint32_t fld_version, + struct mailmime_disposition * fld_disposition, + struct mailmime_language * fld_language, + char * fld_location); + +LIBETPAN_EXPORT +void mailmime_field_free(struct mailmime_field * field); + +LIBETPAN_EXPORT +struct mailmime_fields * mailmime_fields_new(clist * fld_list); + +LIBETPAN_EXPORT +void mailmime_fields_free(struct mailmime_fields * fields); + + +struct mailmime_multipart_body { + clist * bd_list; +}; + +LIBETPAN_EXPORT +struct mailmime_multipart_body * +mailmime_multipart_body_new(clist * bd_list); + +LIBETPAN_EXPORT +void mailmime_multipart_body_free(struct mailmime_multipart_body * mp_body); + + +enum { + MAILMIME_DATA_TEXT, + MAILMIME_DATA_FILE +}; + +struct mailmime_data { + int dt_type; + int dt_encoding; + int dt_encoded; + union { + struct { + const char * dt_data; + size_t dt_length; + } dt_text; + char * dt_filename; + } dt_data; +}; + +LIBETPAN_EXPORT +struct mailmime_data * mailmime_data_new(int dt_type, int dt_encoding, + int dt_encoded, const char * dt_data, size_t dt_length, + char * dt_filename); + +LIBETPAN_EXPORT +void mailmime_data_free(struct mailmime_data * mime_data); + + +enum { + MAILMIME_NONE, + MAILMIME_SINGLE, + MAILMIME_MULTIPLE, + MAILMIME_MESSAGE +}; + +struct mailmime { + /* parent information */ + int mm_parent_type; + struct mailmime * mm_parent; + clistiter * mm_multipart_pos; + + int mm_type; + const char * mm_mime_start; + size_t mm_length; + + struct mailmime_fields * mm_mime_fields; + struct mailmime_content * mm_content_type; + + struct mailmime_data * mm_body; + union { + /* single part */ + struct mailmime_data * mm_single; /* XXX - was body */ + + /* multi-part */ + struct { + struct mailmime_data * mm_preamble; + struct mailmime_data * mm_epilogue; + clist * mm_mp_list; + } mm_multipart; + + /* message */ + struct { + struct mailimf_fields * mm_fields; + struct mailmime * mm_msg_mime; + } mm_message; + + } mm_data; +}; + +LIBETPAN_EXPORT +struct mailmime * mailmime_new(int mm_type, + const char * mm_mime_start, size_t mm_length, + struct mailmime_fields * mm_mime_fields, + struct mailmime_content * mm_content_type, + struct mailmime_data * mm_body, + struct mailmime_data * mm_preamble, + struct mailmime_data * mm_epilogue, + clist * mm_mp_list, + struct mailimf_fields * mm_fields, + struct mailmime * mm_msg_mime); + +LIBETPAN_EXPORT +void mailmime_free(struct mailmime * mime); + +struct mailmime_encoded_word { + char * wd_charset; + char * wd_text; +}; + +LIBETPAN_EXPORT +struct mailmime_encoded_word * +mailmime_encoded_word_new(char * wd_charset, char * wd_text); + +LIBETPAN_EXPORT +void mailmime_encoded_word_free(struct mailmime_encoded_word * ew); + +LIBETPAN_EXPORT +void mailmime_charset_free(char * charset); + +LIBETPAN_EXPORT +void mailmime_encoded_text_free(char * text); + + +struct mailmime_disposition { + struct mailmime_disposition_type * dsp_type; + clist * dsp_parms; /* struct mailmime_disposition_parm */ +}; + + +enum { + MAILMIME_DISPOSITION_TYPE_ERROR, + MAILMIME_DISPOSITION_TYPE_INLINE, + MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + MAILMIME_DISPOSITION_TYPE_EXTENSION +}; + +struct mailmime_disposition_type { + int dsp_type; + char * dsp_extension; +}; + + +enum { + MAILMIME_DISPOSITION_PARM_FILENAME, + MAILMIME_DISPOSITION_PARM_CREATION_DATE, + MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE, + MAILMIME_DISPOSITION_PARM_READ_DATE, + MAILMIME_DISPOSITION_PARM_SIZE, + MAILMIME_DISPOSITION_PARM_PARAMETER +}; + +struct mailmime_disposition_parm { + int pa_type; + union { + char * pa_filename; + char * pa_creation_date; + char * pa_modification_date; + char * pa_read_date; + size_t pa_size; + struct mailmime_parameter * pa_parameter; + } pa_data; +}; + +LIBETPAN_EXPORT +struct mailmime_disposition * +mailmime_disposition_new(struct mailmime_disposition_type * dsp_type, + clist * dsp_parms); + +LIBETPAN_EXPORT +void mailmime_disposition_free(struct mailmime_disposition * dsp); + +LIBETPAN_EXPORT +struct mailmime_disposition_type * +mailmime_disposition_type_new(int dt_type, char * dt_extension); + +LIBETPAN_EXPORT +void mailmime_disposition_type_free(struct mailmime_disposition_type * dsp_type); + +LIBETPAN_EXPORT +struct mailmime_disposition_parm * +mailmime_disposition_parm_new(int pa_type, + char * pa_filename, + char * pa_creation_date, + char * pa_modification_date, + char * pa_read_date, + size_t pa_size, + struct mailmime_parameter * pa_parameter); + +LIBETPAN_EXPORT +void mailmime_disposition_parm_free(struct mailmime_disposition_parm * + dsp_parm); + +LIBETPAN_EXPORT +void mailmime_filename_parm_free(char * filename); + +LIBETPAN_EXPORT +void mailmime_creation_date_parm_free(char * date); + +LIBETPAN_EXPORT +void mailmime_modification_date_parm_free(char * date); + +LIBETPAN_EXPORT +void mailmime_read_date_parm_free(char * date); + +LIBETPAN_EXPORT +void mailmime_quoted_date_time_free(char * date); + +struct mailmime_section { + clist * sec_list; /* list of (uint32 *) */ +}; + +LIBETPAN_EXPORT +struct mailmime_section * mailmime_section_new(clist * list); + +LIBETPAN_EXPORT +void mailmime_section_free(struct mailmime_section * section); + + +LIBETPAN_EXPORT +void mailmime_decoded_part_free(char * part); + +struct mailmime_single_fields { + struct mailmime_content * fld_content; + char * fld_content_charset; + char * fld_content_boundary; + char * fld_content_name; + struct mailmime_mechanism * fld_encoding; + char * fld_id; + char * fld_description; + uint32_t fld_version; + struct mailmime_disposition * fld_disposition; + char * fld_disposition_filename; + char * fld_disposition_creation_date; + char * fld_disposition_modification_date; + char * fld_disposition_read_date; + size_t fld_disposition_size; + struct mailmime_language * fld_language; + char * fld_location; +}; + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Sources/libetpan/low-level/mime/mailmime_types_helper.c b/Sources/libetpan/low-level/mime/mailmime_types_helper.c new file mode 100644 index 00000000..a4b2acd6 --- /dev/null +++ b/Sources/libetpan/low-level/mime/mailmime_types_helper.c @@ -0,0 +1,1426 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_types_helper.c,v 1.30 2011/04/30 17:24:21 hoa Exp $ + */ +#define HAVE_CONFIG_H 1 + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailmime_types_helper.h" + +#include "clist.h" +#include "mailmime.h" + +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#ifdef WIN32 +# include "win_etpan.h" +#endif + +#define MIME_VERSION (1 << 16) + +int mailmime_transfer_encoding_get(struct mailmime_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->fld_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + if (field->fld_type == MAILMIME_FIELD_TRANSFER_ENCODING) + return field->fld_data.fld_encoding->enc_type; + } + + return MAILMIME_MECHANISM_8BIT; +} + +struct mailmime_disposition * +mailmime_disposition_new_filename(int type, char * filename) +{ + return mailmime_disposition_new_with_data(type, filename, + NULL, NULL, NULL, (size_t) -1); + +} + +struct mailmime_fields * mailmime_fields_new_empty(void) +{ + clist * list; + struct mailmime_fields * fields; + + list = clist_new(); + if (list == NULL) + goto err; + + fields = mailmime_fields_new(list); + if (fields == NULL) + goto free; + + return fields; + + free: + clist_free(list); + err: + return NULL; +} + +int mailmime_fields_add(struct mailmime_fields * fields, + struct mailmime_field * field) +{ + int r; + + r = clist_append(fields->fld_list, field); + if (r < 0) + return MAILIMF_ERROR_MEMORY; + + return MAILIMF_NO_ERROR; +} + +static void mailmime_field_detach(struct mailmime_field * field) +{ + switch (field->fld_type) { + case MAILMIME_FIELD_TYPE: + field->fld_data.fld_content = NULL; + break; + case MAILMIME_FIELD_TRANSFER_ENCODING: + field->fld_data.fld_encoding = NULL; + break; + case MAILMIME_FIELD_ID: + field->fld_data.fld_id = NULL; + break; + case MAILMIME_FIELD_DESCRIPTION: + field->fld_data.fld_description = NULL; + break; + case MAILMIME_FIELD_DISPOSITION: + field->fld_data.fld_disposition = NULL; + break; + case MAILMIME_FIELD_LANGUAGE: + field->fld_data.fld_language = NULL; + break; + } +} + +struct mailmime_fields * +mailmime_fields_new_with_data(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language) +{ + struct mailmime_field * field; + struct mailmime_fields * fields; + int r; + + fields = mailmime_fields_new_empty(); + if (fields == NULL) + goto err; + +#if 0 + if (content != NULL) { + field = mailmime_field_new(MAILMIME_FIELD_TYPE, + content, NULL, NULL, NULL, 0, NULL, NULL); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + } +#endif + + if (encoding != NULL) { + field = mailmime_field_new(MAILMIME_FIELD_TRANSFER_ENCODING, + NULL, encoding, NULL, NULL, 0, NULL, NULL, NULL); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + } + + if (id != NULL) { + field = mailmime_field_new(MAILMIME_FIELD_ID, + NULL, NULL, id, NULL, 0, NULL, NULL, NULL); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + } + + if (description != NULL) { + field = mailmime_field_new(MAILMIME_FIELD_DESCRIPTION, + NULL, NULL, NULL, description, 0, NULL, NULL, NULL); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + } + + if (disposition != NULL) { + field = mailmime_field_new(MAILMIME_FIELD_DISPOSITION, + NULL, NULL, NULL, NULL, 0, disposition, NULL, NULL); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + } + + if (language != NULL) { + field = mailmime_field_new(MAILMIME_FIELD_DISPOSITION, + NULL, NULL, NULL, NULL, 0, NULL, language, NULL); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + } + + return fields; + + free: + clist_foreach(fields->fld_list, (clist_func) mailmime_field_detach, NULL); + mailmime_fields_free(fields); + err: + return NULL; +} + +struct mailmime_fields * +mailmime_fields_new_with_version(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language) +{ + struct mailmime_field * field; + struct mailmime_fields * fields; + int r; + + fields = mailmime_fields_new_with_data(encoding, id, description, + disposition, language); + if (fields == NULL) + goto err; + + field = mailmime_field_new(MAILMIME_FIELD_VERSION, + NULL, NULL, NULL, NULL, MIME_VERSION, NULL, NULL, NULL); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + + return fields; + + free: + clist_foreach(fields->fld_list, (clist_func) mailmime_field_detach, NULL); + mailmime_fields_free(fields); + err: + return NULL; +} + + +struct mailmime_content * mailmime_get_content_message(void) +{ + clist * list; + struct mailmime_composite_type * composite_type; + struct mailmime_type * mime_type; + struct mailmime_content * content; + char * subtype; + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MESSAGE, + NULL); + if (composite_type == NULL) + goto err; + + mime_type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, + NULL, composite_type); + if (mime_type == NULL) + goto free_composite; + composite_type = NULL; + + list = clist_new(); + if (list == NULL) + goto free_mime_type; + + subtype = strdup("rfc822"); + if (subtype == NULL) + goto free_list; + + content = mailmime_content_new(mime_type, subtype, list); + if (content == NULL) + goto free_subtype; + + return content; + + free_subtype: + free(subtype); + free_list: + clist_free(list); + free_mime_type: + mailmime_type_free(mime_type); + free_composite: + if (composite_type != NULL) + mailmime_composite_type_free(composite_type); + err: + return NULL; +} + +struct mailmime_content * mailmime_get_content_text(void) +{ + clist * list; + struct mailmime_discrete_type * discrete_type; + struct mailmime_type * mime_type; + struct mailmime_content * content; + char * subtype; + + discrete_type = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT, + NULL); + if (discrete_type == NULL) + goto err; + + mime_type = mailmime_type_new(MAILMIME_TYPE_DISCRETE_TYPE, + discrete_type, NULL); + if (mime_type == NULL) + goto free_discrete; + discrete_type = NULL; + + list = clist_new(); + if (list == NULL) + goto free_type; + + subtype = strdup("plain"); + if (subtype == NULL) + goto free_list; + + content = mailmime_content_new(mime_type, subtype, list); + if (content == NULL) + goto free_subtype; + + return content; + + free_subtype: + free(subtype); + free_list: + clist_free(list); + free_type: + mailmime_type_free(mime_type); + free_discrete: + if (discrete_type != NULL) + mailmime_discrete_type_free(discrete_type); + err: + return NULL; +} + + + + + + + + +/* mailmime build */ + + +#if 0 +struct mailmime * +mailmime_new_message_file(char * filename) +{ + struct mailmime_content * content; + struct mailmime * build_info; + struct mailmime_data * msg_content; + struct mailmime_fields * mime_fields; + + content = mailmime_get_content_message(); + if (content == NULL) { + goto err; + } + + mime_fields = mailmime_fields_new_with_version(NULL, NULL, + NULL, NULL, NULL); + if (mime_fields == NULL) + goto free_content; + + msg_content = mailmime_data_new(MAILMIME_DATA_FILE, MAILMIME_MECHANISM_8BIT, + 1, NULL, 0, filename); + if (msg_content == NULL) + goto free_fields; + + build_info = mailmime_new(MAILMIME_MESSAGE, + NULL, 0, mime_fields, content, + msg_content, NULL, NULL, NULL, NULL, NULL); + if (build_info == NULL) + goto free_msg_content; + + return build_info; + + free_msg_content: + mailmime_data_free(msg_content); + free_fields: + mailmime_fields_free(mime_fields); + free_content: + mailmime_content_free(content); + err: + return NULL; +} + +struct mailmime * +mailmime_new_message_text(char * data_str, size_t length) +{ + struct mailmime_content * content; + struct mailmime * build_info; + struct mailmime_data * msg_content; + struct mailmime_fields * mime_fields; + + content = mailmime_get_content_message(); + if (content == NULL) { + goto err; + } + + mime_fields = mailmime_fields_new_with_version(NULL, NULL, + NULL, NULL, NULL); + if (mime_fields == NULL) + goto free_fields; + + msg_content = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, + 1, data_str, length, NULL); + if (msg_content == NULL) + goto free_content; + + build_info = mailmime_new(MAILMIME_MESSAGE, + NULL, 0, mime_fields, content, + msg_content, NULL, NULL, NULL, + NULL, NULL); + if (build_info == NULL) + goto free_msg_content; + + return build_info; + + free_msg_content: + mailmime_data_free(msg_content); + free_fields: + mailmime_fields_free(mime_fields); + free_content: + mailmime_content_free(content); + err: + return NULL; +} +#endif + +struct mailmime * +mailmime_new_message_data(struct mailmime * msg_mime) +{ + struct mailmime_content * content; + struct mailmime * build_info; + struct mailmime_fields * mime_fields; + + content = mailmime_get_content_message(); + if (content == NULL) + goto err; + + mime_fields = mailmime_fields_new_with_version(NULL, NULL, + NULL, NULL, NULL); + if (mime_fields == NULL) + goto free_content; + + build_info = mailmime_new(MAILMIME_MESSAGE, + NULL, 0, mime_fields, content, + NULL, NULL, NULL, NULL, + NULL, msg_mime); + if (build_info == NULL) + goto free_fields; + + return build_info; + + free_fields: + mailmime_fields_free(mime_fields); + free_content: + mailmime_content_free(content); + err: + return NULL; +} + +#define MAX_MESSAGE_ID 512 + +char * mailmime_generate_boundary(void) +{ + char id[MAX_MESSAGE_ID]; + time_t now; + char name[MAX_MESSAGE_ID]; + long value; + + now = time(NULL); + value = random(); + + gethostname(name, MAX_MESSAGE_ID); + snprintf(id, MAX_MESSAGE_ID, "%llx_%lx_%x", (long long)now, value, getpid()); + + return strdup(id); +} + +struct mailmime * +mailmime_new_empty(struct mailmime_content * content, + struct mailmime_fields * mime_fields) +{ + struct mailmime * build_info; + clist * list; + int r; + int mime_type; + + list = NULL; + + switch (content->ct_type->tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + mime_type = MAILMIME_SINGLE; + break; + + case MAILMIME_TYPE_COMPOSITE_TYPE: + switch (content->ct_type->tp_data.tp_composite_type->ct_type) { + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + mime_type = MAILMIME_MULTIPLE; + break; + + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + if (strcasecmp(content->ct_subtype, "rfc822") == 0) + mime_type = MAILMIME_MESSAGE; + else + mime_type = MAILMIME_SINGLE; + break; + + default: + goto err; + } + break; + + default: + goto err; + } + + if (mime_type == MAILMIME_MULTIPLE) { + char * attr_name; + char * attr_value; + struct mailmime_parameter * param; + clist * parameters; + + list = clist_new(); + if (list == NULL) + goto err; + + attr_name = strdup("boundary"); + if (attr_name == NULL) + goto free_list; + + attr_value = mailmime_generate_boundary(); + if (attr_value == NULL) { + free(attr_name); + goto free_list; + } + + param = mailmime_parameter_new(attr_name, attr_value); + if (param == NULL) { + free(attr_value); + free(attr_name); + goto free_list; + } + + if (content->ct_parameters == NULL) { + parameters = clist_new(); + if (parameters == NULL) { + mailmime_parameter_free(param); + goto free_list; + } + } + else + parameters = content->ct_parameters; + + r = clist_append(parameters, param); + if (r != 0) { + clist_free(parameters); + mailmime_parameter_free(param); + goto free_list; + } + + if (content->ct_parameters == NULL) + content->ct_parameters = parameters; + } + + build_info = mailmime_new(mime_type, + NULL, 0, mime_fields, content, + NULL, NULL, NULL, list, + NULL, NULL); + if (build_info == NULL) { + clist_free(list); + return NULL; + } + + return build_info; + + free_list: + clist_free(list); + err: + return NULL; +} + + +int +mailmime_new_with_content(const char * content_type, + struct mailmime_fields * mime_fields, + struct mailmime ** result) +{ + int r; + size_t cur_token; + struct mailmime_content * content; + struct mailmime * build_info; +#if 0 + int mime_type; +#endif + int res; + + cur_token = 0; + r = mailmime_content_parse(content_type, strlen(content_type), + &cur_token, + &content); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + +#if 0 + switch (content->type->type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + mime_type = MAILMIME_SINGLE; + break; + + case MAILMIME_TYPE_COMPOSITE_TYPE: + switch (content->type->composite_type->type) { + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + mime_type = MAILMIME_MULTIPLE; + break; + + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + if (strcasecmp(content->subtype, "rfc822") == 0) + mime_type = MAILMIME_MESSAGE; + else + mime_type = MAILMIME_SINGLE; + break; + + default: + res = MAILIMF_ERROR_INVAL; + goto free; + } + break; + + default: + res = MAILIMF_ERROR_INVAL; + goto free; + } +#endif + + build_info = mailmime_new_empty(content, mime_fields); + if (build_info == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = build_info; + + return MAILIMF_NO_ERROR; + + free: + mailmime_content_free(content); + err: + return res; +} + +int mailmime_set_preamble_file(struct mailmime * build_info, + char * filename) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_FILE, MAILMIME_MECHANISM_8BIT, + 0, NULL, 0, filename); + if (data == NULL) + return MAILIMF_ERROR_MEMORY; + + build_info->mm_data.mm_multipart.mm_preamble = data; + + return MAILIMF_NO_ERROR; +} + +int mailmime_set_epilogue_file(struct mailmime * build_info, + char * filename) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_FILE, MAILMIME_MECHANISM_8BIT, + 0, NULL, 0, filename); + if (data == NULL) + return MAILIMF_ERROR_MEMORY; + + build_info->mm_data.mm_multipart.mm_epilogue = data; + + return MAILIMF_NO_ERROR; +} + +int mailmime_set_preamble_text(struct mailmime * build_info, + char * data_str, size_t length) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, + 0, data_str, length, NULL); + if (data == NULL) + return MAILIMF_ERROR_MEMORY; + + build_info->mm_data.mm_multipart.mm_preamble = data; + + return MAILIMF_NO_ERROR; +} + +int mailmime_set_epilogue_text(struct mailmime * build_info, + char * data_str, size_t length) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, + 0, data_str, length, NULL); + if (data == NULL) + return MAILIMF_ERROR_MEMORY; + + build_info->mm_data.mm_multipart.mm_epilogue = data; + + return MAILIMF_NO_ERROR; +} + + +int mailmime_set_body_file(struct mailmime * build_info, + char * filename) +{ + int encoding; + struct mailmime_data * data; + + encoding = mailmime_transfer_encoding_get(build_info->mm_mime_fields); + + data = mailmime_data_new(MAILMIME_DATA_FILE, encoding, + 0, NULL, 0, filename); + if (data == NULL) + return MAILIMF_ERROR_MEMORY; + + build_info->mm_data.mm_single = data; + + return MAILIMF_NO_ERROR; +} + +int mailmime_set_body_text(struct mailmime * build_info, + char * data_str, size_t length) +{ + int encoding; + struct mailmime_data * data; + + encoding = mailmime_transfer_encoding_get(build_info->mm_mime_fields); + + data = mailmime_data_new(MAILMIME_DATA_TEXT, encoding, + 0, data_str, length, NULL); + if (data == NULL) + return MAILIMF_ERROR_MEMORY; + + build_info->mm_data.mm_single = data; + + return MAILIMF_NO_ERROR; +} + + +/* add a part as subpart of a mime part */ + +int mailmime_add_part(struct mailmime * build_info, + struct mailmime * part) +{ + int r; + + if (build_info->mm_type == MAILMIME_MESSAGE) { + build_info->mm_data.mm_message.mm_msg_mime = part; + part->mm_parent_type = MAILMIME_MESSAGE; + part->mm_parent = build_info; + } + else if (build_info->mm_type == MAILMIME_MULTIPLE) { + r = clist_append(build_info->mm_data.mm_multipart.mm_mp_list, part); + if (r != 0) + return MAILIMF_ERROR_MEMORY; + + part->mm_parent_type = MAILMIME_MULTIPLE; + part->mm_parent = build_info; + part->mm_multipart_pos = + clist_end(build_info->mm_data.mm_multipart.mm_mp_list); + } + else { + return MAILIMF_ERROR_INVAL; + } + return MAILIMF_NO_ERROR; +} + +/* detach part from parent */ + +void mailmime_remove_part(struct mailmime * mime) +{ + struct mailmime * parent; + + parent = mime->mm_parent; + if (parent == NULL) + return; + + switch (mime->mm_parent_type) { + case MAILMIME_MESSAGE: + mime->mm_parent = NULL; + parent->mm_data.mm_message.mm_msg_mime = NULL; + break; + + case MAILMIME_MULTIPLE: + mime->mm_parent = NULL; + clist_delete(parent->mm_data.mm_multipart.mm_mp_list, + mime->mm_multipart_pos); + break; + } +} + + +/* + attach a part to a mime part and create multipart/mixed + when needed, when the parent part has already some part + attached to it. +*/ + +int mailmime_smart_add_part(struct mailmime * mime, + struct mailmime * mime_sub) +{ + struct mailmime * saved_sub; + struct mailmime * mp; + int res; + int r; + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + res = MAILIMF_ERROR_INVAL; + goto err; + + case MAILMIME_MULTIPLE: + r = mailmime_add_part(mime, mime_sub); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + return MAILIMF_NO_ERROR; + } + + /* MAILMIME_MESSAGE */ + + if (mime->mm_data.mm_message.mm_msg_mime == NULL) { + /* there is no subpart, we can simply attach it */ + + r = mailmime_add_part(mime, mime_sub); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + return MAILIMF_NO_ERROR; + } + + if (mime->mm_data.mm_message.mm_msg_mime->mm_type == MAILMIME_MULTIPLE) { + /* in case the subpart is multipart, simply attach it to the subpart */ + + return mailmime_add_part(mime->mm_data.mm_message.mm_msg_mime, mime_sub); + } + + /* we save the current subpart, ... */ + + saved_sub = mime->mm_data.mm_message.mm_msg_mime; + + /* create a multipart */ + + mp = mailmime_multiple_new("multipart/mixed"); + if (mp == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + /* detach the saved subpart from the parent */ + + mailmime_remove_part(saved_sub); + + /* the created multipart is the new child of the parent */ + + r = mailmime_add_part(mime, mp); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_MEMORY; + goto free_mp; + } + + /* then, attach the saved subpart and ... */ + + r = mailmime_add_part(mp, saved_sub); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_MEMORY; + goto free_saved_sub; + } + + /* the given part to the parent */ + + r = mailmime_add_part(mp, mime_sub); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_MEMORY; + goto free_saved_sub; + } + + return MAILIMF_NO_ERROR; + + free_mp: + mailmime_free(mp); + free_saved_sub: + mailmime_free(saved_sub); + err: + return res; +} + + + +/* detach part from parent and free it only if the part has no child */ + +int mailmime_smart_remove_part(struct mailmime * mime) +{ + struct mailmime * parent; + int res; + + parent = mime->mm_parent; + if (parent == NULL) { + res = MAILIMF_ERROR_INVAL; + goto err; + } + + switch (mime->mm_type) { + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + res = MAILIMF_ERROR_INVAL; + goto err; + } + + mailmime_remove_part(mime); + + mailmime_free(mime); + + return MAILIMF_NO_ERROR; + + case MAILMIME_MULTIPLE: + if (!clist_isempty(mime->mm_data.mm_multipart.mm_mp_list)) { + res = MAILIMF_ERROR_INVAL; + goto err; + } + + mailmime_remove_part(mime); + + mailmime_free(mime); + + return MAILIMF_NO_ERROR; + + case MAILMIME_SINGLE: + mailmime_remove_part(mime); + + mailmime_free(mime); + + return MAILIMF_NO_ERROR; + + default: + return MAILIMF_ERROR_INVAL; + } + + err: + return res; +} + + +/* create a mailmime_content structure (Content-Type field) */ + +struct mailmime_content * mailmime_content_new_with_str(const char * str) +{ + int r; + size_t cur_token; + struct mailmime_content * content; + + cur_token = 0; + r = mailmime_content_parse(str, strlen(str), &cur_token, &content); + if (r != MAILIMF_NO_ERROR) + return NULL; + + return content; +} + +/* create MIME fields with only the field Content-Transfer-Encoding */ + +struct mailmime_fields * mailmime_fields_new_encoding(int type) +{ + struct mailmime_mechanism * encoding; + struct mailmime_fields * mime_fields; + + encoding = mailmime_mechanism_new(type, NULL); + if (encoding == NULL) + goto err; + + mime_fields = mailmime_fields_new_with_data(encoding, + NULL, NULL, NULL, NULL); + if (mime_fields == NULL) + goto free; + + return mime_fields; + + free: + mailmime_mechanism_free(encoding); + err: + return NULL; +} + + +/* create a multipart MIME part */ + +struct mailmime * mailmime_multiple_new(const char * type) +{ + struct mailmime_fields * mime_fields; + struct mailmime_content * content; + struct mailmime * mp; + + mime_fields = mailmime_fields_new_empty(); + if (mime_fields == NULL) + goto err; + + content = mailmime_content_new_with_str(type); + if (content == NULL) + goto free_fields; + + mp = mailmime_new_empty(content, mime_fields); + if (mp == NULL) + goto free_content; + + return mp; + + free_content: + mailmime_content_free(content); + free_fields: + mailmime_fields_free(mime_fields); + err: + return NULL; +} + + + +void mailmime_set_imf_fields(struct mailmime * build_info, + struct mailimf_fields * mm_fields) +{ + build_info->mm_data.mm_message.mm_fields = mm_fields; +} + +#if 0 +struct mailmime_content * mailmime_get_content(char * mime_type) +{ + struct mailmime_content *content; + int r; + size_t cur_token; + + cur_token = 0; + r = mailmime_content_parse(mime_type, strlen(mime_type), + &cur_token, &content); + if (r != MAILIMF_NO_ERROR) + return NULL; + + return content; +} +#endif + + + + +struct mailmime_disposition * +mailmime_disposition_new_with_data(int type, + char * filename, char * creation_date, char * modification_date, + char * read_date, size_t size) +{ + struct mailmime_disposition_type * dsp_type; + clist * list; + int r; + struct mailmime_disposition_parm * parm; + struct mailmime_disposition * dsp; + + dsp_type = mailmime_disposition_type_new(type, NULL); + if (dsp_type == NULL) + goto err; + + list = clist_new(); + if (list == NULL) + goto free_dsp_type; + + if (filename != NULL) { + parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_FILENAME, + filename, NULL, NULL, NULL, 0, NULL); + if (parm == NULL) + goto free_list; + + r = clist_append(list, parm); + if (r < 0) { + mailmime_disposition_parm_free(parm); + goto free_list; + } + } + + if (creation_date != NULL) { + parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_CREATION_DATE, + NULL, creation_date, NULL, NULL, 0, NULL); + if (parm == NULL) + goto free_list; + + r = clist_append(list, parm); + if (r < 0) { + mailmime_disposition_parm_free(parm); + goto free_list; + } + } + + if (modification_date != NULL) { + parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE, + NULL, NULL, modification_date, NULL, 0, NULL); + if (parm == NULL) + goto free_list; + + r = clist_append(list, parm); + if (r < 0) { + mailmime_disposition_parm_free(parm); + goto free_list; + } + } + + if (read_date != NULL) { + parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_READ_DATE, + NULL, NULL, NULL, read_date, 0, NULL); + if (parm == NULL) + goto free_list; + + r = clist_append(list, parm); + if (r < 0) { + mailmime_disposition_parm_free(parm); + goto free_list; + } + } + + if (size != (size_t) -1) { + parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_SIZE, + NULL, NULL, NULL, NULL, size, NULL); + if (parm == NULL) + goto free_list; + + r = clist_append(list, parm); + if (r < 0) { + mailmime_disposition_parm_free(parm); + goto free_list; + } + } + + dsp = mailmime_disposition_new(dsp_type, list); + + return dsp; + + free_list: + clist_foreach(list, (clist_func) mailmime_disposition_parm_free, NULL); + clist_free(list); + free_dsp_type: + mailmime_disposition_type_free(dsp_type); + err: + return NULL; +} + + +static void mailmime_disposition_single_fields_init(struct + mailmime_single_fields * single_fields, + struct mailmime_disposition * fld_disposition) +{ + clistiter * cur; + + single_fields->fld_disposition = fld_disposition; + + for(cur = clist_begin(fld_disposition->dsp_parms) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_disposition_parm * param; + + param = clist_content(cur); + + switch (param->pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + single_fields->fld_disposition_filename = param->pa_data.pa_filename; + break; + + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + single_fields->fld_disposition_creation_date = + param->pa_data.pa_creation_date; + break; + + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + single_fields->fld_disposition_modification_date = + param->pa_data.pa_modification_date; + break; + + case MAILMIME_DISPOSITION_PARM_READ_DATE: + single_fields->fld_disposition_read_date = + param->pa_data.pa_read_date; + break; + + case MAILMIME_DISPOSITION_PARM_SIZE: + single_fields->fld_disposition_size = param->pa_data.pa_size; + break; + } + } +} + +static void mailmime_content_single_fields_init(struct + mailmime_single_fields * single_fields, + struct mailmime_content * fld_content) +{ + clistiter * cur; + + single_fields->fld_content = fld_content; + + for(cur = clist_begin(fld_content->ct_parameters) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = clist_content(cur); + + if (strcasecmp(param->pa_name, "boundary") == 0) + single_fields->fld_content_boundary = param->pa_value; + + if (strcasecmp(param->pa_name, "charset") == 0) + single_fields->fld_content_charset = param->pa_value; + + if (strcasecmp(param->pa_name, "name") == 0) + single_fields->fld_content_name = param->pa_value; + } +} + +void mailmime_single_fields_init(struct mailmime_single_fields * single_fields, + struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content) +{ + clistiter * cur; + + memset(single_fields, 0, sizeof(struct mailmime_single_fields)); + + if (fld_content != NULL) + mailmime_content_single_fields_init(single_fields, fld_content); + + if (fld_fields == NULL) + return; + + for(cur = clist_begin(fld_fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + + switch (field->fld_type) { + case MAILMIME_FIELD_TYPE: + mailmime_content_single_fields_init(single_fields, + field->fld_data.fld_content); + break; + + case MAILMIME_FIELD_TRANSFER_ENCODING: + single_fields->fld_encoding = field->fld_data.fld_encoding; + break; + + case MAILMIME_FIELD_ID: + single_fields->fld_id = field->fld_data.fld_id; + break; + + case MAILMIME_FIELD_DESCRIPTION: + single_fields->fld_description = field->fld_data.fld_description; + break; + + case MAILMIME_FIELD_VERSION: + single_fields->fld_version = field->fld_data.fld_version; + break; + + case MAILMIME_FIELD_DISPOSITION: + mailmime_disposition_single_fields_init(single_fields, + field->fld_data.fld_disposition); + break; + + case MAILMIME_FIELD_LANGUAGE: + single_fields->fld_language = field->fld_data.fld_language; + break; + + case MAILMIME_FIELD_LOCATION: + single_fields->fld_location = field->fld_data.fld_location; + break; + } + } +} + +struct mailmime_single_fields * +mailmime_single_fields_new(struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content) +{ + struct mailmime_single_fields * single_fields; + + single_fields = malloc(sizeof(struct mailmime_single_fields)); + if (single_fields == NULL) + goto err; + + mailmime_single_fields_init(single_fields, fld_fields, fld_content); + + return single_fields; + + err: + return NULL; +} + + +void mailmime_single_fields_free(struct mailmime_single_fields * + single_fields) +{ + free(single_fields); +} + +struct mailmime_fields * mailmime_fields_new_filename(int dsp_type, + char * filename, int encoding_type) +{ + struct mailmime_disposition * dsp; + struct mailmime_mechanism * encoding; + struct mailmime_fields * mime_fields; + + dsp = mailmime_disposition_new_with_data(dsp_type, + filename, NULL, NULL, NULL, (size_t) -1); + if (dsp == NULL) + goto err; + + encoding = mailmime_mechanism_new(encoding_type, NULL); + if (encoding == NULL) + goto free_dsp; + + mime_fields = mailmime_fields_new_with_data(encoding, + NULL, NULL, dsp, NULL); + if (mime_fields == NULL) + goto free_encoding; + + return mime_fields; + + free_encoding: + mailmime_encoding_free(encoding); + free_dsp: + mailmime_disposition_free(dsp); + err: + return NULL; +} + +struct mailmime_data * +mailmime_data_new_data(int encoding, int encoded, + const char * data, size_t length) +{ + return mailmime_data_new(MAILMIME_DATA_TEXT, encoding, encoded, data, length, NULL); +} + +struct mailmime_data * +mailmime_data_new_file(int encoding, int encoded, + char * filename) +{ + return mailmime_data_new(MAILMIME_DATA_FILE, encoding, encoded, NULL, 0, filename); +} + + +struct mailmime_parameter * +mailmime_param_new_with_data(char * name, char * value) +{ + char * param_name; + char * param_value; + struct mailmime_parameter * param; + + param_name = strdup(name); + if (param_name == NULL) + goto err; + + param_value = strdup(value); + if (param_value == NULL) + goto free_name; + + param = mailmime_parameter_new(param_name, param_value); + if (param == NULL) + goto free_value; + + return param; + + free_value: + free(param_value); + free_name: + free(param_name); + err: + return NULL; +} diff --git a/Sources/libetpan/low-level/mime/mailmime_types_helper.h b/Sources/libetpan/low-level/mime/mailmime_types_helper.h new file mode 100644 index 00000000..8b03e15c --- /dev/null +++ b/Sources/libetpan/low-level/mime/mailmime_types_helper.h @@ -0,0 +1,204 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_types_helper.h,v 1.17 2008/01/14 17:13:53 hoa Exp $ + */ + +#ifndef MAILMIME_TYPES_HELPER_H + +#define MAILMIME_TYPES_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +LIBETPAN_EXPORT +int mailmime_transfer_encoding_get(struct mailmime_fields * fields); + +LIBETPAN_EXPORT +struct mailmime_disposition * +mailmime_disposition_new_filename(int type, char * filename); + +LIBETPAN_EXPORT +struct mailmime_fields * mailmime_fields_new_empty(void); + +LIBETPAN_EXPORT +int mailmime_fields_add(struct mailmime_fields * fields, + struct mailmime_field * field); + +LIBETPAN_EXPORT +struct mailmime_fields * +mailmime_fields_new_with_data(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language); + +LIBETPAN_EXPORT +struct mailmime_fields * +mailmime_fields_new_with_version(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language); + +LIBETPAN_EXPORT +struct mailmime_content * mailmime_get_content_message(void); +LIBETPAN_EXPORT +struct mailmime_content * mailmime_get_content_text(void); +/* struct mailmime_content * mailmime_get_content(char * mime_type); */ + +#define mailmime_get_content mailmime_content_new_with_str + +LIBETPAN_EXPORT +struct mailmime_data * +mailmime_data_new_data(int encoding, int encoded, + const char * data, size_t length); + +LIBETPAN_EXPORT +struct mailmime_data * +mailmime_data_new_file(int encoding, int encoded, + char * filename); + +#if 0 +struct mailmime * +mailmime_new_message_file(char * filename); + +struct mailmime * +mailmime_new_message_text(char * data_str, size_t length); +#endif + +LIBETPAN_EXPORT +struct mailmime * +mailmime_new_message_data(struct mailmime * msg_mime); + +LIBETPAN_EXPORT +struct mailmime * +mailmime_new_empty(struct mailmime_content * content, + struct mailmime_fields * mime_fields); + +LIBETPAN_EXPORT +int +mailmime_new_with_content(const char * content_type, + struct mailmime_fields * mime_fields, + struct mailmime ** result); + +LIBETPAN_EXPORT +int mailmime_set_preamble_file(struct mailmime * build_info, + char * filename); + +LIBETPAN_EXPORT +int mailmime_set_epilogue_file(struct mailmime * build_info, + char * filename); + +LIBETPAN_EXPORT +int mailmime_set_preamble_text(struct mailmime * build_info, + char * data_str, size_t length); + +LIBETPAN_EXPORT +int mailmime_set_epilogue_text(struct mailmime * build_info, + char * data_str, size_t length); + +LIBETPAN_EXPORT +int mailmime_set_body_file(struct mailmime * build_info, + char * filename); + +LIBETPAN_EXPORT +int mailmime_set_body_text(struct mailmime * build_info, + char * data_str, size_t length); + +LIBETPAN_EXPORT +int mailmime_add_part(struct mailmime * build_info, + struct mailmime * part); + +LIBETPAN_EXPORT +void mailmime_remove_part(struct mailmime * mime); + +LIBETPAN_EXPORT +void mailmime_set_imf_fields(struct mailmime * build_info, + struct mailimf_fields * fields); + + +LIBETPAN_EXPORT +struct mailmime_disposition * +mailmime_disposition_new_with_data(int type, + char * filename, char * creation_date, char * modification_date, + char * read_date, size_t size); + +LIBETPAN_EXPORT +void mailmime_single_fields_init(struct mailmime_single_fields * single_fields, + struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content); + +LIBETPAN_EXPORT +struct mailmime_single_fields * +mailmime_single_fields_new(struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content); + +LIBETPAN_EXPORT +void mailmime_single_fields_free(struct mailmime_single_fields * + single_fields); + +LIBETPAN_EXPORT +int mailmime_smart_add_part(struct mailmime * mime, + struct mailmime * mime_sub); + +LIBETPAN_EXPORT +int mailmime_smart_remove_part(struct mailmime * mime); + +LIBETPAN_EXPORT +struct mailmime_content * mailmime_content_new_with_str(const char * str); + +LIBETPAN_EXPORT +struct mailmime_fields * mailmime_fields_new_encoding(int type); + +LIBETPAN_EXPORT +struct mailmime * mailmime_multiple_new(const char * type); + +LIBETPAN_EXPORT +struct mailmime_fields * mailmime_fields_new_filename(int dsp_type, + char * filename, int encoding_type); + +LIBETPAN_EXPORT +struct mailmime_parameter * +mailmime_param_new_with_data(char * name, char * value); + +LIBETPAN_EXPORT +char * mailmime_generate_boundary(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/mime/mailmime_write.h b/Sources/libetpan/low-level/mime/mailmime_write.h new file mode 100644 index 00000000..bb11c53a --- /dev/null +++ b/Sources/libetpan/low-level/mime/mailmime_write.h @@ -0,0 +1,73 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_write.h,v 1.13 2004/11/21 21:53:39 hoa Exp $ + */ + +#ifndef MAILMIME_WRITE_H + +#define MAILMIME_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +int mailmime_fields_write(FILE * f, int * col, + struct mailmime_fields * fields); + +int mailmime_content_write(FILE * f, int * col, + struct mailmime_content * content); + +int mailmime_content_type_write(FILE * f, int * col, + struct mailmime_content * content); + +int mailmime_write(FILE * f, int * col, + struct mailmime * build_info); + +int mailmime_quoted_printable_write(FILE * f, int * col, int istext, + const char * text, size_t size); + +int mailmime_base64_write(FILE * f, int * col, + const char * text, size_t size); + +int mailmime_data_write(FILE * f, int * col, + struct mailmime_data * data, + int istext); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/mime/mailmime_write_file.c b/Sources/libetpan/low-level/mime/mailmime_write_file.c new file mode 100644 index 00000000..44689d62 --- /dev/null +++ b/Sources/libetpan/low-level/mime/mailmime_write_file.c @@ -0,0 +1,164 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_write_file.c,v 1.5 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailmime_write_file.h" + +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#include +#ifdef HAVE_SYS_MMAN_H +# include +#endif + +#include "mailmime_content.h" +#include "mailmime_types_helper.h" +#include "mailmime_write_generic.h" + +static int do_write(void * data, const char * str, size_t length) +{ + FILE * f; + + f = data; + + return (int) fwrite(str, 1, length, f); +} + + +int mailmime_fields_write_file(FILE * f, int * col, + struct mailmime_fields * fields) +{ + return mailmime_fields_write_driver(do_write, f, col, fields); +} + +int mailmime_content_write_file(FILE * f, int * col, + struct mailmime_content * content) +{ + return mailmime_content_write_driver(do_write, f, col, content); +} + +int mailmime_content_type_write_file(FILE * f, int * col, + struct mailmime_content * content) +{ + return mailmime_content_type_write_driver(do_write, f, col, content); +} + +int mailmime_write_file(FILE * f, int * col, + struct mailmime * build_info) +{ + return mailmime_write_driver(do_write, f, col, build_info); +} + +int mailmime_quoted_printable_write_file(FILE * f, int * col, int istext, + const char * text, size_t size) +{ + return mailmime_quoted_printable_write_driver(do_write, f, col, + istext, text, size); +} + +int mailmime_base64_write_file(FILE * f, int * col, + const char * text, size_t size) +{ + return mailmime_base64_write_driver(do_write, f, col, text, size); +} + +int mailmime_data_write_file(FILE * f, int * col, + struct mailmime_data * data, + int istext) +{ + return mailmime_data_write_driver(do_write, f, col, data, istext); +} + + + + +/* binary compatibility with 0.34 - begin */ + +#ifdef MAILMIME_WRITE_COMPATIBILITY +int mailmime_fields_write(FILE * f, int * col, + struct mailmime_fields * fields) +{ + return mailmime_fields_write_file(f, col, fields); +} + +int mailmime_content_write(FILE * f, int * col, + struct mailmime_content * content) +{ + return mailmime_content_write_file(f, col, content); +} + +int mailmime_content_type_write(FILE * f, int * col, + struct mailmime_content * content) +{ + return mailmime_content_type_write_file(f, col, content); +} + +int mailmime_write(FILE * f, int * col, + struct mailmime * build_info) +{ + return mailmime_write_file(f, col, build_info); +} + +int mailmime_quoted_printable_write(FILE * f, int * col, int istext, + const char * text, size_t size) +{ + return mailmime_quoted_printable_write_file(f, col, + istext, text, size); +} + +int mailmime_base64_write(FILE * f, int * col, + const char * text, size_t size) +{ + return mailmime_base64_write_file(f, col, text, size); +} + +int mailmime_data_write(FILE * f, int * col, + struct mailmime_data * data, + int istext) +{ + return mailmime_data_write_file(f, col, data, istext); +} +#endif + +/* binary compatibility with 0.34 - end */ diff --git a/Sources/libetpan/low-level/mime/mailmime_write_file.h b/Sources/libetpan/low-level/mime/mailmime_write_file.h new file mode 100644 index 00000000..e6707365 --- /dev/null +++ b/Sources/libetpan/low-level/mime/mailmime_write_file.h @@ -0,0 +1,118 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_write_file.h,v 1.3 2005/06/01 12:22:19 smarinier Exp $ + */ + +#ifndef MAILMIME_WRITE_FILE_H + +#define MAILMIME_WRITE_FILE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#define MAILMIME_WRITE_COMPATIBILITY + +LIBETPAN_EXPORT +int mailmime_fields_write_file(FILE * f, int * col, + struct mailmime_fields * fields); + +LIBETPAN_EXPORT +int mailmime_content_write_file(FILE * f, int * col, + struct mailmime_content * content); + +LIBETPAN_EXPORT +int mailmime_content_type_write_file(FILE * f, int * col, + struct mailmime_content * content); + +LIBETPAN_EXPORT +int mailmime_write_file(FILE * f, int * col, + struct mailmime * build_info); + +LIBETPAN_EXPORT +int mailmime_quoted_printable_write_file(FILE * f, int * col, int istext, + const char * text, size_t size); + +LIBETPAN_EXPORT +int mailmime_base64_write_file(FILE * f, int * col, + const char * text, size_t size); + +LIBETPAN_EXPORT +int mailmime_data_write_file(FILE * f, int * col, + struct mailmime_data * data, + int istext); + + +/* binary compatibility with 0.34 - begin */ + +#ifdef MAILMIME_WRITE_COMPATIBILITY +LIBETPAN_EXPORT +int mailmime_fields_write(FILE * f, int * col, + struct mailmime_fields * fields); + +LIBETPAN_EXPORT +int mailmime_content_write(FILE * f, int * col, + struct mailmime_content * content); + +LIBETPAN_EXPORT +int mailmime_content_type_write(FILE * f, int * col, + struct mailmime_content * content); + +LIBETPAN_EXPORT +int mailmime_write(FILE * f, int * col, + struct mailmime * build_info); + +LIBETPAN_EXPORT +int mailmime_quoted_printable_write(FILE * f, int * col, int istext, + const char * text, size_t size); + +LIBETPAN_EXPORT +int mailmime_base64_write(FILE * f, int * col, + const char * text, size_t size); + +LIBETPAN_EXPORT +int mailmime_data_write(FILE * f, int * col, + struct mailmime_data * data, + int istext); +#endif + +/* binary compatibility with 0.34 - end */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/mime/mailmime_write_generic.c b/Sources/libetpan/low-level/mime/mailmime_write_generic.c new file mode 100644 index 00000000..9c332aaf --- /dev/null +++ b/Sources/libetpan/low-level/mime/mailmime_write_generic.c @@ -0,0 +1,1545 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_write_generic.c,v 1.13 2011/06/25 15:30:46 hoa Exp $ + */ +#define HAVE_CONFIG_H 1 + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailmime_write_generic.h" + +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#include +#ifdef HAVE_SYS_MMAN_H +# include +#endif +#ifdef WIN32 +# include "win_etpan.h" +#endif + +#include "mailimf_write_generic.h" +#include "mailmime_content.h" +#include "mailmime_types_helper.h" + +#define MAX_MAIL_COL 78 + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +static int mailmime_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_field * field); + +static int mailmime_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, char * id); + +static int mailmime_description_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, char * descr); + +static int mailmime_version_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, uint32_t version); + +static int mailmime_encoding_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_mechanism * encoding); + +static int mailmime_location_write_driver(int (* do_write)(void *, const char *, size_t), void *data, int *col, + char *location); + +static int mailmime_language_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_language * language); + +static int mailmime_disposition_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_disposition * + disposition); + +static int +mailmime_disposition_param_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_disposition_parm * param); + +static int mailmime_parameter_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_parameter * param); + +/* +static int mailmime_content_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_content * content); +*/ + +static int mailmime_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_type * type); + +static int +mailmime_discrete_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_discrete_type * discrete_type); + +static int +mailmime_composite_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_composite_type * composite_type); + +static int mailmime_sub_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime * build_info); + + +/* ***** */ + +int mailmime_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, struct mailmime_fields * fields) +{ + int r; + clistiter * cur; + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_field * field; + + field = cur->data; + r = mailmime_field_write_driver(do_write, data, col, field); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + +static int mailmime_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_field * field) +{ + int r; + + switch (field->fld_type) { + case MAILMIME_FIELD_TYPE: + r = mailmime_content_write_driver(do_write, data, col, field->fld_data.fld_content); + break; + + case MAILMIME_FIELD_TRANSFER_ENCODING: + r = mailmime_encoding_write_driver(do_write, data, col, field->fld_data.fld_encoding); + break; + + case MAILMIME_FIELD_ID: + r = mailmime_id_write_driver(do_write, data, col, field->fld_data.fld_id); + break; + + case MAILMIME_FIELD_DESCRIPTION: + r = mailmime_description_write_driver(do_write, data, col, field->fld_data.fld_description); + break; + + case MAILMIME_FIELD_VERSION: + r = mailmime_version_write_driver(do_write, data, col, field->fld_data.fld_version); + break; + + case MAILMIME_FIELD_DISPOSITION: + r = mailmime_disposition_write_driver(do_write, data, col, field->fld_data.fld_disposition); + break; + + case MAILMIME_FIELD_LANGUAGE: + r = mailmime_language_write_driver(do_write, data, col, field->fld_data.fld_language); + break; + + case MAILMIME_FIELD_LOCATION: + r = mailmime_location_write_driver(do_write, data, col, field->fld_data.fld_location); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int mailmime_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, char * id) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Content-ID: ", 12); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, id, strlen(id)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailmime_description_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, char * descr) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Content-Description: ", 21); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, descr, strlen(descr)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailmime_version_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, uint32_t version) +{ + int r; + char versionstr[40]; + + r = mailimf_string_write_driver(do_write, data, col, "MIME-Version: ", 14); + if (r != MAILIMF_NO_ERROR) + return r; + + snprintf(versionstr, 40, "%i.%i", version >> 16, version & 0xFFFF); + + r = mailimf_string_write_driver(do_write, data, col, versionstr, strlen(versionstr)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailmime_encoding_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_mechanism * encoding) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Content-Transfer-Encoding: ", 27); + if (r != MAILIMF_NO_ERROR) + return r; + + switch (encoding->enc_type) { + case MAILMIME_MECHANISM_7BIT: + r = mailimf_string_write_driver(do_write, data, col, "7bit", 4); + break; + + case MAILMIME_MECHANISM_8BIT: + r = mailimf_string_write_driver(do_write, data, col, "8bit", 4); + break; + + case MAILMIME_MECHANISM_BINARY: + r = mailimf_string_write_driver(do_write, data, col, "binary", 6); + break; + + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + r = mailimf_string_write_driver(do_write, data, col, "quoted-printable", 16); + break; + + case MAILMIME_MECHANISM_BASE64: + r = mailimf_string_write_driver(do_write, data, col, "base64", 6); + break; + + case MAILMIME_MECHANISM_TOKEN: + r = mailimf_string_write_driver(do_write, data, col, encoding->enc_token, + strlen(encoding->enc_token)); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailmime_location_write_driver(int (* do_write)(void *, const char *, size_t), void *data, int *col, + char *location) +{ + int r; + int len = strlen(location); + + r = mailimf_string_write_driver(do_write, data, col, "Content-Location: ", 18); + if (r != MAILIMF_NO_ERROR) + return r; + + if (*col > 1 && *col + len > MAX_MAIL_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write_driver(do_write, data, col, location, len); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int mailmime_language_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_language * language) +{ + int r; + clistiter * cur; + int first; + + r = mailimf_string_write_driver(do_write, data, col, "Content-Language: ", 18); + if (r != MAILIMF_NO_ERROR) + return r; + + first = TRUE; + + for(cur = clist_begin(language->lg_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * lang; + size_t len; + + lang = clist_content(cur); + len = strlen(lang); + + if (!first) { + r = mailimf_string_write_driver(do_write, data, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + + if (* col > 1) { + + if (* col + len > MAX_MAIL_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } + + r = mailimf_string_write_driver(do_write, data, col, lang, len); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailmime_disposition_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_disposition * + disposition) +{ + struct mailmime_disposition_type * dsp_type; + int r; + clistiter * cur; + + dsp_type = disposition->dsp_type; + + r = mailimf_string_write_driver(do_write, data, col, "Content-Disposition: ", 21); + if (r != MAILIMF_NO_ERROR) + return r; + + switch (dsp_type->dsp_type) { + case MAILMIME_DISPOSITION_TYPE_INLINE: + r = mailimf_string_write_driver(do_write, data, col, "inline", 6); + break; + + case MAILMIME_DISPOSITION_TYPE_ATTACHMENT: + r = mailimf_string_write_driver(do_write, data, col, "attachment", 10); + break; + + case MAILMIME_DISPOSITION_TYPE_EXTENSION: + r = mailimf_string_write_driver(do_write, data, col, dsp_type->dsp_extension, + strlen(dsp_type->dsp_extension)); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + for(cur = clist_begin(disposition->dsp_parms) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_disposition_parm * param; + + param = cur->data; + + r = mailimf_string_write_driver(do_write, data, col, "; ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailmime_disposition_param_write_driver(do_write, data, col, param); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int +mailmime_disposition_param_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_disposition_parm * param) +{ + size_t len; + char sizestr[20]; + int r; + + switch (param->pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + len = strlen("filename=") + strlen(param->pa_data.pa_filename); + break; + + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + len = strlen("creation-date=") + strlen(param->pa_data.pa_creation_date); + break; + + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + len = strlen("modification-date=") + + strlen(param->pa_data.pa_modification_date); + break; + + case MAILMIME_DISPOSITION_PARM_READ_DATE: + len = strlen("read-date=") + strlen(param->pa_data.pa_read_date); + break; + + case MAILMIME_DISPOSITION_PARM_SIZE: + snprintf(sizestr, 20, "%lu", (unsigned long) param->pa_data.pa_size); + len = strlen("size=") + strlen(sizestr); + break; + + case MAILMIME_DISPOSITION_PARM_PARAMETER: + len = strlen(param->pa_data.pa_parameter->pa_name) + 1 + + strlen(param->pa_data.pa_parameter->pa_value); + break; + + default: + return MAILIMF_ERROR_INVAL; + } + + if (* col > 1) { + + if (* col + len > MAX_MAIL_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } + + switch (param->pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + r = mailimf_string_write_driver(do_write, data, col, "filename=", 9); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_quoted_string_write_driver(do_write, data, col, + param->pa_data.pa_filename, strlen(param->pa_data.pa_filename)); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + r = mailimf_string_write_driver(do_write, data, col, "creation-date=", 14); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_quoted_string_write_driver(do_write, data, col, param->pa_data.pa_creation_date, + strlen(param->pa_data.pa_creation_date)); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + r = mailimf_string_write_driver(do_write, data, col, "modification-date=", 18); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_quoted_string_write_driver(do_write, data, col, + param->pa_data.pa_modification_date, + strlen(param->pa_data.pa_modification_date)); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_DISPOSITION_PARM_READ_DATE: + r = mailimf_string_write_driver(do_write, data, col, "read-date=", 10); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_quoted_string_write_driver(do_write, data, col, param->pa_data.pa_read_date, + strlen(param->pa_data.pa_read_date)); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_DISPOSITION_PARM_SIZE: + r = mailimf_string_write_driver(do_write, data, col, "size=", 5); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, sizestr, strlen(sizestr)); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_DISPOSITION_PARM_PARAMETER: + r = mailmime_parameter_write_driver(do_write, data, col, param->pa_data.pa_parameter); + if (r != MAILIMF_NO_ERROR) + return r; + break; + } + + return MAILIMF_NO_ERROR; +} + +static int mailmime_parameter_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_parameter * param) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, param->pa_name, + strlen(param->pa_name)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "=", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_quoted_string_write_driver(do_write, data, col, param->pa_value, + strlen(param->pa_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +int mailmime_content_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_content * content) +{ + clistiter * cur; + size_t len; + int r; + + r = mailmime_type_write_driver(do_write, data, col, content->ct_type); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "/", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, content->ct_subtype, + strlen(content->ct_subtype)); + if (r != MAILIMF_NO_ERROR) + return r; + + if (content->ct_parameters != NULL) { + for(cur = clist_begin(content->ct_parameters) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = cur->data; + + r = mailimf_string_write_driver(do_write, data, col, "; ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + len = strlen(param->pa_name) + 1 + strlen(param->pa_value); + + if (* col > 1) { + + if (* col + len > MAX_MAIL_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } + + r = mailmime_parameter_write_driver(do_write, data, col, param); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + + return MAILIMF_NO_ERROR; +} + +int mailmime_content_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_content * content) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Content-Type: ", 14); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailmime_content_type_write_driver(do_write, data, col, content); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int mailmime_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_type * type) +{ + int r; + + switch (type->tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + r = mailmime_discrete_type_write_driver(do_write, data, col, type->tp_data.tp_discrete_type); + break; + + case MAILMIME_TYPE_COMPOSITE_TYPE: + r = mailmime_composite_type_write_driver(do_write, data, col, type->tp_data.tp_composite_type); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int +mailmime_discrete_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_discrete_type * discrete_type) +{ + int r; + + switch (discrete_type->dt_type) { + case MAILMIME_DISCRETE_TYPE_TEXT: + r = mailimf_string_write_driver(do_write, data, col, "text", 4); + break; + + case MAILMIME_DISCRETE_TYPE_IMAGE: + r = mailimf_string_write_driver(do_write, data, col, "image", 5); + break; + + case MAILMIME_DISCRETE_TYPE_AUDIO: + r = mailimf_string_write_driver(do_write, data, col, "audio", 5); + break; + + case MAILMIME_DISCRETE_TYPE_VIDEO: + r = mailimf_string_write_driver(do_write, data, col, "video", 5); + break; + + case MAILMIME_DISCRETE_TYPE_APPLICATION: + r = mailimf_string_write_driver(do_write, data, col, "application", 11); + break; + + case MAILMIME_DISCRETE_TYPE_EXTENSION: + r = mailimf_string_write_driver(do_write, data, col, discrete_type->dt_extension, + strlen(discrete_type->dt_extension)); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int +mailmime_composite_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_composite_type * composite_type) +{ + int r; + + switch (composite_type->ct_type) { + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + r = mailimf_string_write_driver(do_write, data, col, "message", 7); + break; + + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + r = mailimf_string_write_driver(do_write, data, col, "multipart", 9); + break; + + case MAILMIME_COMPOSITE_TYPE_EXTENSION: + r = mailimf_string_write_driver(do_write, data, col, composite_type->ct_token, + strlen(composite_type->ct_token)); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + + + + +/* ****************************************************************** */ +/* message */ + +/* +static int mailmime_data_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_data * data, + int is_text); +*/ + +static int mailmime_text_content_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, int encoding, + int istext, + const char * text, size_t size); + +/* +static int mailmime_base64_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + char * text, size_t size); + +static int mailmime_quoted_printable_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, int istext, + char * text, size_t size); +*/ + +static int mailmime_part_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime * build_info) +{ + clistiter * cur; + int first; + int r; + char * boundary; + int istext; + int res; + + istext = TRUE; + boundary = NULL; + + if (build_info->mm_content_type != NULL) { + if (build_info->mm_type == MAILMIME_MULTIPLE) { + boundary = mailmime_extract_boundary(build_info->mm_content_type); + if (boundary == NULL) { + boundary = mailmime_generate_boundary(); + if (boundary == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + } + } + + if (build_info->mm_content_type->ct_type->tp_type == + MAILMIME_TYPE_DISCRETE_TYPE) { + if (build_info->mm_content_type->ct_type->tp_data.tp_discrete_type->dt_type != + MAILMIME_DISCRETE_TYPE_TEXT) + istext = FALSE; + } + } + + switch (build_info->mm_type) { + case MAILMIME_SINGLE: + + /* 1-part body */ + + if (build_info->mm_data.mm_single != NULL) { + r = mailmime_data_write_driver(do_write, data, col, build_info->mm_data.mm_single, istext); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_boundary; + } + } + + break; + + case MAILMIME_MULTIPLE: + + /* multi-part */ + + + /* preamble */ + + if (build_info->mm_data.mm_multipart.mm_preamble != NULL) { + r = mailmime_data_write_driver(do_write, data, col, + build_info->mm_data.mm_multipart.mm_preamble, TRUE); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_boundary; + } + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_boundary; + } + } + + /* sub-parts */ + + first = TRUE; + + for(cur = clist_begin(build_info->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * subpart; + + subpart = cur->data; + + if (!first) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_boundary; + } + } + else { + first = FALSE; + } + + r = mailimf_string_write_driver(do_write, data, col, "--", 2); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_boundary; + } + + if (boundary == NULL) { + // Make clang static analyzer happy. + res = MAILIMF_ERROR_MEMORY; + goto free_boundary; + } + + r = mailimf_string_write_driver(do_write, data, col, boundary, strlen(boundary)); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_boundary; + } + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_boundary; + } + + r = mailmime_sub_write_driver(do_write, data, col, subpart); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_boundary; + } + } + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_boundary; + } + + r = mailimf_string_write_driver(do_write, data, col, "--", 2); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_boundary; + } + + if (boundary == NULL) { + // Make clang static analyzer happy. + res = MAILIMF_ERROR_MEMORY; + goto free_boundary; + } + + r = mailimf_string_write_driver(do_write, data, col, boundary, strlen(boundary)); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_boundary; + } + + r = mailimf_string_write_driver(do_write, data, col, "--", 2); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_boundary; + } + + /* epilogue */ + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_boundary; + } + + if (build_info->mm_data.mm_multipart.mm_epilogue != NULL) { + r = mailmime_data_write_driver(do_write, data, col, + build_info->mm_data.mm_multipart.mm_epilogue, TRUE); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_boundary; + } + } + + break; + + case MAILMIME_MESSAGE: + + if (build_info->mm_data.mm_message.mm_fields != NULL) { + r = mailimf_fields_write_driver(do_write, data, col, + build_info->mm_data.mm_message.mm_fields); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_boundary; + } + } + + if (build_info->mm_mime_fields != NULL) { + int r; + clistiter * cur; + + for(cur = clist_begin(build_info->mm_mime_fields->fld_list) ; + cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_field * field; + + /* only MIME-Version field */ + field = cur->data; + if (field->fld_type == MAILMIME_FIELD_VERSION) { + r = mailmime_field_write_driver(do_write, data, col, field); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_boundary; + } + } + } + } + + /* encapsuled message */ + + if (build_info->mm_data.mm_message.mm_msg_mime != NULL) { + r = mailmime_sub_write_driver(do_write, data, col, + build_info->mm_data.mm_message.mm_msg_mime); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_boundary; + } + } + break; + + } + + free(boundary); + + return MAILIMF_NO_ERROR; + + free_boundary: + free(boundary); + err: + return res; +} + + +static int mailmime_sub_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime * build_info) +{ + int r; + +#if 0 + * col = 0; +#endif + /* MIME field - Content-Type */ + + if (build_info->mm_content_type != NULL) { + r = mailmime_content_write_driver(do_write, data, col, build_info->mm_content_type); + if (r != MAILIMF_NO_ERROR) + return r; + } + + /* other MIME fields */ + + if (build_info->mm_type != MAILMIME_MESSAGE) { + if (build_info->mm_mime_fields != NULL) { + r = mailmime_fields_write_driver(do_write, data, col, build_info->mm_mime_fields); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + else { + if (build_info->mm_mime_fields != NULL) { + int r; + clistiter * cur; + + /* filter out MIME-Version */ + for(cur = clist_begin(build_info->mm_mime_fields->fld_list) ; + cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_field * field; + + field = cur->data; + if (field->fld_type != MAILMIME_FIELD_VERSION) { + r = mailmime_field_write_driver(do_write, data, col, field); + if (r != MAILIMF_NO_ERROR) { + return r; + } + } + } + } + } + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return mailmime_part_write_driver(do_write, data, col, build_info); +} + +int mailmime_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime * build_info) +{ + if (build_info->mm_parent != NULL) + return mailmime_sub_write_driver(do_write, data, col, build_info); + else + return mailmime_part_write_driver(do_write, data, col, build_info); +} + + +int mailmime_data_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_data * mime_data, + int istext) +{ + int fd; + int r; + char * text; + struct stat buf; + int res; + + switch (mime_data->dt_type) { + case MAILMIME_DATA_TEXT: + + if (mime_data->dt_encoded) { + r = mailimf_string_write_driver(do_write, data, col, + mime_data->dt_data.dt_text.dt_data, + mime_data->dt_data.dt_text.dt_length); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + r = mailmime_text_content_write_driver(do_write, data, col, mime_data->dt_encoding, istext, + mime_data->dt_data.dt_text.dt_data, + mime_data->dt_data.dt_text.dt_length); + if (r != MAILIMF_NO_ERROR) + return r; + } + + break; + + case MAILMIME_DATA_FILE: + fd = open(mime_data->dt_data.dt_filename, O_RDONLY); + if (fd < 0) { + res = MAILIMF_ERROR_FILE; + goto err; + } + + r = fstat(fd, &buf); + if (r < 0) { + res = MAILIMF_ERROR_FILE; + goto close; + } + + if (buf.st_size != 0) { + text = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (text == (char *)MAP_FAILED) { + res = MAILIMF_ERROR_FILE; + goto close; + } + + if (mime_data->dt_encoded) { + r = mailimf_string_write_driver(do_write, data, col, text, buf.st_size); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto unmap; + } + } + else { + r = mailmime_text_content_write_driver(do_write, data, col, mime_data->dt_encoding, istext, + text, buf.st_size); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto unmap; + } + } + + munmap(text, buf.st_size); + } + close(fd); + + if (r != MAILIMF_NO_ERROR) + return r; + + break; + + unmap: + munmap(text, buf.st_size); + close: + close(fd); + err: + return res; + } + + return MAILIMF_NO_ERROR; +} + +static int mailmime_text_content_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, int encoding, + int istext, + const char * text, size_t size) +{ + switch (encoding) { + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + return mailmime_quoted_printable_write_driver(do_write, data, col, istext, text, size); + break; + + case MAILMIME_MECHANISM_BASE64: + return mailmime_base64_write_driver(do_write, data, col, text, size); + break; + + case MAILMIME_MECHANISM_7BIT: + case MAILMIME_MECHANISM_8BIT: + case MAILMIME_MECHANISM_BINARY: + default: + return mailimf_string_write_driver(do_write, data, col, text, size); + } +} + + +static const char base64_encoding[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +#define BASE64_MAX_COL 76 + +int mailmime_base64_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + const char * text, size_t size) +{ + int a; + int b; + int c; + size_t remains; + const char * p; + size_t count; + char ogroup[4]; + int r; + + remains = size; + p = text; + + while (remains > 0) { + switch (remains) { + case 1: + a = (unsigned char) p[0]; + b = 0; + c = 0; + count = 1; + break; + case 2: + a = (unsigned char) p[0]; + b = (unsigned char) p[1]; + c = 0; + count = 2; + break; + default: + a = (unsigned char) p[0]; + b = (unsigned char) p[1]; + c = (unsigned char) p[2]; + count = 3; + break; + } + + ogroup[0]= base64_encoding[a >> 2]; + ogroup[1]= base64_encoding[((a & 3) << 4) | (b >> 4)]; + ogroup[2]= base64_encoding[((b & 0xF) << 2) | (c >> 6)]; + ogroup[3]= base64_encoding[c & 0x3F]; + + switch (count) { + case 1: + ogroup[2]= '='; + ogroup[3]= '='; + break; + case 2: + ogroup[3]= '='; + break; + } + + if (* col + 4 > BASE64_MAX_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + } + + r = mailimf_string_write_driver(do_write, data, col, ogroup, 4); + if (r != MAILIMF_NO_ERROR) + return r; + + remains -= count; + p += count; + } + + return mailimf_string_write_driver(do_write, data, col, "\r\n", 2); +} + +#if 0 +#define MAX_WRITE_SIZE 512 +#endif + +enum { + STATE_INIT, + STATE_CR, + STATE_SPACE, + STATE_SPACE_CR +}; + +#if 0 +static inline int write_try_buf(int (* do_write)(void *, const char *, size_t), void * data, int * col, + char ** pstart, size_t * plen) +{ + int r; + + if (* plen >= MAX_WRITE_SIZE) { + r = mailimf_string_write_driver(do_write, data, col, * pstart, * plen); + if (r != MAILIMF_NO_ERROR) + return r; + * plen = 0; + } + + return MAILIMF_NO_ERROR; +} +#endif + +static inline int write_remaining(int (* do_write)(void *, const char *, size_t), void * data, int * col, + const char ** pstart, size_t * plen) +{ + int r; + + if (* plen > 0) { + r = mailimf_string_write_driver(do_write, data, col, * pstart, * plen); + if (r != MAILIMF_NO_ERROR) + return r; + * plen = 0; + } + + return MAILIMF_NO_ERROR; +} + + + +#define QP_MAX_COL 72 + +int mailmime_quoted_printable_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, int istext, + const char * text, size_t size) +{ + size_t i; + const char * start; + size_t len; + char hexstr[6]; + int r; + int state; + + start = text; + len = 0; + state = STATE_INIT; + + i = 0; + while (i < size) { + unsigned char ch; + + if (* col + len > QP_MAX_COL) { + r = write_remaining(do_write, data, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i; + + r = mailimf_string_write_driver(do_write, data, col, "=\r\n", 3); + if (r != MAILIMF_NO_ERROR) + return r; + } + + ch = text[i]; + + switch (state) { + + case STATE_INIT: + switch (ch) { + case ' ': + case '\t': + state = STATE_SPACE; + len ++; + i ++; + break; + + case '\r': + state = STATE_CR; + i ++; + break; + + case '!': + case '"': + case '#': + case '$': + case '@': + case '[': + case '\\': + case ']': + case '^': + case '`': + case '{': + case '|': + case '}': + case '~': + case '=': + case '?': + case '_': + case 'F': /* there is no more 'From' at the beginning of a line */ + r = write_remaining(do_write, data, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + + snprintf(hexstr, 6, "=%02X", ch); + + r = mailimf_string_write_driver(do_write, data, col, hexstr, 3); + if (r != MAILIMF_NO_ERROR) + return r; + i ++; + break; + + default: + if (istext && (ch == '\n')) { + r = write_remaining(do_write, data, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; + i ++; + break; + } + else { + if (((ch >= 33) && (ch <= 60)) || ((ch >= 62) && (ch <= 126))) { + len ++; + i ++; + } + else { + r = write_remaining(do_write, data, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + + snprintf(hexstr, 6, "=%02X", ch); + + r = mailimf_string_write_driver(do_write, data, col, hexstr, 3); + if (r != MAILIMF_NO_ERROR) + return r; + i ++; + } + } + + break; + } + break; + + case STATE_CR: + switch (ch) { + case '\n': + r = write_remaining(do_write, data, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; + i ++; + state = STATE_INIT; + break; + + default: + r = write_remaining(do_write, data, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i; + snprintf(hexstr, 6, "=%02X", '\r'); + r = mailimf_string_write_driver(do_write, data, col, hexstr, 3); + if (r != MAILIMF_NO_ERROR) + return r; + state = STATE_INIT; + break; + } + break; + + case STATE_SPACE: + switch (ch) { + case '\r': + state = STATE_SPACE_CR; + i ++; + break; + + case '\n': + r = write_remaining(do_write, data, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + snprintf(hexstr, 6, "=%02X\r\n", text[i - 1]); + r = mailimf_string_write_driver(do_write, data, col, hexstr, strlen(hexstr)); + if (r != MAILIMF_NO_ERROR) + return r; + state = STATE_INIT; + i ++; + break; + + case ' ': + case '\t': + len ++; + i ++; + break; + + default: +#if 0 + len += 2; + state = STATE_INIT; + i ++; +#endif + state = STATE_INIT; + break; + } + + break; + + case STATE_SPACE_CR: + switch (ch) { + case '\n': + r = write_remaining(do_write, data, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + snprintf(hexstr, 6, "=%02X\r\n", text[i - 2]); + r = mailimf_string_write_driver(do_write, data, col, hexstr, strlen(hexstr)); + if (r != MAILIMF_NO_ERROR) + return r; + state = STATE_INIT; + i ++; + break; + + default: + r = write_remaining(do_write, data, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + snprintf(hexstr, 6, "%c=%02X", text[i - 2], '\r'); + r = mailimf_string_write_driver(do_write, data, col, hexstr, strlen(hexstr)); + if (r != MAILIMF_NO_ERROR) + return r; + state = STATE_INIT; + break; + } + + break; + } + } + + r = write_remaining(do_write, data, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} diff --git a/Sources/libetpan/low-level/mime/mailmime_write_generic.h b/Sources/libetpan/low-level/mime/mailmime_write_generic.h new file mode 100644 index 00000000..ee92b3e4 --- /dev/null +++ b/Sources/libetpan/low-level/mime/mailmime_write_generic.h @@ -0,0 +1,73 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_write_generic.h,v 1.2 2004/11/21 21:53:39 hoa Exp $ + */ + +#ifndef MAILMIME_WRITE_GENERIC_H + +#define MAILMIME_WRITE_GENERIC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +int mailmime_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_fields * fields); + +int mailmime_content_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_content * content); + +int mailmime_content_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_content * content); + +int mailmime_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime * build_info); + +int mailmime_quoted_printable_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, int istext, + const char * text, size_t size); + +int mailmime_base64_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + const char * text, size_t size); + +int mailmime_data_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_data * mime_data, + int istext); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/mime/mailmime_write_mem.c b/Sources/libetpan/low-level/mime/mailmime_write_mem.c new file mode 100644 index 00000000..88a76ed5 --- /dev/null +++ b/Sources/libetpan/low-level/mime/mailmime_write_mem.c @@ -0,0 +1,114 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_write_mem.c,v 1.6 2007/07/12 14:45:54 smarinier Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailmime_write_mem.h" + +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#include +#ifdef HAVE_SYS_MMAN_H +# include +#endif + +#include "mailmime_content.h" +#include "mailmime_types_helper.h" +#include "mailmime_write_generic.h" + +static int do_write(void * data, const char * str, size_t length) +{ + MMAPString * f; + + f = data; + + if (mmap_string_append_len(f, str, length) == NULL) + return 0; + else + return (int) length; +} + +int mailmime_fields_write_mem(MMAPString * f, int * col, + struct mailmime_fields * fields) +{ + return mailmime_fields_write_driver(do_write, f, col, fields); +} + +int mailmime_content_write_mem(MMAPString * f, int * col, + struct mailmime_content * content) +{ + return mailmime_content_write_driver(do_write, f, col, content); +} + +int mailmime_content_type_write_mem(MMAPString * f, int * col, + struct mailmime_content * content) +{ + return mailmime_content_type_write_driver(do_write, f, col, content); +} + +int mailmime_write_mem(MMAPString * f, int * col, + struct mailmime * build_info) +{ + return mailmime_write_driver(do_write, f, col, build_info); +} + +int mailmime_quoted_printable_write_mem(MMAPString * f, int * col, int istext, + const char * text, size_t size) +{ + return mailmime_quoted_printable_write_driver(do_write, f, col, + istext, text, size); +} + +int mailmime_base64_write_mem(MMAPString * f, int * col, + const char * text, size_t size) +{ + return mailmime_base64_write_driver(do_write, f, col, text, size); +} + +int mailmime_data_write_mem(MMAPString * f, int * col, + struct mailmime_data * data, + int istext) +{ + return mailmime_data_write_driver(do_write, f, col, data, istext); +} + diff --git a/Sources/libetpan/low-level/mime/mailmime_write_mem.h b/Sources/libetpan/low-level/mime/mailmime_write_mem.h new file mode 100644 index 00000000..00f1b662 --- /dev/null +++ b/Sources/libetpan/low-level/mime/mailmime_write_mem.h @@ -0,0 +1,80 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_write_mem.h,v 1.3 2006/06/07 12:52:45 smarinier Exp $ + */ + +#ifndef MAILMIME_WRITE_MEM_H + +#define MAILMIME_WRITE_MEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +LIBETPAN_EXPORT +int mailmime_fields_write_mem(MMAPString * f, int * col, + struct mailmime_fields * fields); + +LIBETPAN_EXPORT +int mailmime_content_write_mem(MMAPString * f, int * col, + struct mailmime_content * content); + +LIBETPAN_EXPORT +int mailmime_content_type_write_mem(MMAPString * f, int * col, + struct mailmime_content * content); + +LIBETPAN_EXPORT +int mailmime_write_mem(MMAPString * f, int * col, + struct mailmime * build_info); + +LIBETPAN_EXPORT +int mailmime_quoted_printable_write_mem(MMAPString * f, int * col, int istext, + const char * text, size_t size); + +LIBETPAN_EXPORT +int mailmime_base64_write_mem(MMAPString * f, int * col, + const char * text, size_t size); + +LIBETPAN_EXPORT +int mailmime_data_write_mem(MMAPString * f, int * col, + struct mailmime_data * data, + int istext); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/nntp/Makefile.am b/Sources/libetpan/low-level/nntp/Makefile.am new file mode 100644 index 00000000..a8ecbf1a --- /dev/null +++ b/Sources/libetpan/low-level/nntp/Makefile.am @@ -0,0 +1,41 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +etpaninclude_HEADERS = \ + newsnntp.h newsnntp_socket.h newsnntp_ssl.h newsnntp_types.h + +AM_CPPFLAGS = -I$(top_builddir)/include \ + -I$(top_srcdir)/src/data-types + +noinst_LTLIBRARIES = libnntp.la + +libnntp_la_SOURCES = \ + newsnntp.c newsnntp_socket.c newsnntp_ssl.c diff --git a/Sources/libetpan/low-level/nntp/newsnntp.c b/Sources/libetpan/low-level/nntp/newsnntp.c new file mode 100644 index 00000000..dd47fdc8 --- /dev/null +++ b/Sources/libetpan/low-level/nntp/newsnntp.c @@ -0,0 +1,2574 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: newsnntp.c,v 1.31 2011/03/11 21:49:36 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "newsnntp.h" + + +#include +#ifndef WIN32 +# include +# include +# include +#endif + +#include +#include +#include + +#include "connect.h" +#include "mail.h" +#include "clist.h" + +/* + NNTP Protocol + + RFC 977 + RFC 2980 + + TODO : + + XPAT header range| pat [pat...] + + + */ + + + + +#define NNTP_STRING_SIZE 513 + + +static inline void nntp_logger(mailstream * s, int log_type, + const char * str, size_t size, void * context); + +static char * read_line(newsnntp * f); +static char * read_multiline(newsnntp * f, size_t size, + MMAPString * multiline_buffer); +static int parse_response(newsnntp * f, char * response); + +static int send_command(newsnntp * f, char * command); +static int send_command_private(newsnntp * f, char * command, int can_be_published); + +newsnntp * newsnntp_new(size_t progr_rate, progress_function * progr_fun) +{ + newsnntp * f; + + f = malloc(sizeof(* f)); + if (f == NULL) + goto err; + + f->nntp_stream = NULL; + f->nntp_readonly = FALSE; + + f->nntp_progr_rate = progr_rate; + f->nntp_progr_fun = progr_fun; + + f->nntp_stream_buffer = mmap_string_new(""); + if (f->nntp_stream_buffer == NULL) + goto free_f; + + f->nntp_response_buffer = mmap_string_new(""); + if (f->nntp_response_buffer == NULL) + goto free_stream_buffer; + + f->nntp_timeout = 0; + f->nntp_progress_fun = NULL; + f->nntp_progress_context = NULL; + + f->nntp_logger = NULL; + f->nntp_logger_context = NULL; + + return f; + + free_stream_buffer: + mmap_string_free(f->nntp_stream_buffer); + free_f: + free(f); + err: + return NULL; +} + +void newsnntp_free(newsnntp * f) +{ + if (f->nntp_stream) + newsnntp_quit(f); + + mmap_string_free(f->nntp_response_buffer); + mmap_string_free(f->nntp_stream_buffer); + + free(f); +} + + +void newsnntp_set_timeout(newsnntp * f, time_t timeout) +{ + f->nntp_timeout = timeout; +} + +time_t newsnntp_get_timeout(newsnntp * f) +{ + return f->nntp_timeout; +} + + + + + +int newsnntp_quit(newsnntp * f) +{ + char command[NNTP_STRING_SIZE]; + char * response; + int r; + int res; + + if (f->nntp_stream == NULL) + return NEWSNNTP_ERROR_BAD_STATE; + + snprintf(command, NNTP_STRING_SIZE, "QUIT\r\n"); + r = send_command(f, command); + if (r == -1) { + res = NEWSNNTP_ERROR_STREAM; + goto close; + } + + response = read_line(f); + if (response == NULL) { + res = NEWSNNTP_ERROR_STREAM; + goto close; + } + + parse_response(f, response); + + res = NEWSNNTP_NO_ERROR; + + close: + + mailstream_close(f->nntp_stream); + + f->nntp_stream = NULL; + + return res; +} + +int newsnntp_connect(newsnntp * f, mailstream * s) +{ + char * response; + int r; + + if (f->nntp_stream != NULL) + return NEWSNNTP_ERROR_BAD_STATE; + + f->nntp_stream = s; + mailstream_set_logger(s, nntp_logger, f); + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 200: + f->nntp_readonly = FALSE; + return NEWSNNTP_NO_ERROR; + + case 201: + f->nntp_readonly = TRUE; + return NEWSNNTP_NO_ERROR; + + default: + f->nntp_stream = NULL; + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + + + + + + + + + + + + + + + + + + + + +/* +static struct newsnntp_xover_resp_item * get_xover_info(newsnntp * f, + guint32 article); +*/ + +static void newsnntp_multiline_response_free(char * str) +{ + mmap_string_unref(str); +} + +void newsnntp_head_free(char * str) +{ + newsnntp_multiline_response_free(str); +} + +void newsnntp_article_free(char * str) +{ + newsnntp_multiline_response_free(str); +} + +void newsnntp_body_free(char * str) +{ + newsnntp_multiline_response_free(str); +} + +/* ******************** HEADER ******************************** */ + +/* + message content in (* result) is still there until the + next retrieve or top operation on the mailpop3 structure +*/ + +static int newsnntp_get_content(newsnntp * f, char ** result, + size_t * result_len) +{ + int r; + char * response; + MMAPString * buffer; + char * result_multiline; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 220: + case 221: + case 222: + case 223: + buffer = mmap_string_new(""); + if (buffer == NULL) + return NEWSNNTP_ERROR_MEMORY; + + result_multiline = read_multiline(f, 0, buffer); + if (result_multiline == NULL) { + mmap_string_free(buffer); + return NEWSNNTP_ERROR_MEMORY; + } + else { + r = mmap_string_ref(buffer); + if (r < 0) { + mmap_string_free(buffer); + return NEWSNNTP_ERROR_MEMORY; + } + + * result = result_multiline; + * result_len = buffer->len; + return NEWSNNTP_NO_ERROR; + } + + case 412: + return NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED; + + case 420: + return NEWSNNTP_ERROR_NO_ARTICLE_SELECTED; + + case 423: + return NEWSNNTP_ERROR_INVALID_ARTICLE_NUMBER; + + case 430: + return NEWSNNTP_ERROR_ARTICLE_NOT_FOUND; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +int newsnntp_head(newsnntp * f, uint32_t indx, char ** result, + size_t * result_len) +{ + char command[NNTP_STRING_SIZE]; + int r; + + snprintf(command, NNTP_STRING_SIZE, "HEAD %i\r\n", indx); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + return newsnntp_get_content(f, result, result_len); +} + +/* ******************** ARTICLE ******************************** */ + +int newsnntp_article(newsnntp * f, uint32_t indx, char ** result, + size_t * result_len) +{ + char command[NNTP_STRING_SIZE]; + int r; + + snprintf(command, NNTP_STRING_SIZE, "ARTICLE %i\r\n", indx); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + return newsnntp_get_content(f, result, result_len); +} + +int newsnntp_article_by_message_id(newsnntp * f, char * msg_id, + char ** result, size_t * result_len) +{ + char command[NNTP_STRING_SIZE]; + int r; + + snprintf(command, NNTP_STRING_SIZE, "ARTICLE <%s>\r\n", msg_id); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + return newsnntp_get_content(f, result, result_len); +} + +/* ******************** BODY ******************************** */ + +int newsnntp_body(newsnntp * f, uint32_t indx, char ** result, + size_t * result_len) +{ + char command[NNTP_STRING_SIZE]; + int r; + + snprintf(command, NNTP_STRING_SIZE, "BODY %i\r\n", indx); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + return newsnntp_get_content(f, result, result_len); +} + +/* ******************** GROUP ******************************** */ + +static struct newsnntp_group_info * +group_info_init(char * name, uint32_t first, uint32_t last, uint32_t count, + char type) +{ + struct newsnntp_group_info * n; + + n = malloc(sizeof(* n)); + + if (n == NULL) + return NULL; + + n->grp_name = strdup(name); + if (n->grp_name == NULL) { + free(n); + return NULL; + } + + n->grp_first = first; + n->grp_last = last; + n->grp_count = count; + n->grp_type = type; + + return n; +} + +static void group_info_free(struct newsnntp_group_info * n) +{ + if (n->grp_name) + free(n->grp_name); + free(n); +} + +static void group_info_list_free(clist * l) +{ + clist_foreach(l, (clist_func) group_info_free, NULL); + clist_free(l); +} + +static int parse_group_info(char * response, + struct newsnntp_group_info ** info); + +int newsnntp_group(newsnntp * f, const char * groupname, + struct newsnntp_group_info ** info) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "GROUP %s\r\n", groupname); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 211: + if (!parse_group_info(f->nntp_response, info)) + return NEWSNNTP_ERROR_INVALID_RESPONSE; + return NEWSNNTP_NO_ERROR; + + case 411: + return NEWSNNTP_ERROR_NO_SUCH_NEWS_GROUP; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_group_free(struct newsnntp_group_info * info) +{ + group_info_free(info); +} + +/* ******************** LIST ******************************** */ + +static clist * read_groups_list(newsnntp * f); + +int newsnntp_list(newsnntp * f, clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "LIST\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 215: + * result = read_groups_list(f); + return NEWSNNTP_NO_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_list_free(clist * l) +{ + group_info_list_free(l); +} + +/* ******************** POST ******************************** */ + +static void send_data(newsnntp * f, const char * message, size_t size) +{ + mailstream_send_data(f->nntp_stream, message, size, + f->nntp_progr_rate, f->nntp_progr_fun); +} + + +int newsnntp_post(newsnntp * f, const char * message, size_t size) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "POST\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 340: + break; + + case 440: + return NEWSNNTP_ERROR_POSTING_NOT_ALLOWED; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } + + send_data(f, message, size); + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 240: + return NEWSNNTP_NO_ERROR; + return 1; + + case 441: + return NEWSNNTP_ERROR_POSTING_FAILED; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + + +/* ******************** AUTHINFO ******************************** */ + +int newsnntp_authinfo_username(newsnntp * f, const char * username) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "AUTHINFO USER %s\r\n", username); + r = send_command_private(f, command, 0); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME; + + case 481: + return NEWSNNTP_ERROR_AUTHENTICATION_REJECTED; + + case 482: + return NEWSNNTP_ERROR_AUTHENTICATION_OUT_OF_SEQUENCE; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 281: + return NEWSNNTP_NO_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +int newsnntp_authinfo_password(newsnntp * f, const char * password) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "AUTHINFO PASS %s\r\n", password); + r = send_command_private(f, command, 0); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME; + + case 481: + return NEWSNNTP_ERROR_AUTHENTICATION_REJECTED; + + case 482: + return NEWSNNTP_ERROR_AUTHENTICATION_OUT_OF_SEQUENCE; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 281: + return NEWSNNTP_NO_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +/* ******************** LIST OVERVIEW.FMT ******************************** */ + +static clist * read_headers_list(newsnntp * f); + +static void headers_list_free(clist * l) +{ + clist_foreach(l, (clist_func) free, NULL); + clist_free(l); +} + +int newsnntp_list_overview_fmt(newsnntp * f, clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "LIST OVERVIEW.FMT\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 215: + * result = read_headers_list(f); + return NEWSNNTP_NO_ERROR; + + case 503: + return NEWSNNTP_ERROR_PROGRAM_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_list_overview_fmt_free(clist * l) +{ + headers_list_free(l); +} + + + + + + +/* ******************** LIST ACTIVE ******************************** */ + +int newsnntp_list_active(newsnntp * f, const char * wildcard, clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + if (wildcard != NULL) + snprintf(command, NNTP_STRING_SIZE, "LIST ACTIVE %s\r\n", wildcard); + else + snprintf(command, NNTP_STRING_SIZE, "LIST ACTIVE\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 215: + * result = read_groups_list(f); + return NEWSNNTP_NO_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_list_active_free(clist * l) +{ + group_info_list_free(l); +} + + + + + + +/* ******************** LIST ACTIVE.TIMES ******************************** */ + +static struct newsnntp_group_time * +group_time_new(char * group_name, time_t date, char * email) +{ + struct newsnntp_group_time * n; + + n = malloc(sizeof(* n)); + + if (n == NULL) + return NULL; + + n->grp_name = strdup(group_name); + if (n->grp_name == NULL) { + free(n); + return NULL; + } + + n->grp_email = strdup(email); + if (n->grp_email == NULL) { + free(n->grp_name); + free(n); + return NULL; + } + + n->grp_date = date; + + return n; +} + +static void group_time_free(struct newsnntp_group_time * n) +{ + if (n->grp_name) + free(n->grp_name); + if (n->grp_email) + free(n->grp_email); + free(n); +} + +static void group_time_list_free(clist * l) +{ + clist_foreach(l, (clist_func) group_time_free, NULL); + clist_free(l); +} + + + + + + + +static clist * read_group_time_list(newsnntp * f); + + +int newsnntp_list_active_times(newsnntp * f, clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "LIST ACTIVE.TIMES\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 215: + * result = read_group_time_list(f); + return NEWSNNTP_NO_ERROR; + + case 503: + return NEWSNNTP_ERROR_PROGRAM_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_list_active_times_free(clist * l) +{ + group_time_list_free(l); +} + + + + + + + + +/* ********************** LIST DISTRIBUTION ***************************** */ + +static struct newsnntp_distrib_value_meaning * +distrib_value_meaning_new(char * value, char * meaning) +{ + struct newsnntp_distrib_value_meaning * n; + + n = malloc(sizeof(* n)); + + if (n == NULL) + return NULL; + + n->dst_value = strdup(value); + if (n->dst_value == NULL) { + free(n); + return NULL; + } + + n->dst_meaning = strdup(meaning); + if (n->dst_meaning == NULL) { + free(n->dst_value); + free(n); + return NULL; + } + + return n; +} + + +static void +distrib_value_meaning_free(struct newsnntp_distrib_value_meaning * n) +{ + if (n->dst_value) + free(n->dst_value); + if (n->dst_meaning) + free(n->dst_meaning); + free(n); +} + +static void distrib_value_meaning_list_free(clist * l) +{ + clist_foreach(l, (clist_func) distrib_value_meaning_free, NULL); + clist_free(l); +} + +static clist * read_distrib_value_meaning_list(newsnntp * f); + + +int newsnntp_list_distribution(newsnntp * f, clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "LIST DISTRIBUTIONS\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 215: + * result = read_distrib_value_meaning_list(f); + return NEWSNNTP_NO_ERROR; + + case 503: + return NEWSNNTP_ERROR_PROGRAM_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + + +void newsnntp_list_distribution_free(clist * l) +{ + distrib_value_meaning_list_free(l); +} + + + + + + + + + + + +/* ********************** LIST DISTRIB.PATS ***************************** */ + +static struct newsnntp_distrib_default_value * +distrib_default_value_new(uint32_t weight, char * group_pattern, char * value) +{ + struct newsnntp_distrib_default_value * n; + + n = malloc(sizeof(* n)); + if (n == NULL) + return NULL; + + n->dst_group_pattern = strdup(group_pattern); + if (n->dst_group_pattern == NULL) { + free(n); + return NULL; + } + + n->dst_value = strdup(value); + if (n->dst_value == NULL) { + free(n->dst_group_pattern); + free(n); + return NULL; + } + + n->dst_weight = weight; + + return n; +} + +static void +distrib_default_value_free(struct newsnntp_distrib_default_value * n) +{ + if (n->dst_group_pattern) + free(n->dst_group_pattern); + if (n->dst_value) + free(n->dst_value); + free(n); +} + +static void distrib_default_value_list_free(clist * l) +{ + clist_foreach(l, (clist_func) distrib_default_value_free, NULL); + clist_free(l); +} + +static clist * read_distrib_default_value_list(newsnntp * f); + +int newsnntp_list_distrib_pats(newsnntp * f, clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "LIST DISTRIB.PATS\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 215: + * result = read_distrib_default_value_list(f); + return NEWSNNTP_NO_ERROR; + + case 503: + return NEWSNNTP_ERROR_PROGRAM_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_list_distrib_pats_free(clist * l) +{ + distrib_default_value_list_free(l); +} + + + + + + + + + + + + +/* ********************** LIST NEWSGROUPS ***************************** */ + +static struct newsnntp_group_description * +group_description_new(char * group_name, char * description) +{ + struct newsnntp_group_description * n; + + n = malloc(sizeof(* n)); + if (n == NULL) + return NULL; + + n->grp_name = strdup(group_name); + if (n->grp_name == NULL) { + free(n); + return NULL; + } + + n->grp_description = strdup(description); + if (n->grp_description == NULL) { + free(n->grp_name); + free(n); + return NULL; + } + + return n; +} + +static void group_description_free(struct newsnntp_group_description * n) +{ + if (n->grp_name) + free(n->grp_name); + if (n->grp_description) + free(n->grp_description); + free(n); +} + +static void group_description_list_free(clist * l) +{ + clist_foreach(l, (clist_func) group_description_free, NULL); + clist_free(l); +} + +static clist * read_group_description_list(newsnntp * f); + +int newsnntp_list_newsgroups(newsnntp * f, const char * pattern, + clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + if (pattern) + snprintf(command, NNTP_STRING_SIZE, "LIST NEWSGROUPS %s\r\n", pattern); + else + snprintf(command, NNTP_STRING_SIZE, "LIST NEWSGROUPS\r\n"); + + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 215: + * result = read_group_description_list(f); + return NEWSNNTP_NO_ERROR; + + case 503: + return NEWSNNTP_ERROR_PROGRAM_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_list_newsgroups_free(clist * l) +{ + group_description_list_free(l); +} + + + + + + + + + + + + +/* ******************** LIST SUBSCRIPTIONS ******************************** */ + +static void subscriptions_list_free(clist * l) +{ + clist_foreach(l, (clist_func) free, NULL); + clist_free(l); +} + +static clist * read_subscriptions_list(newsnntp * f); + +int newsnntp_list_subscriptions(newsnntp * f, clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "LIST SUBSCRIPTIONS\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 215: + * result = read_subscriptions_list(f); + return NEWSNNTP_NO_ERROR; + + case 503: + return NEWSNNTP_ERROR_PROGRAM_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_list_subscriptions_free(clist * l) +{ + subscriptions_list_free(l); +} + + + + + + + + + + + + +/* ******************** LISTGROUP ******************************** */ + +static void articles_list_free(clist * l) +{ + clist_foreach(l, (clist_func) free, NULL); + clist_free(l); +} + +static clist * read_articles_list(newsnntp * f); + +int newsnntp_listgroup(newsnntp * f, const char * group_name, + clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + if (group_name) + snprintf(command, NNTP_STRING_SIZE, "LISTGROUP %s\r\n", group_name); + else + snprintf(command, NNTP_STRING_SIZE, "LISTGROUP\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 211: + * result = read_articles_list(f); + return NEWSNNTP_NO_ERROR; + + case 412: + return NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED; + + case 502: + return NEWSNNTP_ERROR_NO_PERMISSION; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_listgroup_free(clist * l) +{ + articles_list_free(l); +} + + + + + + + +/* ********************** MODE READER ***************************** */ + +int newsnntp_mode_reader(newsnntp * f) +{ + char command[NNTP_STRING_SIZE]; + char * response; + int r; + + snprintf(command, NNTP_STRING_SIZE, "MODE READER\r\n"); + + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + switch (r) { + case 480: + return NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 200: + case 201: + return NEWSNNTP_NO_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +/* ********************** DATE ***************************** */ + +#define strfcpy(a,b,c) {if (c) {strncpy(a,b,c);a[c-1]=0;}} + +int newsnntp_date(newsnntp * f, struct tm * tm) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + char year[5]; + char month[3]; + char day[3]; + char hour[3]; + char minute[3]; + char second[3]; + + snprintf(command, NNTP_STRING_SIZE, "DATE\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + if (f->nntp_response == NULL) { + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } + + switch (r) { + case 111: + strfcpy(year, f->nntp_response, 4); + strfcpy(month, f->nntp_response + 4, 2); + strfcpy(day, f->nntp_response + 6, 2); + strfcpy(hour, f->nntp_response + 8, 2); + strfcpy(minute, f->nntp_response + 10, 2); + strfcpy(second, f->nntp_response + 12, 2); + + tm->tm_year = atoi(year); + tm->tm_mon = atoi(month); + tm->tm_mday = atoi(day); + tm->tm_hour = atoi(hour); + tm->tm_min = atoi(minute); + tm->tm_sec = atoi(second); + + return NEWSNNTP_NO_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + + + + + + + + + +/* ********************** XHDR ***************************** */ + +static struct newsnntp_xhdr_resp_item * xhdr_resp_item_new(uint32_t article, + char * value) +{ + struct newsnntp_xhdr_resp_item * n; + + n = malloc(sizeof(* n)); + if (n == NULL) + return NULL; + + n->hdr_value = strdup(value); + if (n->hdr_value == NULL) { + free(n); + return NULL; + } + + n->hdr_article = article; + + return n; +} + +static void xhdr_resp_item_free(struct newsnntp_xhdr_resp_item * n) +{ + if (n->hdr_value) + free(n->hdr_value); + free(n); +} + +static void xhdr_resp_list_free(clist * l) +{ + clist_foreach(l, (clist_func) xhdr_resp_item_free, NULL); + clist_free(l); +} + +static clist * read_xhdr_resp_list(newsnntp * f); + +static int newsnntp_xhdr_resp(newsnntp * f, clist ** result); + +int newsnntp_xhdr_single(newsnntp * f, const char * header, uint32_t article, + clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + + snprintf(command, NNTP_STRING_SIZE, "XHDR %s %i\r\n", header, article); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + return newsnntp_xhdr_resp(f, result); +} + +int newsnntp_xhdr_range(newsnntp * f, const char * header, + uint32_t rangeinf, uint32_t rangesup, + clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + + snprintf(command, NNTP_STRING_SIZE, "XHDR %s %i-%i\r\n", header, + rangeinf, rangesup); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + return newsnntp_xhdr_resp(f, result); +} + +void newsnntp_xhdr_free(clist * l) +{ + xhdr_resp_list_free(l); +} + +static int newsnntp_xhdr_resp(newsnntp * f, clist ** result) +{ + int r; + char * response; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 221: + * result = read_xhdr_resp_list(f); + return NEWSNNTP_NO_ERROR; + + case 412: + return NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED; + + case 420: + return NEWSNNTP_ERROR_NO_ARTICLE_SELECTED; + + case 430: + return NEWSNNTP_ERROR_ARTICLE_NOT_FOUND; + + case 502: + return NEWSNNTP_ERROR_NO_PERMISSION; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + + + + + + + + + + + + + + +/* ********************** XOVER ***************************** */ + +static struct newsnntp_xover_resp_item * +xover_resp_item_new(uint32_t article, + char * subject, + char * author, + char * date, + char * message_id, + char * references, + size_t size, + uint32_t line_count, + clist * others) +{ + struct newsnntp_xover_resp_item * n; + + n = malloc(sizeof(* n)); + if (n == NULL) + return NULL; + + n->ovr_subject = strdup(subject); + if (n->ovr_subject == NULL) { + free(n); + return NULL; + } + + n->ovr_author = strdup(author); + if (n->ovr_author == NULL) { + free(n->ovr_subject); + free(n); + return NULL; + } + + n->ovr_date = strdup(date); + if (n->ovr_date == NULL) { + free(n->ovr_subject); + free(n->ovr_author); + free(n); + return NULL; + } + + n->ovr_message_id = strdup(message_id); + if (n->ovr_message_id == NULL) { + free(n->ovr_subject); + free(n->ovr_author); + free(n->ovr_date); + free(n); + return NULL; + } + + n->ovr_references = strdup(references); + if (n->ovr_references == NULL) { + free(n->ovr_subject); + free(n->ovr_author); + free(n->ovr_date); + free(n->ovr_message_id); + free(n); + return NULL; + } + + n->ovr_article = article; + n->ovr_size = size; + n->ovr_line_count = line_count; + n->ovr_others = others; + + return n; +} + +void xover_resp_item_free(struct newsnntp_xover_resp_item * n) +{ + if (n->ovr_subject) + free(n->ovr_subject); + if (n->ovr_author) + free(n->ovr_author); + if (n->ovr_date) + free(n->ovr_date); + if (n->ovr_message_id) + free(n->ovr_message_id); + if (n->ovr_references) + free(n->ovr_references); + clist_foreach(n->ovr_others, (clist_func) free, NULL); + clist_free(n->ovr_others); + + free(n); +} + +void newsnntp_xover_resp_list_free(clist * l) +{ + clist_foreach(l, (clist_func) xover_resp_item_free, NULL); + clist_free(l); +} + +static clist * read_xover_resp_list(newsnntp * f); + + +static int newsnntp_xover_resp(newsnntp * f, clist ** result); + +int newsnntp_xover_single(newsnntp * f, uint32_t article, + struct newsnntp_xover_resp_item ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + clist * list; + clistiter * cur; + struct newsnntp_xover_resp_item * item; + + snprintf(command, NNTP_STRING_SIZE, "XOVER %i\r\n", article); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + r = newsnntp_xover_resp(f, &list); + if (r != NEWSNNTP_NO_ERROR) + return r; + + cur = clist_begin(list); + item = clist_content(cur); + clist_free(list); + + * result = item; + + return r; +} + +int newsnntp_xover_range(newsnntp * f, uint32_t rangeinf, uint32_t rangesup, + clist ** result) +{ + int r; + char command[NNTP_STRING_SIZE]; + + snprintf(command, NNTP_STRING_SIZE, "XOVER %i-%i\r\n", rangeinf, rangesup); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + return newsnntp_xover_resp(f, result); +} + +static int newsnntp_xover_resp(newsnntp * f, clist ** result) +{ + int r; + char * response; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 224: + * result = read_xover_resp_list(f); + return NEWSNNTP_NO_ERROR; + + case 412: + return NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED; + + case 420: + return NEWSNNTP_ERROR_NO_ARTICLE_SELECTED; + + case 502: + return NEWSNNTP_ERROR_NO_PERMISSION; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + + + + + + + +/* ********************** AUTHINFO GENERIC ***************************** */ + +int newsnntp_authinfo_generic(newsnntp * f, const char * authentificator, + const char * arguments) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "AUTHINFO GENERIC %s %s\r\n", + authentificator, arguments); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 281: + return NEWSNNTP_NO_ERROR; + + case 500: + return NEWSNNTP_ERROR_COMMAND_NOT_UNDERSTOOD; + + case 501: + return NEWSNNTP_ERROR_COMMAND_NOT_SUPPORTED; + + case 502: + return NEWSNNTP_ERROR_NO_PERMISSION; + + case 503: + return NEWSNNTP_ERROR_PROGRAM_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + + + + + + + + + + + + + + + + + + + +static int parse_space(char ** line) +{ + char * p; + + p = * line; + + while ((* p == ' ') || (* p == '\t')) + p ++; + + if (p != * line) { + * line = p; + return TRUE; + } + else + return FALSE; +} + +static char * cut_token(char * line) +{ + char * p; + char * p_tab; + char * p_space; + + p = line; + + p_space = strchr(line, ' '); + p_tab = strchr(line, '\t'); + if (p_tab == NULL) + p = p_space; + else if (p_space == NULL) + p = p_tab; + else { + if (p_tab < p_space) + p = p_tab; + else + p = p_space; + } + if (p == NULL) + return NULL; + * p = 0; + p ++; + + return p; +} + +static int parse_response(newsnntp * f, char * response) +{ + int code; + + code = (int) strtol(response, &response, 10); + + if (response == NULL) { + f->nntp_response = NULL; + return code; + } + + parse_space(&response); + + if (mmap_string_assign(f->nntp_response_buffer, response) != NULL) + f->nntp_response = f->nntp_response_buffer->str; + else + f->nntp_response = NULL; + + return code; +} + + +static char * read_line(newsnntp * f) +{ + return mailstream_read_line_remove_eol(f->nntp_stream, f->nntp_stream_buffer); +} + +static char * read_multiline(newsnntp * f, size_t size, + MMAPString * multiline_buffer) +{ + return mailstream_read_multiline(f->nntp_stream, size, + f->nntp_stream_buffer, multiline_buffer, + f->nntp_progr_rate, f->nntp_progr_fun, f->nntp_progress_fun, f->nntp_progress_context); +} + + + + + + + +static int parse_group_info(char * response, + struct newsnntp_group_info ** result) +{ + char * line; + uint32_t first; + uint32_t last; + uint32_t count; + char * name; + struct newsnntp_group_info * info; + + line = response; + + count = (uint32_t) strtoul(line, &line, 10); + if (!parse_space(&line)) + return FALSE; + + first = (uint32_t) strtoul(line, &line, 10); + if (!parse_space(&line)) + return FALSE; + + last = (uint32_t) strtoul(line, &line, 10); + if (!parse_space(&line)) + return FALSE; + + name = line; + + info = group_info_init(name, first, last, count, FALSE); + if (info == NULL) + return FALSE; + + * result = info; + + return TRUE; +} + + +static clist * read_groups_list(newsnntp * f) +{ + char * line; + char * group_name; + uint32_t first; + uint32_t last; + uint32_t count; + int type; + clist * groups_list; + struct newsnntp_group_info * n; + int r; + + groups_list = clist_new(); + if (groups_list == NULL) + goto err; + + while (1) { + char * p; + + line = read_line(f); + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + p = cut_token(line); + if (p == NULL) + continue; + + group_name = line; + line = p; + + last = (uint32_t)strtol(line, &line, 10); + if (!parse_space(&line)) + continue; + + first = (uint32_t)strtol(line, &line, 10); + if (!parse_space(&line)) + continue; + + count = last - first + 1; + + type = * line; + + n = group_info_init(group_name, first, last, count, type); + if (n == NULL) + goto free_list; + + r = clist_append(groups_list, n); + if (r < 0) { + group_info_free(n); + goto free_list; + } + } + + return groups_list; + + free_list: + group_info_list_free(groups_list); + err: + return NULL; +} + + +static clist * read_headers_list(newsnntp * f) +{ + char * line; + clist * headers_list; + char * header; + int r; + + headers_list = clist_new(); + if (headers_list == NULL) + goto err; + + while (1) { + line = read_line(f); + + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + header = strdup(line); + if (header == NULL) + goto free_list; + + r = clist_append(headers_list, header); + if (r < 0) { + free(header); + goto free_list; + } + } + + return headers_list; + + free_list: + headers_list_free(headers_list); + err: + return NULL; +} + + + + +static clist * read_group_time_list(newsnntp * f) +{ + char * line; + char * group_name; + time_t date; + char * email; + clist * group_time_list; + struct newsnntp_group_time * n; + int r; + + group_time_list = clist_new(); + if (group_time_list == NULL) + goto err; + + while (1) { + char * p; + char * remaining; + + line = read_line(f); + + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + p = cut_token(line); + if (p == NULL) + continue; + + date = strtoul(p, &remaining, 10); + + p = remaining; + parse_space(&p); + + email = p; + + group_name = line; + + n = group_time_new(group_name, date, email); + if (n == NULL) + goto free_list; + + r = clist_append(group_time_list, n); + if (r < 0) { + group_time_free(n); + goto free_list; + } + } + + return group_time_list; + + free_list: + group_time_list_free(group_time_list); + err: + return NULL; +} + + + + +static clist * read_distrib_value_meaning_list(newsnntp * f) +{ + char * line; + char * value; + char * meaning; + clist * distrib_value_meaning_list; + struct newsnntp_distrib_value_meaning * n; + int r; + + distrib_value_meaning_list = clist_new(); + if (distrib_value_meaning_list == NULL) + goto err; + + while (1) { + char * p; + + line = read_line(f); + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + p = cut_token(line); + if (p == NULL) + continue; + + meaning = p; + + value = line; + + n = distrib_value_meaning_new(value, meaning); + if (n == NULL) + goto free_list; + + r = clist_append(distrib_value_meaning_list, n); + if (r < 0) { + distrib_value_meaning_free(n); + goto free_list; + } + } + + return distrib_value_meaning_list; + + free_list: + distrib_value_meaning_list_free(distrib_value_meaning_list); + err: + return NULL; +} + + + + +static clist * read_distrib_default_value_list(newsnntp * f) +{ + char * line; + uint32_t weight; + char * group_pattern; + char * meaning; + clist * distrib_default_value_list; + struct newsnntp_distrib_default_value * n; + int r; + + distrib_default_value_list = clist_new(); + if (distrib_default_value_list == NULL) + goto err; + + while (1) { + char * p; + char * remaining; + + line = read_line(f); + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + p = line; + + weight = (uint32_t)strtoul(p, &remaining, 10); + p = remaining; + parse_space(&p); + + p = cut_token(line); + if (p == NULL) + continue; + + meaning = p; + group_pattern = line; + + n = distrib_default_value_new(weight, group_pattern, meaning); + if (n == NULL) + goto free_list; + + r = clist_append(distrib_default_value_list, n); + if (r < 0) { + distrib_default_value_free(n); + goto free_list; + } + } + + return distrib_default_value_list; + + free_list: + distrib_default_value_list_free(distrib_default_value_list); + err: + return NULL; +} + + + +static clist * read_group_description_list(newsnntp * f) +{ + char * line; + char * group_name; + char * description; + clist * group_description_list; + struct newsnntp_group_description * n; + int r; + + group_description_list = clist_new(); + if (group_description_list == NULL) + goto err; + + while (1) { + char * p; + + line = read_line(f); + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + p = cut_token(line); + if (p == NULL) + continue; + + description = p; + + group_name = line; + + n = group_description_new(group_name, description); + if (n == NULL) + goto free_list; + + r = clist_append(group_description_list, n); + if (r < 0) { + group_description_free(n); + goto free_list; + } + } + + return group_description_list; + + free_list: + group_description_list_free(group_description_list); + err: + return NULL; +} + + + +static clist * read_subscriptions_list(newsnntp * f) +{ + char * line; + clist * subscriptions_list; + char * group_name; + int r; + + subscriptions_list = clist_new(); + if (subscriptions_list == NULL) + goto err; + + while (1) { + line = read_line(f); + + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + group_name = strdup(line); + if (group_name == NULL) + goto free_list; + + r = clist_append(subscriptions_list, group_name); + if (r < 0) { + free(group_name); + goto free_list; + } + } + + return subscriptions_list; + + free_list: + subscriptions_list_free(subscriptions_list); + err: + return NULL; +} + + + +static clist * read_articles_list(newsnntp * f) +{ + char * line; + clist * articles_list; + uint32_t * article_num; + int r; + + articles_list = clist_new(); + if (articles_list == NULL) + goto err; + + while (1) { + line = read_line(f); + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + article_num = malloc(sizeof(* article_num)); + if (article_num == NULL) + goto free_list; + * article_num = atoi(line); + + r = clist_append(articles_list, article_num); + if (r < 0) { + free(article_num); + goto free_list; + } + } + + return articles_list; + + free_list: + articles_list_free(articles_list); + err: + return NULL; +} + +static clist * read_xhdr_resp_list(newsnntp * f) +{ + char * line; + uint32_t article; + char * value; + clist * xhdr_resp_list; + struct newsnntp_xhdr_resp_item * n; + int r; + + xhdr_resp_list = clist_new(); + if (xhdr_resp_list == NULL) + goto err; + + while (1) { + line = read_line(f); + + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + article = (uint32_t) strtoul(line, &line, 10); + if (!parse_space(&line)) + continue; + + value = line; + + n = xhdr_resp_item_new(article, value); + if (n == NULL) + goto free_list; + + r = clist_append(xhdr_resp_list, n); + if (r < 0) { + xhdr_resp_item_free(n); + goto free_list; + } + } + + return xhdr_resp_list; + + free_list: + xhdr_resp_list_free(xhdr_resp_list); + err: + return NULL; +} + + +static clist * read_xover_resp_list(newsnntp * f) +{ + char * line; + clist * xover_resp_list; + struct newsnntp_xover_resp_item * n; + clist * values_list; + clistiter * current; + uint32_t article; + char * subject; + char * author; + char * date; + char * message_id; + char * references; + size_t size; + uint32_t line_count; + clist * others; + int r; + + xover_resp_list = clist_new(); + if (xover_resp_list == NULL) + goto err; + + while (1) { + char * p; + + line = read_line(f); + + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + /* parse the data separated with \t */ + + values_list = clist_new(); + if (values_list == NULL) + goto free_list; + + while ((p = strchr(line, '\t')) != NULL) { + * p = 0; + p ++; + + r = clist_append(values_list, line); + if (r < 0) + goto free_values_list; + line = p; + } + + r = clist_append(values_list, line); + if (r < 0) + goto free_values_list; + + /* set the known data */ + current = clist_begin(values_list); + if (current == NULL) { + clist_free(values_list); + continue; + } + article = 0; + if (clist_content(current) != NULL) { + article = atoi((char *) clist_content(current)); + } + + current = clist_next(current); + if (current == NULL) { + clist_free(values_list); + continue; + } + subject = clist_content(current); + + current = clist_next(current); + if (current == NULL) { + clist_free(values_list); + continue; + } + author = clist_content(current); + + current = clist_next(current); + if (current == NULL) { + clist_free(values_list); + continue; + } + date = clist_content(current); + + current = clist_next(current); + if (current == NULL) { + clist_free(values_list); + continue; + } + message_id = clist_content(current); + + current = clist_next(current); + if (current == NULL) { + clist_free(values_list); + continue; + } + references = clist_content(current); + + current = clist_next(current); + if (current == NULL) { + clist_free(values_list); + continue; + } + size = 0; + if (clist_content(current) != NULL) { + size = atoi((char *) clist_content(current)); + } + + current = clist_next(current); + if (current == NULL) { + clist_free(values_list); + continue; + } + line_count = 0; + if (clist_content(current) != NULL) { + line_count = atoi((char *) clist_content(current)); + } + + current = clist_next(current); + + /* make a copy of the other data */ + others = clist_new(); + if (others == NULL) { + goto free_values_list; + } + + while (current) { + char * val; + char * original_val; + + original_val = clist_content(current); + val = strdup(original_val); + if (val == NULL) { + clist_foreach(others, (clist_func) free, NULL); + clist_free(others); + goto free_list; + } + + r = clist_append(others, val); + if (r < 0) { + goto free_list; + } + + current = clist_next(current); + } + + clist_free(values_list); + + n = xover_resp_item_new(article, subject, author, date, message_id, + references, size, line_count, others); + if (n == NULL) { + clist_foreach(others, (clist_func) free, NULL); + clist_free(others); + goto free_list; + } + + r = clist_append(xover_resp_list, n); + if (r < 0) { + xover_resp_item_free(n); + goto free_list; + } + } + + return xover_resp_list; + + free_list: + newsnntp_xover_resp_list_free(xover_resp_list); + err: + return NULL; + + free_values_list: + clist_foreach(values_list, (clist_func) free, NULL); + clist_free(values_list); + return NULL; +} + +static int send_command(newsnntp * f, char * command) +{ + return send_command_private(f, command, 1); +} + +static int send_command_private(newsnntp * f, char * command, int can_be_published) +{ + ssize_t r; + + mailstream_set_privacy(f->nntp_stream, can_be_published); + r = mailstream_write(f->nntp_stream, command, strlen(command)); + if (r == -1) + return -1; + + r = mailstream_flush(f->nntp_stream); + if (r == -1) + return -1; + + return 0; +} + +static inline void nntp_logger(mailstream * s, int log_type, + const char * str, size_t size, void * context) +{ + newsnntp * session; + + session = context; + if (session->nntp_logger == NULL) + return; + + session->nntp_logger(session, log_type, str, size, session->nntp_logger_context); +} + +void newsnntp_set_logger(newsnntp * session, void (* logger)(newsnntp * session, int log_type, + const char * str, size_t size, void * context), void * logger_context) +{ + session->nntp_logger = logger; + session->nntp_logger_context = logger_context; +} + +void newsnntp_set_progress_callback(newsnntp * f, mailprogress_function * progr_fun, void * context) +{ + f->nntp_progress_fun = progr_fun; + f->nntp_progress_context = context; +} diff --git a/Sources/libetpan/low-level/nntp/newsnntp.h b/Sources/libetpan/low-level/nntp/newsnntp.h new file mode 100644 index 00000000..b52e3e9a --- /dev/null +++ b/Sources/libetpan/low-level/nntp/newsnntp.h @@ -0,0 +1,695 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: newsnntp.h,v 1.21 2008/02/20 22:15:53 hoa Exp $ + */ + +#ifndef NEWSNNTP_H + +#define NEWSNNTP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_INTTYPES_H +# include +#endif +#include +#include + +#include +#include +#include +#include +#include + +/* + newsnntp_new() + + This function returns a new NNTP session. + + @param progr_rate When downloading messages, a function will be called + each time the amount of bytes downloaded reaches a multiple of this + value, this can be 0. + @param progr_fun This is the function to call to notify the progress, + this can be NULL. + + @return an NNTP session is returned. +*/ + +LIBETPAN_EXPORT +newsnntp * newsnntp_new(size_t nntp_progr_rate, + progress_function * nntp_progr_fun); + +/* + newsnntp_free() + + This function will free the data structures associated with + the NNTP session. + + @param session NNTP session +*/ + +LIBETPAN_EXPORT +void newsnntp_free(newsnntp * session); + +/* + newsnntp_set_logger() set a logger for the connection. + + @param session NNTP session + @param logger logger function. See mailstream_types.h to know possible log_type values. + str is the log, data received or data sent. + @param logger_context parameter that is passed to the logger function. + @return the value of the timeout in seconds. +*/ + +LIBETPAN_EXPORT +void newsnntp_set_logger(newsnntp * session, void (* logger)(newsnntp * session, int log_type, + const char * str, size_t size, void * context), void * logger_context); + +/* + newsnntp_set_progress_callback() set NNTP progression callbacks. + + @param session NNTP session + @param progr_fun callback function. +*/ + +LIBETPAN_EXPORT +void newsnntp_set_progress_callback(newsnntp * f, mailprogress_function * progr_fun, void * context); + +/* + newsnntp_set_timeout() set the network timeout of the NNTP session. + + @param session NNTP session + @param timeout value of the timeout in seconds. +*/ + +LIBETPAN_EXPORT +void newsnntp_set_timeout(newsnntp * session, time_t timeout); + +/* + newsnntp_get_timeout() get the network timeout of the NNTP session. + + @param session NNTP session + + @return value of the timeout in seconds. +*/ + +LIBETPAN_EXPORT +time_t newsnntp_get_timeout(newsnntp * session); + +/* + newsnntp_connect() + + This function will connect the NNTP session with the given stream. + + @param session the NNTP session + @param s stream to use + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_connect(newsnntp * session, mailstream * s); + +/* + newsnntp_quit() disconnect the NNTP session. + + @param session NNTP session + */ + +LIBETPAN_EXPORT +int newsnntp_quit(newsnntp * session); + +/* + newsnntp_head() fetch the headers of an article. + + @param session NNTP session + @param indx index of the article to fetch. + @param result the header data. + @param result_len the length of the result data. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_head(newsnntp * session, uint32_t indx, + char ** result, size_t * result_len); + +/* + newsnntp_head_free() + + This function will free the data associated with an NNTP + article header. + + @param str header data. +*/ + +LIBETPAN_EXPORT +void newsnntp_head_free(char * str); + +/* + newsnntp_article() fetch the header and contents of an article. + + @param session NNTP session + @param indx index of the article to fetch. + @param result the article data. + @param result_len the length of the result data. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_article(newsnntp * session, uint32_t indx, + char ** result, size_t * result_len); + +/* + newsnntp_article_by_message_id() fetch the header and contents + of an article by message id. + + @param session NNTP session + @param msg_id ID of the article to fetch. + @param result The article data. + @param result_len The length of the result data. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_article_by_message_id(newsnntp * session, char * msg_id, + char ** result, size_t * result_len); + +/* + newsnntp_article_free() + + This function will free the data associated with an NNTP + article. + + @param str article data. +*/ + +LIBETPAN_EXPORT +void newsnntp_article_free(char * str); + +/* + newsnntp_body() fetch the contents of an article. + + @param session NNTP session + @param indx index of the article to fetch. + @param result body data. + @param result_len length of the result data. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_body(newsnntp * session, uint32_t indx, + char ** result, size_t * result_len); + +/* + newsnntp_body_free() + + This function will free the data associated with an NNTP + article body. + + @param str article body data. +*/ + +LIBETPAN_EXPORT +void newsnntp_body_free(char * str); + +/* + newsnntp_mode_reader() switch the mode of the server to + reader mode. + + @param session NNTP session + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_mode_reader(newsnntp * session); + +/* + newsnntp_date() fetches the current Coordinated Universal + Time from the server's perspective. + + @param session NNTP session + @param tm server's current time. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_date(newsnntp * session, struct tm * tm); + +/* + newsnntp_authinfo_username() sets the session's username. + + @param session NNTP session + @param username username. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_authinfo_username(newsnntp * session, const char * username); + +/* + newsnntp_authinfo_password() sets the session's password. + + @param session NNTP session + @param username password. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_authinfo_password(newsnntp * session, const char * password); + +/* + newsnntp_post() posts a message to a newsgroup. + + @param session NNTP session + @param message the message data. + @param size the size of the message. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_post(newsnntp * session, const char * message, size_t size); + + + +/******************* requests ******************************/ + +/* + newsnntp_group() select a newsgroup and fetch info about it. + + @param session NNTP session + @param groupname name of the newsgroup. + @param info information about the group. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_group(newsnntp * session, const char * groupname, + struct newsnntp_group_info ** info); + +/* + newsnntp_group_free() + + This function will free the data associated with NNTP group + data. + + @param info group info. +*/ + +LIBETPAN_EXPORT +void newsnntp_group_free(struct newsnntp_group_info * info); + +/* + newsnntp_list() select a newsgroup and fetch info about it. + + @param session NNTP session + @param result list of struct newsnntp_group_info *. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_list(newsnntp * session, clist ** result); + +/* + newsnntp_list_free() + + This function will free the data associated with a list + of newsnntp_group_info *. + + @param l the list of group info. +*/ + +LIBETPAN_EXPORT +void newsnntp_list_free(clist * l); + +/* + newsnntp_list_overview_fmt() fetch the server's format + overview. + + @param session NNTP session + @param result string describing the server's format + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_list_overview_fmt(newsnntp * session, clist ** result); + +/* + newsnntp_list_overview_fmt_free() + + This function will free the data associated with a list + obtained from newsnntp_list_overview_fmt() + + @param l the list of format data. +*/ + +LIBETPAN_EXPORT +void newsnntp_list_overview_fmt_free(clist * l); + +/* + newsnntp_list_active() fetch groups matching a wildmat string. + + @param session NNTP session + @param wildmat an optional wildmat pattern string + @param result a list of struct newsnntp_group_info * + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_list_active(newsnntp * session, const char * wildmat, clist ** result); + +/* + newsnntp_list_active_free() + + This function will free the data associated with a list + obtained from newsnntp_list_active() + + @param l the list of group data. +*/ + +LIBETPAN_EXPORT +void newsnntp_list_active_free(clist * l); + +/* + newsnntp_list_active_times() fetches when the selected newsgroup + was created. + + @param session NNTP session + @param result a list of struct newsnntp_group_time * + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_list_active_times(newsnntp * session, clist ** result); + +/* + newsnntp_list_active_times_free() + + This function will free the data associated with a list + obtained from newsnntp_list_active_times() + + @param l the list of group time data. +*/ + +LIBETPAN_EXPORT +void newsnntp_list_active_times_free(clist * l); + +/* + newsnntp_list_distribution() fetches a list of descriptions of + distributions known to the server. + + @param session NNTP session + @param result a list of struct newsnntp_distrib_value_meaning * + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_list_distribution(newsnntp * session, clist ** result); + +/* + newsnntp_list_distribution_free() + + This function will free the data associated with a list + obtained from newsnntp_list_distribution() + + @param l the list of distribution data. +*/ + +LIBETPAN_EXPORT +void newsnntp_list_distribution_free(clist * l); + +/* + newsnntp_list_distrib_pats() fetches a list of canonical + distribution values. Good for figuring out what to put in the + Distribution header of an article being posted. + + @param session NNTP session + @param result a list of struct newsnntp_distrib_default_value * + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_list_distrib_pats(newsnntp * session, clist ** result); + +/* + newsnntp_list_distribution_free() + + This function will free the data associated with a list + obtained from newsnntp_list_distrib_pats() + + @param l the list of distribution data. +*/ + +LIBETPAN_EXPORT +void newsnntp_list_distrib_pats_free(clist * l); + +/* + newsnntp_list_newsgroups() fetches a list of newsgroups and + their descriptions. + + @param session NNTP session + @param pattern an optional wildmat pattern + @param result a list of struct newsnntp_group_description * + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_list_newsgroups(newsnntp * session, const char * pattern, + clist ** result); + +/* + newsnntp_list_newsgroups_free() + + This function will free the data associated with a list + obtained from newsnntp_list_newsgroups() + + @param l the list of newsgroup data. +*/ + +LIBETPAN_EXPORT +void newsnntp_list_newsgroups_free(clist * l); + +/* + newsnntp_list_subscriptions() fetches a default list of + subscriptions for new users of the server. + + @param session NNTP session + @param result a list of newsgroup name strings + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_list_subscriptions(newsnntp * session, clist ** result); + +/* + newsnntp_list_subscriptions_free() + + This function will free the data associated with a list of + subscriptions. + + @param l the list of newsgroup data. +*/ + +LIBETPAN_EXPORT +void newsnntp_list_subscriptions_free(clist * l); + +/* + newsnntp_listgroup() fetches a list of all article numbers + for a particular group. + + @param session NNTP session + @param group_name the group name + @param result a list of uint32_t article numbers + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_listgroup(newsnntp * session, const char * group_name, + clist ** result); + +/* + newsnntp_listgroup_free() + + This function will free the data associated with a list of + subscriptions. + + @param l the list of article numbers. +*/ + +LIBETPAN_EXPORT +void newsnntp_listgroup_free(clist * l); + +/* + newsnntp_xhdr_single() retrieves specific header fields from a + specific article. + + @param session NNTP session + @param header the field name + @param result a list of struct newsnntp_xhdr_resp_item *. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_xhdr_single(newsnntp * session, const char * header, uint32_t article, + clist ** result); + +/* + newsnntp_xhdr_range() retrieves specific header fields from + a range of specific articles. + + @param session NNTP session + @param header the field name + @param rangeinf the lower bound of the range + @param rangesup the upper bound of the range + @param result a list of struct newsnntp_xhdr_resp_item *. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_xhdr_range(newsnntp * session, const char * header, + uint32_t rangeinf, uint32_t rangesup, + clist ** result); + +/* + newsnntp_xhdr_free() + + This function will free the data associated with a list of + struct newsnntp_xhdr_resp_item *. + + @param l the list of article header responses. +*/ + +LIBETPAN_EXPORT +void newsnntp_xhdr_free(clist * l); + +/* + newsnntp_xover_single() retrieves overview data for a specific + article. + + @param session NNTP session + @param header the field name + @param result a list of struct newsnntp_xhdr_resp_item *. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_xover_single(newsnntp * session, uint32_t article, + struct newsnntp_xover_resp_item ** result); + +/* + newsnntp_xover_range() retrieves overview information for a + particular range of articles. + + @param session NNTP session + @param header the field name + @param rangeinf the lower bound of the range + @param rangesup the upper bound of the range + @param result a list of struct newsnntp_xover_resp_item *. + + @return the return code is one of NEWSNNTP_ERROR_XXX or + NEWSNNTP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int newsnntp_xover_range(newsnntp * session, uint32_t rangeinf, uint32_t rangesup, + clist ** result); +void xover_resp_item_free(struct newsnntp_xover_resp_item * n); + +/* + newsnntp_xover_resp_list_free() + + This function will free the data associated with a list of + struct newsnntp_xover_resp_item *. + + @param l the list of overview responses. +*/ + +LIBETPAN_EXPORT +void newsnntp_xover_resp_list_free(clist * l); + +/* deprecated */ +LIBETPAN_EXPORT +int newsnntp_authinfo_generic(newsnntp * session, const char * authentificator, + const char * arguments); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/nntp/newsnntp_socket.c b/Sources/libetpan/low-level/nntp/newsnntp_socket.c new file mode 100644 index 00000000..333e4951 --- /dev/null +++ b/Sources/libetpan/low-level/nntp/newsnntp_socket.c @@ -0,0 +1,112 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: newsnntp_socket.c,v 1.15 2009/12/19 00:57:31 hoa Exp $ + */ +#define HAVE_CONFIG_H 1 + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "newsnntp_socket.h" + +#include "newsnntp.h" + +#include "mailstream_cfstream.h" +#include "connect.h" + +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif + +#define DEFAULT_NNTP_PORT 119 +#define SERVICE_NAME_NNTP "nntp" +#define SERVICE_TYPE_TCP "tcp" + +#if HAVE_CFNETWORK +static int newsnntp_cfsocket_connect(newsnntp * f, const char * server, uint16_t port); +#endif + +int newsnntp_socket_connect(newsnntp * f, const char * server, uint16_t port) +{ + int s; + mailstream * stream; + +#if HAVE_CFNETWORK + if (mailstream_cfstream_enabled) { + return newsnntp_cfsocket_connect(f, server, port); + } +#endif + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_NNTP, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_NNTP_PORT; + } + + /* Connection */ + + s = mail_tcp_connect_timeout(server, port, f->nntp_timeout); + if (s == -1) + return NEWSNNTP_ERROR_CONNECTION_REFUSED; + + stream = mailstream_socket_open_timeout(s, f->nntp_timeout); + if (stream == NULL) { +#ifdef WIN32 + closesocket(s); +#else + close(s); +#endif + + return NEWSNNTP_ERROR_MEMORY; + } + + return newsnntp_connect(f, stream); +} + +#if HAVE_CFNETWORK +static int newsnntp_cfsocket_connect(newsnntp * f, const char * server, uint16_t port) +{ + mailstream * stream; + + stream = mailstream_cfstream_open_timeout(server, port, f->nntp_timeout); + if (stream == NULL) { + return NEWSNNTP_ERROR_STREAM; + } + + return newsnntp_connect(f, stream); +} +#endif diff --git a/Sources/libetpan/low-level/nntp/newsnntp_socket.h b/Sources/libetpan/low-level/nntp/newsnntp_socket.h new file mode 100644 index 00000000..7b6a160b --- /dev/null +++ b/Sources/libetpan/low-level/nntp/newsnntp_socket.h @@ -0,0 +1,58 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: newsnntp_socket.h,v 1.14 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifndef NEWSNNTP_SOCKET_H + +#define NEWSNNTP_SOCKET_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef HAVE_INTTYPES_H +# include +#endif + +#include + +LIBETPAN_EXPORT +int newsnntp_socket_connect(newsnntp * f, const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/nntp/newsnntp_ssl.c b/Sources/libetpan/low-level/nntp/newsnntp_ssl.c new file mode 100644 index 00000000..d68bc602 --- /dev/null +++ b/Sources/libetpan/low-level/nntp/newsnntp_ssl.c @@ -0,0 +1,135 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: newsnntp_ssl.c,v 1.18 2009/12/19 00:57:31 hoa Exp $ + */ +#define HAVE_CONFIG_H 1 + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "newsnntp_ssl.h" + +#include "newsnntp.h" +#include "mailstream_cfstream.h" + +#include "connect.h" +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif + +#define DEFAULT_NNTPS_PORT 563 +#define SERVICE_NAME_NNTPS "nntps" +#define SERVICE_TYPE_TCP "tcp" + +#if HAVE_CFNETWORK +static int newsnntp_cfssl_connect(newsnntp * f, const char * server, uint16_t port); +#endif + +int newsnntp_ssl_connect(newsnntp * f, const char * server, uint16_t port) +{ + return newsnntp_ssl_connect_with_callback(f, server, port, + NULL, NULL); +} + +int newsnntp_ssl_connect_with_callback(newsnntp * f, const char * server, uint16_t port, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data) +{ + int s; + mailstream * stream; + +#if HAVE_CFNETWORK + if (mailstream_cfstream_enabled) { + if (callback == NULL) { + return newsnntp_cfssl_connect(f, server, port); + } + } +#endif + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_NNTPS, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_NNTPS_PORT; + } + + /* Connection */ + + s = mail_tcp_connect_timeout(server, port, f->nntp_timeout); + if (s == -1) + return NEWSNNTP_ERROR_CONNECTION_REFUSED; + + stream = mailstream_ssl_open_with_callback_timeout(s, f->nntp_timeout, callback, data); + if (stream == NULL) { +#ifdef WIN32 + closesocket(s); +#else + close(s); +#endif + return NEWSNNTP_ERROR_SSL; + } + + return newsnntp_connect(f, stream); +} + +#if HAVE_CFNETWORK +static int newsnntp_cfssl_connect_ssl_level(newsnntp * f, const char * server, uint16_t port, int ssl_level) +{ + mailstream * stream; + int r; + + stream = mailstream_cfstream_open_timeout(server, port, f->nntp_timeout); + if (stream == NULL) { + return NEWSNNTP_ERROR_CONNECTION_REFUSED; + } + mailstream_cfstream_set_ssl_level(stream, ssl_level); + mailstream_cfstream_set_ssl_verification_mask(stream, MAILSTREAM_CFSTREAM_SSL_NO_VERIFICATION); + r = mailstream_cfstream_set_ssl_enabled(stream, 1); + if (r < 0) { + mailstream_close(stream); + return NEWSNNTP_ERROR_SSL; + } + + return newsnntp_connect(f, stream); +} +#endif + +#if HAVE_CFNETWORK +static int newsnntp_cfssl_connect(newsnntp * f, const char * server, uint16_t port) +{ + return newsnntp_cfssl_connect_ssl_level(f, server, port, MAILSTREAM_CFSTREAM_SSL_LEVEL_NEGOCIATED_SSL); +} +#endif + diff --git a/Sources/libetpan/low-level/nntp/newsnntp_ssl.h b/Sources/libetpan/low-level/nntp/newsnntp_ssl.h new file mode 100644 index 00000000..6465771f --- /dev/null +++ b/Sources/libetpan/low-level/nntp/newsnntp_ssl.h @@ -0,0 +1,62 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: newsnntp_ssl.h,v 1.17 2006/12/26 13:13:24 hoa Exp $ + */ + +#ifndef NEWSNNTP_SSL_H + +#define NEWSNNTP_SSL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifdef HAVE_INTTYPES_H +# include +#endif + +#include + +LIBETPAN_EXPORT +int newsnntp_ssl_connect(newsnntp * f, const char * server, uint16_t port); + +LIBETPAN_EXPORT +int newsnntp_ssl_connect_with_callback(newsnntp * f, const char * server, uint16_t port, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/nntp/newsnntp_types.h b/Sources/libetpan/low-level/nntp/newsnntp_types.h new file mode 100644 index 00000000..e3532b2b --- /dev/null +++ b/Sources/libetpan/low-level/nntp/newsnntp_types.h @@ -0,0 +1,155 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: newsnntp_types.h,v 1.15 2006/12/13 18:31:32 hoa Exp $ + */ + +#ifndef NEWSNNTP_TYPES_H + +#define NEWSNNTP_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include +#include + +enum { + NEWSNNTP_NO_ERROR = 0, + NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME=1, /* DEPRECATED, use ERROR instead */ + NEWSNNTP_ERROR_REQUEST_AUTHORIZATION_USERNAME=1, + NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD, + NEWSNNTP_ERROR_STREAM, + NEWSNNTP_ERROR_UNEXPECTED, + NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED, + NEWSNNTP_ERROR_NO_ARTICLE_SELECTED, + NEWSNNTP_ERROR_INVALID_ARTICLE_NUMBER, + NEWSNNTP_ERROR_ARTICLE_NOT_FOUND, + NEWSNNTP_ERROR_UNEXPECTED_RESPONSE, + NEWSNNTP_ERROR_INVALID_RESPONSE, + NEWSNNTP_ERROR_NO_SUCH_NEWS_GROUP, + NEWSNNTP_ERROR_POSTING_NOT_ALLOWED, + NEWSNNTP_ERROR_POSTING_FAILED, + NEWSNNTP_ERROR_PROGRAM_ERROR, + NEWSNNTP_ERROR_NO_PERMISSION, + NEWSNNTP_ERROR_COMMAND_NOT_UNDERSTOOD, + NEWSNNTP_ERROR_COMMAND_NOT_SUPPORTED, + NEWSNNTP_ERROR_CONNECTION_REFUSED, + NEWSNNTP_ERROR_MEMORY, + NEWSNNTP_ERROR_AUTHENTICATION_REJECTED, + NEWSNNTP_ERROR_BAD_STATE, + NEWSNNTP_ERROR_SSL, + NEWSNNTP_ERROR_AUTHENTICATION_OUT_OF_SEQUENCE, +}; + +typedef struct newsnntp newsnntp; + +struct newsnntp +{ + mailstream * nntp_stream; + + int nntp_readonly; + + size_t nntp_progr_rate; + progress_function * nntp_progr_fun; + + MMAPString * nntp_stream_buffer; + MMAPString * nntp_response_buffer; + + char * nntp_response; + + time_t nntp_timeout; + + void (* nntp_logger)(newsnntp * session, int log_type, const char * str, size_t size, void * context); + void * nntp_logger_context; + + mailprogress_function * nntp_progress_fun; + void * nntp_progress_context; +}; + +struct newsnntp_group_info +{ + char * grp_name; + uint32_t grp_first; + uint32_t grp_last; + uint32_t grp_count; + char grp_type; +}; + +struct newsnntp_group_time { + char * grp_name; + time_t grp_date; + char * grp_email; +}; + +struct newsnntp_distrib_value_meaning { + char * dst_value; + char * dst_meaning; +}; + +struct newsnntp_distrib_default_value { + uint32_t dst_weight; + char * dst_group_pattern; + char * dst_value; +}; + +struct newsnntp_group_description { + char * grp_name; + char * grp_description; +}; + +struct newsnntp_xhdr_resp_item { + uint32_t hdr_article; + char * hdr_value; +}; + +struct newsnntp_xover_resp_item { + uint32_t ovr_article; + char * ovr_subject; + char * ovr_author; + char * ovr_date; + char * ovr_message_id; + char * ovr_references; + size_t ovr_size; + uint32_t ovr_line_count; + clist * ovr_others; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/pop3/Makefile.am b/Sources/libetpan/low-level/pop3/Makefile.am new file mode 100644 index 00000000..64712d18 --- /dev/null +++ b/Sources/libetpan/low-level/pop3/Makefile.am @@ -0,0 +1,42 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +etpaninclude_HEADERS = \ + mailpop3.h mailpop3_socket.h mailpop3_helper.h mailpop3_ssl.h \ + mailpop3_types.h + +AM_CPPFLAGS = -I$(top_builddir)/include \ + -I$(top_srcdir)/src/data-types + +noinst_LTLIBRARIES = libpop3.la + +libpop3_la_SOURCES = \ + mailpop3.c mailpop3_helper.c mailpop3_socket.c mailpop3_ssl.c diff --git a/Sources/libetpan/low-level/pop3/mailpop3.c b/Sources/libetpan/low-level/pop3/mailpop3.c new file mode 100644 index 00000000..e2124bf8 --- /dev/null +++ b/Sources/libetpan/low-level/pop3/mailpop3.c @@ -0,0 +1,1695 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailpop3.c,v 1.36 2011/03/11 21:49:36 hoa Exp $ + */ + +/* + POP3 Protocol + + RFC 1734 + RFC 1939 + RFC 2449 + + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailpop3.h" +#include +#include +#include "md5.h" +#include "mail.h" +#include + +#ifdef USE_SASL +#include +#include +#endif + +#include "mailsasl.h" +#include "mailpop3_types.h" + + + + +enum { + POP3_STATE_DISCONNECTED, + POP3_STATE_AUTHORIZATION, + POP3_STATE_TRANSACTION +}; + +static inline void pop3_logger(mailstream * s, int log_type, + const char * str, size_t size, void * context); + + +/* + mailpop3_msg_info structure +*/ + +static struct mailpop3_msg_info * +mailpop3_msg_info_new(unsigned int indx, uint32_t size, char * uidl) +{ + struct mailpop3_msg_info * msg; + + msg = malloc(sizeof(* msg)); + if (msg == NULL) + return NULL; + msg->msg_index = indx; + msg->msg_size = size; + msg->msg_deleted = FALSE; + msg->msg_uidl = uidl; + + return msg; +} + +static void mailpop3_msg_info_free(struct mailpop3_msg_info * msg) +{ + if (msg->msg_uidl != NULL) + free(msg->msg_uidl); + free(msg); +} + +static void mailpop3_msg_info_tab_free(carray * msg_tab) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(msg_tab) ; i++) { + struct mailpop3_msg_info * msg; + + msg = carray_get(msg_tab, i); + mailpop3_msg_info_free(msg); + } + carray_free(msg_tab); +} + +static void mailpop3_msg_info_tab_reset(carray * msg_tab) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(msg_tab) ; i++) { + struct mailpop3_msg_info * msg; + msg = carray_get(msg_tab, i); + msg->msg_deleted = FALSE; + } +} + +static inline struct mailpop3_msg_info * +mailpop3_msg_info_tab_find_msg(carray * msg_tab, unsigned int indx) +{ + struct mailpop3_msg_info * msg; + + if (indx == 0) + return NULL; + + if (indx > carray_count(msg_tab)) + return NULL; + + msg = carray_get(msg_tab, indx - 1); + + return msg; +} + + + +int mailpop3_get_msg_info(mailpop3 * f, unsigned int indx, + struct mailpop3_msg_info ** result) +{ + carray * tab; + struct mailpop3_msg_info * info; + int r; + + r = mailpop3_list(f, &tab); + if (r != MAILPOP3_NO_ERROR) + return r; + + if (tab == NULL) + return MAILPOP3_ERROR_BAD_STATE; + + info = mailpop3_msg_info_tab_find_msg(tab, indx); + if (info == NULL) + return MAILPOP3_ERROR_NO_SUCH_MESSAGE; + + * result = info; + + return MAILPOP3_NO_ERROR; +} + + +/* + mailpop3_capa +*/ + +struct mailpop3_capa * mailpop3_capa_new(char * name, clist * param) +{ + struct mailpop3_capa * capa; + + capa = malloc(sizeof(* capa)); + if (capa == NULL) + return NULL; + capa->cap_name = name; + capa->cap_param = param; + + return capa; +} + + + +void mailpop3_capa_free(struct mailpop3_capa * capa) +{ + clist_foreach(capa->cap_param, (clist_func) free, NULL); + clist_free(capa->cap_param); + free(capa->cap_name); + free(capa); +} + + +/* + mailpop3_stat_response +*/ + +struct mailpop3_stat_response * mailpop3_stat_response_new(uint32_t count, uint32_t size) +{ + struct mailpop3_stat_response * stat_response; + + stat_response = malloc(sizeof(* stat_response)); + if(stat_response == NULL) + return NULL; + stat_response->msgs_count = count; + stat_response->msgs_size = size; + + return stat_response; +} + +void mailpop3_stat_resp_free(struct mailpop3_stat_response * stat_response) +{ + free(stat_response); +} + +/* + mailpop3 structure +*/ + +mailpop3 * mailpop3_new(size_t progr_rate, progress_function * progr_fun) +{ + mailpop3 * f; + + f = malloc(sizeof(* f)); + if (f == NULL) + goto err; + + f->pop3_timestamp = NULL; + f->pop3_response = NULL; + + f->pop3_stream = NULL; + + f->pop3_progr_rate = progr_rate; + f->pop3_progr_fun = progr_fun; + + f->pop3_stream_buffer = mmap_string_new(""); + if (f->pop3_stream_buffer == NULL) + goto free_f; + + f->pop3_response_buffer = mmap_string_new(""); + if (f->pop3_response_buffer == NULL) + goto free_stream_buffer; + + f->pop3_msg_tab = NULL; + f->pop3_deleted_count = 0; + f->pop3_state = POP3_STATE_DISCONNECTED; + + f->pop3_sasl.sasl_conn = NULL; + + f->pop3_timeout = 0; + f->pop3_progress_fun = NULL; + f->pop3_progress_context = NULL; + + f->pop3_logger = NULL; + f->pop3_logger_context = NULL; + + return f; + + free_stream_buffer: + mmap_string_free(f->pop3_stream_buffer); + free_f: + free(f); + err: + return NULL; +} + + + +void mailpop3_free(mailpop3 * f) +{ +#ifdef USE_SASL + if (f->pop3_sasl.sasl_conn != NULL) { + sasl_dispose((sasl_conn_t **) &f->pop3_sasl.sasl_conn); + mailsasl_unref(); + } +#endif + + if (f->pop3_stream) + mailpop3_quit(f); + + mmap_string_free(f->pop3_response_buffer); + mmap_string_free(f->pop3_stream_buffer); + + free(f); +} + + + + + + + + + + + +/* + operations on mailpop3 structure +*/ + +#define RESPONSE_OK 0 +#define RESPONSE_ERR -1 +#define RESPONSE_AUTH_CONT 1 + +static int send_command(mailpop3 * f, char * command); +static int send_command_private(mailpop3 * f, char * command, int can_be_published); + +static char * read_line(mailpop3 * f); + +static char * read_multiline(mailpop3 * f, size_t size, + MMAPString * multiline_buffer); + +static int parse_response(mailpop3 * f, char * response); + + +/* get the timestamp in the connection response */ + +#define TIMESTAMP_START '<' +#define TIMESTAMP_END '>' + +static char * mailpop3_get_timestamp(char * response) +{ + char * begin_timestamp; + char * end_timestamp; + char * timestamp; + size_t len_timestamp; + + if (response == NULL) + return NULL; + + begin_timestamp = strchr(response, TIMESTAMP_START); + + end_timestamp = NULL; + if (begin_timestamp != NULL) { + end_timestamp = strchr(begin_timestamp, TIMESTAMP_END); + if (end_timestamp == NULL) + begin_timestamp = NULL; + } + + if (!begin_timestamp) + return NULL; + + len_timestamp = end_timestamp - begin_timestamp + 1; + + timestamp = malloc(len_timestamp + 1); + if (timestamp == NULL) + return NULL; + strncpy(timestamp, begin_timestamp, len_timestamp); + timestamp[len_timestamp] = '\0'; + + return timestamp; +} + +/* + connect a stream to the mailpop3 structure +*/ + +int mailpop3_connect(mailpop3 * f, mailstream * s) +{ + char * response; + int r; + char * timestamp; + + if (f->pop3_state != POP3_STATE_DISCONNECTED) + return MAILPOP3_ERROR_BAD_STATE; + + f->pop3_stream = s; + mailstream_set_logger(s, pop3_logger, f); + + response = read_line(f); + + r = parse_response(f, response); + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_UNAUTHORIZED; + + f->pop3_state = POP3_STATE_AUTHORIZATION; + + timestamp = mailpop3_get_timestamp(f->pop3_response); + if (timestamp != NULL) + f->pop3_timestamp = timestamp; + + return MAILPOP3_NO_ERROR; +} + + +/* + disconnect from a pop3 server +*/ + +int mailpop3_quit(mailpop3 * f) +{ + char command[POP3_STRING_SIZE]; + char * response; + int r; + int res; + + if ((f->pop3_state != POP3_STATE_AUTHORIZATION) + && (f->pop3_state != POP3_STATE_TRANSACTION)) { + res = MAILPOP3_ERROR_BAD_STATE; + goto close; + } + + snprintf(command, POP3_STRING_SIZE, "QUIT\r\n"); + r = send_command(f, command); + if (r == -1) { + res = MAILPOP3_ERROR_STREAM; + goto close; + } + + response = read_line(f); + if (response == NULL) { + res = MAILPOP3_ERROR_STREAM; + goto close; + } + if (parse_response(f, response) == RESPONSE_OK) { + res = MAILPOP3_NO_ERROR; + } + else { + res = MAILPOP3_ERROR_QUIT_FAILED; + } + + res = MAILPOP3_NO_ERROR; + + close: + if (f->pop3_stream != NULL) { + mailstream_close(f->pop3_stream); + f->pop3_stream = NULL; + } + + if (f->pop3_timestamp != NULL) { + free(f->pop3_timestamp); + f->pop3_timestamp = NULL; + } + + if (f->pop3_msg_tab != NULL) { + mailpop3_msg_info_tab_free(f->pop3_msg_tab); + f->pop3_msg_tab = NULL; + } + + f->pop3_state = POP3_STATE_DISCONNECTED; + + return res; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +int mailpop3_apop(mailpop3 * f, + const char * user, const char * password) +{ + char command[POP3_STRING_SIZE]; + MD5_CTX md5context; + unsigned char md5digest[16]; + char md5string[33]; + char * cmd_ptr; + int r; + int i; + char * response; + + if (f->pop3_state != POP3_STATE_AUTHORIZATION) + return MAILPOP3_ERROR_BAD_STATE; + + if (f->pop3_timestamp == NULL) + return MAILPOP3_ERROR_APOP_NOT_SUPPORTED; + + /* calculate md5 sum */ + + MD5Init(&md5context); + MD5Update(&md5context, (const unsigned char *) f->pop3_timestamp, (unsigned int) strlen (f->pop3_timestamp)); + MD5Update(&md5context, (const unsigned char *) password, (unsigned int) strlen (password)); + MD5Final(md5digest, &md5context); + + cmd_ptr = md5string; + for(i = 0 ; i < 16 ; i++, cmd_ptr += 2) + snprintf(cmd_ptr, 3, "%02x", md5digest[i]); + * cmd_ptr = 0; + + /* send apop command */ + + snprintf(command, POP3_STRING_SIZE, "APOP %s %s\r\n", user, md5string); + r = send_command_private(f, command, 0); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_DENIED; + + f->pop3_state = POP3_STATE_TRANSACTION; + + return MAILPOP3_NO_ERROR; +} + +int mailpop3_user(mailpop3 * f, const char * user) +{ + char command[POP3_STRING_SIZE]; + int r; + char * response; + + if (f->pop3_state != POP3_STATE_AUTHORIZATION) + return MAILPOP3_ERROR_BAD_STATE; + + /* send user command */ + + snprintf(command, POP3_STRING_SIZE, "USER %s\r\n", user); + r = send_command_private(f, command, 0); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_BAD_USER; + + return MAILPOP3_NO_ERROR; +} + +int mailpop3_pass(mailpop3 * f, const char * password) +{ + char command[POP3_STRING_SIZE]; + int r; + char * response; + + if (f->pop3_state != POP3_STATE_AUTHORIZATION) + return MAILPOP3_ERROR_BAD_STATE; + + /* send password command */ + + snprintf(command, POP3_STRING_SIZE, "PASS %s\r\n", password); + r = send_command_private(f, command, 0); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_BAD_PASSWORD; + + f->pop3_state = POP3_STATE_TRANSACTION; + + return MAILPOP3_NO_ERROR; +} + +static int read_list(mailpop3 * f, carray ** result); + + + +static int read_uidl(mailpop3 * f, carray * msg_tab); + + + +static int mailpop3_do_uidl(mailpop3 * f, carray * msg_tab) +{ + char command[POP3_STRING_SIZE]; + int r; + char * response; + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + /* send list command */ + + snprintf(command, POP3_STRING_SIZE, "UIDL\r\n"); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_CANT_LIST; + + r = read_uidl(f, msg_tab); + if (r != MAILPOP3_NO_ERROR) + return r; + + return MAILPOP3_NO_ERROR; +} + + + +static int mailpop3_do_list(mailpop3 * f) +{ + char command[POP3_STRING_SIZE]; + int r; + carray * msg_tab; + char * response; + + if (f->pop3_msg_tab != NULL) { + mailpop3_msg_info_tab_free(f->pop3_msg_tab); + f->pop3_msg_tab = NULL; + } + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + /* send list command */ + + snprintf(command, POP3_STRING_SIZE, "LIST\r\n"); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_CANT_LIST; + + r = read_list(f, &msg_tab); + if (r != MAILPOP3_NO_ERROR) + return r; + + f->pop3_msg_tab = msg_tab; + f->pop3_deleted_count = 0; + + mailpop3_do_uidl(f, msg_tab); + + return MAILPOP3_NO_ERROR; +} + + + +static int mailpop3_list_if_needed(mailpop3 * f) +{ + if (f->pop3_msg_tab == NULL) + return mailpop3_do_list(f); + return MAILPOP3_NO_ERROR; +} + +/* + mailpop3_list +*/ + +int mailpop3_list(mailpop3 * f, carray ** result) +{ + int r; + r = mailpop3_list_if_needed(f); + if (r == MAILPOP3_NO_ERROR) + * result = f->pop3_msg_tab; + return r; +} + +static inline struct mailpop3_msg_info * +find_msg(mailpop3 * f, unsigned int indx) +{ + mailpop3_list_if_needed(f); + + if (f->pop3_msg_tab == NULL) + return NULL; + + return mailpop3_msg_info_tab_find_msg(f->pop3_msg_tab, indx); +} + + + + + + + + +static void mailpop3_multiline_response_free(char * str) +{ + mmap_string_unref(str); +} + +void mailpop3_top_free(char * str) +{ + mailpop3_multiline_response_free(str); +} + +void mailpop3_retr_free(char * str) +{ + mailpop3_multiline_response_free(str); +} + +/* + mailpop3_retr + + message content in (* result) is still there until the + next retrieve or top operation on the mailpop3 structure +*/ + +static int +mailpop3_get_content(mailpop3 * f, struct mailpop3_msg_info * msginfo, + char ** result, size_t * result_len) +{ + char * response; + char * result_multiline; + MMAPString * buffer; + int r; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_NO_SUCH_MESSAGE; + + buffer = mmap_string_new(""); + if (buffer == NULL) + return MAILPOP3_ERROR_MEMORY; + + result_multiline = read_multiline(f, msginfo->msg_size, buffer); + if (result_multiline == NULL) { + mmap_string_free(buffer); + return MAILPOP3_ERROR_STREAM; + } + else { + r = mmap_string_ref(buffer); + if (r < 0) { + mmap_string_free(buffer); + return MAILPOP3_ERROR_MEMORY; + } + + * result = result_multiline; + * result_len = buffer->len; + return MAILPOP3_NO_ERROR; + } +} + +int mailpop3_retr(mailpop3 * f, unsigned int indx, char ** result, + size_t * result_len) +{ + char command[POP3_STRING_SIZE]; + struct mailpop3_msg_info * msginfo; + int r; + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + msginfo = find_msg(f, indx); + + if (msginfo == NULL) { + f->pop3_response = NULL; + return MAILPOP3_ERROR_NO_SUCH_MESSAGE; + } + + snprintf(command, POP3_STRING_SIZE, "RETR %i\r\n", indx); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + return mailpop3_get_content(f, msginfo, result, result_len); +} + +int mailpop3_top(mailpop3 * f, unsigned int indx, + unsigned int count, char ** result, + size_t * result_len) +{ + char command[POP3_STRING_SIZE]; + struct mailpop3_msg_info * msginfo; + int r; + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + msginfo = find_msg(f, indx); + + if (msginfo == NULL) { + f->pop3_response = NULL; + return MAILPOP3_ERROR_NO_SUCH_MESSAGE; + } + + snprintf(command, POP3_STRING_SIZE, "TOP %i %i\r\n", indx, count); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + return mailpop3_get_content(f, msginfo, result, result_len); +} + +int mailpop3_dele(mailpop3 * f, unsigned int indx) +{ + char command[POP3_STRING_SIZE]; + struct mailpop3_msg_info * msginfo; + char * response; + int r; + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + msginfo = find_msg(f, indx); + + if (msginfo == NULL) { + f->pop3_response = NULL; + return MAILPOP3_ERROR_NO_SUCH_MESSAGE; + } + + snprintf(command, POP3_STRING_SIZE, "DELE %i\r\n", indx); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_NO_SUCH_MESSAGE; + + msginfo->msg_deleted = TRUE; + f->pop3_deleted_count ++; + + return MAILPOP3_NO_ERROR; +} + +int mailpop3_noop(mailpop3 * f) +{ + char command[POP3_STRING_SIZE]; + char * response; + int r; + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + snprintf(command, POP3_STRING_SIZE, "NOOP\r\n"); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + parse_response(f, response); + + return MAILPOP3_NO_ERROR; +} + +int mailpop3_rset(mailpop3 * f) +{ + char command[POP3_STRING_SIZE]; + char * response; + int r; + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + snprintf(command, POP3_STRING_SIZE, "RSET\r\n"); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + parse_response(f, response); + + if (f->pop3_msg_tab != NULL) { + mailpop3_msg_info_tab_reset(f->pop3_msg_tab); + f->pop3_deleted_count = 0; + } + + return MAILPOP3_NO_ERROR; +} + + + +static int read_capa_resp(mailpop3 * f, clist ** result); + +int mailpop3_capa(mailpop3 * f, clist ** result) +{ + clist * capa_list; + char command[POP3_STRING_SIZE]; + int r; + char * response; + + snprintf(command, POP3_STRING_SIZE, "CAPA\r\n"); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_CAPA_NOT_SUPPORTED; + + capa_list = NULL; + r = read_capa_resp(f, &capa_list); + if (r != MAILPOP3_NO_ERROR) + return r; + + * result = capa_list; + + return MAILPOP3_NO_ERROR; +} + +void mailpop3_capa_resp_free(clist * capa_list) +{ + clist_foreach(capa_list, (clist_func) mailpop3_capa_free, NULL); + clist_free(capa_list); +} + +int mailpop3_stls(mailpop3 * f) +{ + char command[POP3_STRING_SIZE]; + int r; + char * response; + + snprintf(command, POP3_STRING_SIZE, "STLS\r\n"); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_STLS_NOT_SUPPORTED; + + // Detect if the server send extra data after the STLS response. + // This *may* be a "response injection attack". + if (f->pop3_stream->read_buffer_len != 0) { + // Since it is also protocol violation, exit. + // There is no error type for STARTTLS errors in POP3 + return MAILPOP3_ERROR_SSL; + } + + return MAILPOP3_NO_ERROR; +} + +static int parse_stat_response(mailpop3 * f, struct mailpop3_stat_response ** result); + +int mailpop3_stat(mailpop3 * f, struct mailpop3_stat_response ** result) +{ + struct mailpop3_stat_response * stat_response; + char command[POP3_STRING_SIZE]; + int r; + char * response; + + snprintf(command, POP3_STRING_SIZE, "STAT\r\n"); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_CAPA_NOT_SUPPORTED; + + stat_response = NULL; + r = parse_stat_response(f, &stat_response); + if (r != MAILPOP3_NO_ERROR) + return r; + + * result = stat_response; + + return MAILPOP3_NO_ERROR; +} + + + +#define RESP_OK_STR "+OK" +#define RESP_ERR_STR "-ERR" +#define RESP_AUTH_CONT_STR "+" + + +static int parse_space(char ** line) +{ + char * p; + + p = * line; + + while ((* p == ' ') || (* p == '\t')) + p ++; + + if (p != * line) { + * line = p; + return TRUE; + } + else + return FALSE; +} + +static char * cut_token(char * line) +{ + char * p; + char * p_tab; + char * p_space; + + p = line; + + p_space = strchr(line, ' '); + p_tab = strchr(line, '\t'); + if (p_tab == NULL) + p = p_space; + else if (p_space == NULL) + p = p_tab; + else { + if (p_tab < p_space) + p = p_tab; + else + p = p_space; + } + if (p == NULL) + return NULL; + * p = 0; + p ++; + + return p; +} + + +static int parse_response(mailpop3 * f, char * response) +{ + char * msg; + + if (response == NULL) { + f->pop3_response = NULL; + return RESPONSE_ERR; + } + + if (strncmp(response, RESP_OK_STR, strlen(RESP_OK_STR)) == 0) { + + if (response[strlen(RESP_OK_STR)] == ' ') + msg = response + strlen(RESP_OK_STR) + 1; + else + msg = response + strlen(RESP_OK_STR); + + if (mmap_string_assign(f->pop3_response_buffer, msg)) + f->pop3_response = f->pop3_response_buffer->str; + else + f->pop3_response = NULL; + + return RESPONSE_OK; + } + else if (strncmp(response, RESP_ERR_STR, strlen(RESP_ERR_STR)) == 0) { + + if (response[strlen(RESP_ERR_STR)] == ' ') + msg = response + strlen(RESP_ERR_STR) + 1; + else + msg = response + strlen(RESP_ERR_STR); + + if (mmap_string_assign(f->pop3_response_buffer, msg)) + f->pop3_response = f->pop3_response_buffer->str; + else + f->pop3_response = NULL; + + return RESPONSE_ERR; + } + + f->pop3_response = NULL; + return RESPONSE_ERR; +} + + + + + +#ifdef USE_SASL +static int parse_auth(mailpop3 * f, char * response) +{ + char * msg; + + if (response == NULL) { + f->pop3_response = NULL; + return RESPONSE_ERR; + } + + if ((strncmp(response, RESP_AUTH_CONT_STR, strlen(RESP_AUTH_CONT_STR)) == 0) && + (strncmp(response, RESP_OK_STR, strlen(RESP_OK_STR)) != 0)) { + + if (response[strlen(RESP_AUTH_CONT_STR)] == ' ') + msg = response + strlen(RESP_AUTH_CONT_STR) + 1; + else + msg = response + strlen(RESP_AUTH_CONT_STR); + + if (mmap_string_assign(f->pop3_response_buffer, msg)) + f->pop3_response = f->pop3_response_buffer->str; + else + f->pop3_response = NULL; + + return RESPONSE_AUTH_CONT; + } + else { + return parse_response(f, response); + } +} +#endif + + +static int read_list(mailpop3 * f, carray ** result) +{ + unsigned int indx; + uint32_t size; + carray * msg_tab; + struct mailpop3_msg_info * msg; + char * line; + + msg_tab = carray_new(128); + if (msg_tab == NULL) + goto err; + + while (1) { + line = read_line(f); + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + indx = (unsigned int) strtol(line, &line, 10); + + if (!parse_space(&line)) + continue; + + size = (uint32_t) strtol(line, &line, 10); + + msg = mailpop3_msg_info_new(indx, size, NULL); + if (msg == NULL) + goto free_list; + + if (carray_count(msg_tab) < indx) { + int r; + + r = carray_set_size(msg_tab, indx); + if (r == -1) { + mailpop3_msg_info_free(msg); + goto free_list; + } + } + + carray_set(msg_tab, indx - 1, msg); + } + + * result = msg_tab; + + return MAILPOP3_NO_ERROR; + + free_list: + mailpop3_msg_info_tab_free(msg_tab); + err: + return MAILPOP3_ERROR_STREAM; +} + + + +static int read_uidl(mailpop3 * f, carray * msg_tab) +{ + unsigned int indx; + struct mailpop3_msg_info * msg; + char * line; + + while (1) { + char * uidl; + + line = read_line(f); + if (line == NULL) + goto err; + + if (mailstream_is_end_multiline(line)) + break; + + indx = (unsigned int) strtol(line, &line, 10); + + if (!parse_space(&line)) + continue; + + uidl = strdup(line); + if (uidl == NULL) + continue; + + if (indx > carray_count(msg_tab)) { + free(uidl); + continue; + } + + msg = carray_get(msg_tab, indx - 1); + if (msg == NULL) { + free(uidl); + continue; + } + + msg->msg_uidl = uidl; + } + + return MAILPOP3_NO_ERROR; + + err: + return MAILPOP3_ERROR_STREAM; +} + + + +static int read_capa_resp(mailpop3 * f, clist ** result) +{ + char * line; + int res; + clist * list; + int r; + char * name; + clist * param_list; + + list = clist_new(); + if (list == NULL) { + res = MAILPOP3_NO_ERROR; + goto err; + } + + while (1) { + char * next_token; + char * param; + struct mailpop3_capa * capa; + + line = read_line(f); + if (line == NULL) { + res = MAILPOP3_ERROR_STREAM; + goto free_list; + } + + if (mailstream_is_end_multiline(line)) + break; + + next_token = cut_token(line); + name = strdup(line); + if (name == NULL) { + res = MAILPOP3_ERROR_MEMORY; + goto free_list; + } + + param_list = clist_new(); + if (param_list == NULL) { + res = MAILPOP3_ERROR_MEMORY; + goto free_capa_name; + } + + while (next_token != NULL) { + line = next_token; + next_token = cut_token(line); + param = strdup(line); + if (param == NULL) { + res = MAILPOP3_ERROR_MEMORY; + goto free_param_list; + } + r = clist_append(param_list, param); + if (r < 0) { + free(param); + res = MAILPOP3_ERROR_MEMORY; + goto free_param_list; + } + } + + capa = mailpop3_capa_new(name, param_list); + if (capa == NULL) { + res = MAILPOP3_ERROR_MEMORY; + goto free_param_list; + } + + r = clist_append(list, capa); + if (r < 0) { + mailpop3_capa_free(capa); + res = MAILPOP3_ERROR_MEMORY; + goto free_list; + } + } + + * result = list; + + return MAILPOP3_NO_ERROR; + + free_param_list: + clist_foreach(param_list, (clist_func) free, NULL); + clist_free(param_list); + free_capa_name: + free(name); + free_list: + clist_foreach(list, (clist_func) mailpop3_capa_free, NULL); + clist_free(list); + err: + return res; +} + +static int parse_stat_response(mailpop3 * f, struct mailpop3_stat_response ** result) +{ + unsigned int count; + uint32_t size; + struct mailpop3_stat_response * resp; + char * line; + + line = f->pop3_response; + if (line == NULL) + goto err; + + count = (unsigned int) strtol(line, &line, 10); + + if (!parse_space(&line)) + goto err; + + size = (uint32_t) strtol(line, &line, 10); + + resp = mailpop3_stat_response_new(count, size); + if(resp == NULL) + return MAILPOP3_ERROR_MEMORY; + + * result = resp; + + return MAILPOP3_NO_ERROR; + + err: + return MAILPOP3_ERROR_STREAM; +} + + + +static char * read_line(mailpop3 * f) +{ + return mailstream_read_line_remove_eol(f->pop3_stream, f->pop3_stream_buffer); +} + +static char * read_multiline(mailpop3 * f, size_t size, + MMAPString * multiline_buffer) +{ + return mailstream_read_multiline(f->pop3_stream, size, + f->pop3_stream_buffer, multiline_buffer, + f->pop3_progr_rate, f->pop3_progr_fun, f->pop3_progress_fun, f->pop3_progress_context); +} + +static int send_command(mailpop3 * f, char * command) +{ + return send_command_private(f, command, 1); +} + +static int send_command_private(mailpop3 * f, char * command, int can_be_published) +{ + ssize_t r; + + mailstream_set_privacy(f->pop3_stream, can_be_published); + r = mailstream_write(f->pop3_stream, command, strlen(command)); + if (r == -1) + return -1; + + r = mailstream_flush(f->pop3_stream); + if (r == -1) + return -1; + + return 0; +} + + + +#ifdef USE_SASL +static int sasl_getsimple(void * context, int id, + const char ** result, unsigned * len) +{ + mailpop3 * session; + + session = context; + + switch (id) { + case SASL_CB_USER: + if (result != NULL) + * result = session->pop3_sasl.sasl_login; + if (len != NULL) + * len = (unsigned) strlen(session->pop3_sasl.sasl_login); + return SASL_OK; + + case SASL_CB_AUTHNAME: + if (result != NULL) + * result = session->pop3_sasl.sasl_auth_name; + if (len != NULL) + * len = (unsigned) strlen(session->pop3_sasl.sasl_auth_name); + return SASL_OK; + } + + return SASL_FAIL; +} + +static int sasl_getsecret(sasl_conn_t * conn, void * context, int id, + sasl_secret_t ** psecret) +{ + mailpop3 * session; + + session = context; + + switch (id) { + case SASL_CB_PASS: + if (psecret != NULL) + * psecret = session->pop3_sasl.sasl_secret; + return SASL_OK; + } + + return SASL_FAIL; +} + +static int sasl_getrealm(void * context, int id, + const char ** availrealms, + const char ** result) +{ + mailpop3 * session; + + session = context; + + switch (id) { + case SASL_CB_GETREALM: + if (result != NULL) + * result = session->pop3_sasl.sasl_realm; + return SASL_OK; + } + + return SASL_FAIL; +} +#endif + +int mailpop3_auth(mailpop3 * f, const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm) +{ +#ifdef USE_SASL + int r; + char command[POP3_STRING_SIZE]; + sasl_callback_t sasl_callback[5]; + const char * sasl_out; + unsigned sasl_out_len; + const char * mechusing; + sasl_secret_t * secret; + int res; + size_t len; + char * encoded; + unsigned int encoded_len; + unsigned int max_encoded; + + sasl_callback[0].id = SASL_CB_GETREALM; + sasl_callback[0].proc = (int(*)(void)) sasl_getrealm; + sasl_callback[0].context = f; + sasl_callback[1].id = SASL_CB_USER; + sasl_callback[1].proc = (int(*)(void)) sasl_getsimple; + sasl_callback[1].context = f; + sasl_callback[2].id = SASL_CB_AUTHNAME; + sasl_callback[2].proc = (int(*)(void)) sasl_getsimple; + sasl_callback[2].context = f; + sasl_callback[3].id = SASL_CB_PASS; + sasl_callback[3].proc = (int(*)(void)) sasl_getsecret; + sasl_callback[3].context = f; + sasl_callback[4].id = SASL_CB_LIST_END; + sasl_callback[4].proc = NULL; + sasl_callback[4].context = NULL; + + len = strlen(password); + secret = malloc(sizeof(* secret) + len); + if (secret == NULL) { + res = MAILPOP3_ERROR_MEMORY; + goto err; + } + secret->len = len; + memcpy(secret->data, password, len + 1); + + f->pop3_sasl.sasl_server_fqdn = server_fqdn; + f->pop3_sasl.sasl_login = login; + f->pop3_sasl.sasl_auth_name = auth_name; + f->pop3_sasl.sasl_password = password; + f->pop3_sasl.sasl_realm = realm; + f->pop3_sasl.sasl_secret = secret; + + /* init SASL */ + if (f->pop3_sasl.sasl_conn != NULL) { + sasl_dispose((sasl_conn_t **) &f->pop3_sasl.sasl_conn); + f->pop3_sasl.sasl_conn = NULL; + } + else { + mailsasl_ref(); + } + + r = sasl_client_new("pop", server_fqdn, + local_ip_port, remote_ip_port, sasl_callback, 0, + (sasl_conn_t **) &f->pop3_sasl.sasl_conn); + if (r != SASL_OK) { + res = MAILPOP3_ERROR_BAD_USER; + goto free_secret; + } + + r = sasl_client_start(f->pop3_sasl.sasl_conn, + auth_type, NULL, &sasl_out, &sasl_out_len, &mechusing); + if ((r != SASL_CONTINUE) && (r != SASL_OK)) { + res = MAILPOP3_ERROR_BAD_USER; + goto free_sasl_conn; + } + + snprintf(command, POP3_STRING_SIZE, "AUTH %s\r\n", auth_type); + + r = send_command(f, command); + if (r == -1) { + res = MAILPOP3_ERROR_STREAM; + goto free_sasl_conn; + } + + while (1) { + char * response; + + response = read_line(f); + + r = parse_auth(f, response); + switch (r) { + case RESPONSE_OK: + f->pop3_state = POP3_STATE_TRANSACTION; + res = MAILPOP3_NO_ERROR; + goto free_sasl_conn; + + case RESPONSE_ERR: + res = MAILPOP3_ERROR_BAD_USER; + goto free_sasl_conn; + + case RESPONSE_AUTH_CONT: + { + unsigned int response_len; + char * decoded; + unsigned int decoded_len; + unsigned int max_decoded; + int got_response; + + got_response = 1; + if (f->pop3_response == NULL) { + // Make clang static analyzer happy. + got_response = 0; + } + else if (* f->pop3_response == '\0') + got_response = 0; + + if (got_response) { + char * p; + + p = strchr(f->pop3_response, '\r'); + if (p != NULL) { + * p = '\0'; + } + p = strchr(f->pop3_response, '\n'); + if (p != NULL) { + * p = '\0'; + } + response_len = (unsigned int) strlen(f->pop3_response); + max_decoded = response_len * 3 / 4; + decoded = malloc(max_decoded + 1); + if (decoded == NULL) { + res = MAILPOP3_ERROR_MEMORY; + goto free_sasl_conn; + } + + r = sasl_decode64(f->pop3_response, response_len, + decoded, max_decoded + 1, &decoded_len); + + if (r != SASL_OK) { + free(decoded); + res = MAILPOP3_ERROR_MEMORY; + goto free_sasl_conn; + } + + r = sasl_client_step(f->pop3_sasl.sasl_conn, + decoded, decoded_len, NULL, &sasl_out, &sasl_out_len); + + free(decoded); + + if ((r != SASL_CONTINUE) && (r != SASL_OK)) { + res = MAILPOP3_ERROR_BAD_USER; + goto free_sasl_conn; + } + } + + max_encoded = ((sasl_out_len + 2) / 3) * 4; + encoded = malloc(max_encoded + 1); + if (encoded == NULL) { + res = MAILPOP3_ERROR_MEMORY; + goto free_sasl_conn; + } + + r = sasl_encode64(sasl_out, sasl_out_len, + encoded, max_encoded + 1, &encoded_len); + if (r != SASL_OK) { + free(encoded); + res = MAILPOP3_ERROR_MEMORY; + goto free_sasl_conn; + } + + snprintf(command, POP3_STRING_SIZE, "%s\r\n", encoded); + r = send_command(f, command); + + free(encoded); + + if (r == -1) { + res = MAILPOP3_ERROR_STREAM; + goto free_sasl_conn; + } + } + break; + } + } + + f->pop3_state = POP3_STATE_TRANSACTION; + res = MAILPOP3_NO_ERROR; + + free_sasl_conn: + sasl_dispose((sasl_conn_t **) &f->pop3_sasl.sasl_conn); + f->pop3_sasl.sasl_conn = NULL; + mailsasl_unref(); + free_secret: + free(f->pop3_sasl.sasl_secret); + f->pop3_sasl.sasl_secret = NULL; + err: + return res; +#else + return MAILPOP3_ERROR_BAD_USER; +#endif +} + +void mailpop3_set_timeout(mailpop3 * f, time_t timeout) +{ + f->pop3_timeout = timeout; +} + +time_t mailpop3_get_timeout(mailpop3 * f) +{ + return f->pop3_timeout; +} + +void mailpop3_set_progress_callback(mailpop3 * f, mailprogress_function * progr_fun, void * context) +{ + f->pop3_progress_fun = progr_fun; + f->pop3_progress_context = context; +} + +static inline void pop3_logger(mailstream * s, int log_type, + const char * str, size_t size, void * context) +{ + mailpop3 * session; + + session = context; + if (session->pop3_logger == NULL) + return; + + session->pop3_logger(session, log_type, str, size, session->pop3_logger_context); +} + +LIBETPAN_EXPORT +void mailpop3_set_logger(mailpop3 * session, void (* logger)(mailpop3 * session, int log_type, + const char * str, size_t size, void * context), void * logger_context) +{ + session->pop3_logger = logger; + session->pop3_logger_context = logger_context; +} diff --git a/Sources/libetpan/low-level/pop3/mailpop3.h b/Sources/libetpan/low-level/pop3/mailpop3.h new file mode 100644 index 00000000..1a397843 --- /dev/null +++ b/Sources/libetpan/low-level/pop3/mailpop3.h @@ -0,0 +1,146 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailpop3.h,v 1.19 2010/04/05 12:56:44 hoa Exp $ + */ + +#ifndef MAILPOP3_H + +#define MAILPOP3_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +#include +#include + +#define POP3_STRING_SIZE 513 + +LIBETPAN_EXPORT +mailpop3 * mailpop3_new(size_t pop3_progr_rate, + progress_function * pop3_progr_fun); + +LIBETPAN_EXPORT +void mailpop3_free(mailpop3 * f); + +LIBETPAN_EXPORT +void mailpop3_set_timeout(mailpop3 * f, time_t timeout); + +LIBETPAN_EXPORT +time_t mailpop3_get_timeout(mailpop3 * f); + +LIBETPAN_EXPORT +void mailpop3_set_progress_callback(mailpop3 * f, mailprogress_function * progr_fun, void * context); + +LIBETPAN_EXPORT +int mailpop3_connect(mailpop3 * f, mailstream * s); + +LIBETPAN_EXPORT +int mailpop3_quit(mailpop3 * f); + +LIBETPAN_EXPORT +int mailpop3_apop(mailpop3 * f, const char * user, const char * password); + +LIBETPAN_EXPORT +int mailpop3_user(mailpop3 * f, const char * user); + +LIBETPAN_EXPORT +int mailpop3_pass(mailpop3 * f, const char * password); + +LIBETPAN_EXPORT +int mailpop3_list(mailpop3 * f, carray ** result); + +LIBETPAN_EXPORT +int mailpop3_retr(mailpop3 * f, unsigned int indx, char ** result, + size_t * result_len); + +LIBETPAN_EXPORT +int mailpop3_top(mailpop3 * f, unsigned int indx, + unsigned int count, char ** result, + size_t * result_len); + +LIBETPAN_EXPORT +int mailpop3_dele(mailpop3 * f, unsigned int indx); + +LIBETPAN_EXPORT +int mailpop3_noop(mailpop3 * f); + +LIBETPAN_EXPORT +int mailpop3_rset(mailpop3 * f); + +LIBETPAN_EXPORT +void mailpop3_top_free(char * str); + +LIBETPAN_EXPORT +void mailpop3_retr_free(char * str); + +LIBETPAN_EXPORT +int mailpop3_get_msg_info(mailpop3 * f, unsigned int indx, + struct mailpop3_msg_info ** result); + +LIBETPAN_EXPORT +int mailpop3_capa(mailpop3 * f, clist ** result); + +LIBETPAN_EXPORT +void mailpop3_capa_resp_free(clist * capa_list); + +LIBETPAN_EXPORT +int mailpop3_stat(mailpop3 * f, struct mailpop3_stat_response ** result); + +LIBETPAN_EXPORT +void mailpop3_stat_resp_free(struct mailpop3_stat_response * stat_result); + +LIBETPAN_EXPORT +int mailpop3_stls(mailpop3 * f); + +LIBETPAN_EXPORT +int mailpop3_auth(mailpop3 * f, const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); + +LIBETPAN_EXPORT +void mailpop3_set_logger(mailpop3 * session, void (* logger)(mailpop3 * session, int log_type, + const char * str, size_t size, void * context), void * logger_context); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/pop3/mailpop3_helper.c b/Sources/libetpan/low-level/pop3/mailpop3_helper.c new file mode 100644 index 00000000..d0d544de --- /dev/null +++ b/Sources/libetpan/low-level/pop3/mailpop3_helper.c @@ -0,0 +1,83 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailpop3_helper.c,v 1.11 2008/02/20 22:15:53 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailpop3_helper.h" + +#include + +int mailpop3_login_apop(mailpop3 * f, + const char * user, + const char * password) +{ + return mailpop3_apop(f, user, password); +} + + +/* + mailpop3_login + + log on to pop3 server using USER and PASS commands + must be used immediately after connect +*/ + +int mailpop3_login(mailpop3 * f, + const char * user, + const char * password) +{ + int r; + + if ((r = mailpop3_user(f, user)) != MAILPOP3_NO_ERROR) + return r; + + if ((r = mailpop3_pass(f, password)) != MAILPOP3_NO_ERROR) + return r; + + return MAILPOP3_NO_ERROR; +} + +void mailpop3_header_free(char * str) +{ + mailpop3_top_free(str); +} + +int mailpop3_header(mailpop3 * f, uint32_t indx, char ** result, + size_t * result_len) +{ + return mailpop3_top(f, indx, 0, result, result_len); +} diff --git a/Sources/libetpan/low-level/pop3/mailpop3_helper.h b/Sources/libetpan/low-level/pop3/mailpop3_helper.h new file mode 100644 index 00000000..d278bc1a --- /dev/null +++ b/Sources/libetpan/low-level/pop3/mailpop3_helper.h @@ -0,0 +1,64 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailpop3_helper.h,v 1.9 2008/02/20 22:15:53 hoa Exp $ + */ + +#ifndef MAILPOP3_HELPER_H + +#define MAILPOP3_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailpop3.h" + +int mailpop3_login_apop(mailpop3 * f, + const char * user, + const char * password); + +int mailpop3_login(mailpop3 * f, + const char * user, + const char * password); + +int mailpop3_header(mailpop3 * f, uint32_t indx, char ** result, + size_t * result_len); + +void mailpop3_header_free(char * str); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Sources/libetpan/low-level/pop3/mailpop3_socket.c b/Sources/libetpan/low-level/pop3/mailpop3_socket.c new file mode 100644 index 00000000..ac828ef1 --- /dev/null +++ b/Sources/libetpan/low-level/pop3/mailpop3_socket.c @@ -0,0 +1,179 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailpop3_socket.c,v 1.16 2009/12/19 00:57:31 hoa Exp $ + */ +#define HAVE_CONFIG_H 1 + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailpop3_socket.h" + +#include "mailpop3.h" +#include "mailstream_cfstream.h" + +#include "connect.h" +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif +#include + +#define DEFAULT_POP3_PORT 110 +#define SERVICE_NAME_POP3 "pop3" +#define SERVICE_TYPE_TCP "tcp" + +#if HAVE_CFNETWORK +static int mailpop3_cfsocket_connect(mailpop3 * f, const char * server, uint16_t port); +#endif + +int mailpop3_socket_connect(mailpop3 * f, const char * server, uint16_t port) +{ + int s; + mailstream * stream; + +#if HAVE_CFNETWORK + if (mailstream_cfstream_enabled) { + return mailpop3_cfsocket_connect(f, server, port); + } +#endif + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_POP3, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_POP3_PORT; + } + + /* Connection */ + + s = mail_tcp_connect_timeout(server, port, f->pop3_timeout); + if (s == -1) + return MAILPOP3_ERROR_CONNECTION_REFUSED; + + stream = mailstream_socket_open_timeout(s, f->pop3_timeout); + if (stream == NULL) { +#ifdef WIN32 + closesocket(s); +#else + close(s); +#endif + return MAILPOP3_ERROR_MEMORY; + } + + return mailpop3_connect(f, stream); +} + +static int mailpop3_cfsocket_starttls(mailpop3 * f); + +LIBETPAN_EXPORT +int mailpop3_socket_starttls(mailpop3 * f) +{ + return mailpop3_socket_starttls_with_callback(f, NULL, NULL); +} + +LIBETPAN_EXPORT +int mailpop3_socket_starttls_with_callback(mailpop3 * f, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data) +{ + int r; + int fd; + mailstream_low * low; + mailstream_low * new_low; + + low = mailstream_get_low(f->pop3_stream); + if (low->driver == mailstream_cfstream_driver) { + // won't use callback + return mailpop3_cfsocket_starttls(f); + } + + r = mailpop3_stls(f); + + switch (r) { + case MAILPOP3_NO_ERROR: + break; + default: + return r; + } + + fd = mailstream_low_get_fd(low); + if (fd == -1) + return MAILPOP3_ERROR_STREAM; + + new_low = mailstream_low_tls_open_with_callback_timeout(fd, + f->pop3_timeout, callback, data); + if (new_low == NULL) + return MAILPOP3_ERROR_SSL; + + mailstream_low_free(low); + mailstream_set_low(f->pop3_stream, new_low); + + return MAILPOP3_NO_ERROR; +} + +#if HAVE_CFNETWORK +static int mailpop3_cfsocket_connect(mailpop3 * f, const char * server, uint16_t port) +{ + mailstream * stream; + + stream = mailstream_cfstream_open_timeout(server, port, f->pop3_timeout); + if (stream == NULL) { + return MAILPOP3_ERROR_CONNECTION_REFUSED; + } + + return mailpop3_connect(f, stream); +} +#endif + +static int mailpop3_cfsocket_starttls(mailpop3 * f) +{ + int r; + + r = mailpop3_stls(f); + switch (r) { + case MAILPOP3_NO_ERROR: + break; + default: + return r; + } + + mailstream_cfstream_set_ssl_verification_mask(f->pop3_stream, MAILSTREAM_CFSTREAM_SSL_NO_VERIFICATION); + r = mailstream_cfstream_set_ssl_enabled(f->pop3_stream, 1); + if (r < 0) { + return MAILPOP3_ERROR_SSL; + } + + return MAILPOP3_NO_ERROR; +} diff --git a/Sources/libetpan/low-level/pop3/mailpop3_socket.h b/Sources/libetpan/low-level/pop3/mailpop3_socket.h new file mode 100644 index 00000000..1aba8f17 --- /dev/null +++ b/Sources/libetpan/low-level/pop3/mailpop3_socket.h @@ -0,0 +1,64 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailpop3_socket.h,v 1.16 2006/12/26 13:13:24 hoa Exp $ + */ + +#ifndef MAILPOP3_SOCKET_H + +#define MAILPOP3_SOCKET_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_INTTYPES_H +# include +#endif + +#include + +LIBETPAN_EXPORT +int mailpop3_socket_connect(mailpop3 * f, const char * server, uint16_t port); + +LIBETPAN_EXPORT +int mailpop3_socket_starttls(mailpop3 * f); + +LIBETPAN_EXPORT +int mailpop3_socket_starttls_with_callback(mailpop3 * f, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/pop3/mailpop3_ssl.c b/Sources/libetpan/low-level/pop3/mailpop3_ssl.c new file mode 100644 index 00000000..de14af51 --- /dev/null +++ b/Sources/libetpan/low-level/pop3/mailpop3_ssl.c @@ -0,0 +1,133 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailpop3_ssl.c,v 1.17 2009/12/19 00:57:31 hoa Exp $ + */ +#define HAVE_CONFIG_H 1 + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailpop3_ssl.h" + +#include "mailpop3.h" +#include "mailstream_cfstream.h" + +#include "connect.h" +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif +#include + +#define DEFAULT_POP3S_PORT 995 +#define SERVICE_NAME_POP3S "pop3s" +#define SERVICE_TYPE_TCP "tcp" + +#if HAVE_CFNETWORK +static int mailpop3_cfssl_connect(mailpop3 * f, const char * server, uint16_t port); +#endif + +int mailpop3_ssl_connect(mailpop3 * f, const char * server, uint16_t port) +{ + return mailpop3_ssl_connect_with_callback(f, server, port, + NULL, NULL); +} + +int mailpop3_ssl_connect_with_callback(mailpop3 * f, const char * server, uint16_t port, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data) +{ + int s; + mailstream * stream; + +#if HAVE_CFNETWORK + if (mailstream_cfstream_enabled) { + if (callback == NULL) { + return mailpop3_cfssl_connect(f, server, port); + } + } +#endif + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_POP3S, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_POP3S_PORT; + } + + /* Connection */ + + s = mail_tcp_connect_timeout(server, port, f->pop3_timeout); + if (s == -1) + return MAILPOP3_ERROR_CONNECTION_REFUSED; + + stream = mailstream_ssl_open_with_callback_timeout(s, f->pop3_timeout, callback, data); + if (stream == NULL) { +#ifdef WIN32 + closesocket(s); +#else + close(s); +#endif + return MAILPOP3_ERROR_SSL; + } + + return mailpop3_connect(f, stream); +} + +#if HAVE_CFNETWORK +static int mailpop3_cfssl_connect_ssl_level(mailpop3 * f, const char * server, uint16_t port, int ssl_level) +{ + mailstream * stream; + int r; + + stream = mailstream_cfstream_open_timeout(server, port, f->pop3_timeout); + if (stream == NULL) { + return MAILPOP3_ERROR_CONNECTION_REFUSED; + } + mailstream_cfstream_set_ssl_level(stream, ssl_level); + mailstream_cfstream_set_ssl_verification_mask(stream, MAILSTREAM_CFSTREAM_SSL_NO_VERIFICATION); + r = mailstream_cfstream_set_ssl_enabled(stream, 1); + if (r < 0) { + mailstream_close(stream); + return MAILPOP3_ERROR_SSL; + } + + return mailpop3_connect(f, stream); +} + +static int mailpop3_cfssl_connect(mailpop3 * f, const char * server, uint16_t port) +{ + return mailpop3_cfssl_connect_ssl_level(f, server, port, MAILSTREAM_CFSTREAM_SSL_LEVEL_NEGOCIATED_SSL); +} +#endif diff --git a/Sources/libetpan/low-level/pop3/mailpop3_ssl.h b/Sources/libetpan/low-level/pop3/mailpop3_ssl.h new file mode 100644 index 00000000..d399a799 --- /dev/null +++ b/Sources/libetpan/low-level/pop3/mailpop3_ssl.h @@ -0,0 +1,61 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailpop3_ssl.h,v 1.17 2006/12/26 13:13:24 hoa Exp $ + */ + +#ifndef MAILPOP3_SSL_H + +#define MAILPOP3_SSL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_INTTYPES_H +# include +#endif + +#include + +LIBETPAN_EXPORT +int mailpop3_ssl_connect(mailpop3 * f, const char * server, uint16_t port); + +LIBETPAN_EXPORT +int mailpop3_ssl_connect_with_callback(mailpop3 * f, const char * server, uint16_t port, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/pop3/mailpop3_types.h b/Sources/libetpan/low-level/pop3/mailpop3_types.h new file mode 100644 index 00000000..cbcbd553 --- /dev/null +++ b/Sources/libetpan/low-level/pop3/mailpop3_types.h @@ -0,0 +1,131 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailpop3_types.h,v 1.19 2006/12/13 18:31:33 hoa Exp $ + */ + +#ifndef MAILPOP3_TYPES_H + +#define MAILPOP3_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include + +enum { + MAILPOP3_NO_ERROR = 0, + MAILPOP3_ERROR_BAD_STATE, + MAILPOP3_ERROR_UNAUTHORIZED, + MAILPOP3_ERROR_STREAM, + MAILPOP3_ERROR_DENIED, + MAILPOP3_ERROR_BAD_USER, + MAILPOP3_ERROR_BAD_PASSWORD, + MAILPOP3_ERROR_CANT_LIST, + MAILPOP3_ERROR_NO_SUCH_MESSAGE, + MAILPOP3_ERROR_MEMORY, + MAILPOP3_ERROR_CONNECTION_REFUSED, + MAILPOP3_ERROR_APOP_NOT_SUPPORTED, + MAILPOP3_ERROR_CAPA_NOT_SUPPORTED, + MAILPOP3_ERROR_STLS_NOT_SUPPORTED, + MAILPOP3_ERROR_SSL, + MAILPOP3_ERROR_QUIT_FAILED +}; + +typedef struct mailpop3 mailpop3; + +struct mailpop3 +{ + char * pop3_response; /* response message */ + char * pop3_timestamp; /* connection timestamp */ + + /* internals */ + mailstream * pop3_stream; + size_t pop3_progr_rate; + progress_function * pop3_progr_fun; + + MMAPString * pop3_stream_buffer; /* buffer for lines reading */ + MMAPString * pop3_response_buffer; /* buffer for responses */ + + carray * pop3_msg_tab; /* list of pop3_msg_info structures */ + int pop3_state; /* state */ + + unsigned int pop3_deleted_count; + + struct { + void * sasl_conn; + const char * sasl_server_fqdn; + const char * sasl_login; + const char * sasl_auth_name; + const char * sasl_password; + const char * sasl_realm; + void * sasl_secret; + } pop3_sasl; + + time_t pop3_timeout; + mailprogress_function * pop3_progress_fun; + void * pop3_progress_context; + + void (* pop3_logger)(mailpop3 * session, int log_type, const char * str, size_t size, void * context); + void * pop3_logger_context; +}; + +struct mailpop3_msg_info +{ + unsigned int msg_index; + uint32_t msg_size; + char * msg_uidl; + int msg_deleted; +}; + + +struct mailpop3_capa { + char * cap_name; + clist * cap_param; /* (char *) */ +}; + + +struct mailpop3_stat_response { + unsigned int msgs_count; + size_t msgs_size; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/smtp/Makefile.am b/Sources/libetpan/low-level/smtp/Makefile.am new file mode 100644 index 00000000..78219753 --- /dev/null +++ b/Sources/libetpan/low-level/smtp/Makefile.am @@ -0,0 +1,49 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +EXTRA_DIST = TODO + +etpaninclude_HEADERS = \ + mailsmtp.h mailsmtp_helper.h mailsmtp_socket.h mailsmtp_ssl.h \ + mailsmtp_types.h mailsmtp_oauth2.h + +AM_CPPFLAGS = -I$(top_builddir)/include \ + -I$(top_srcdir)/src/data-types + +noinst_LTLIBRARIES = libsmtp.la + +libsmtp_la_SOURCES = \ + mailsmtp.h mailsmtp.c \ + mailsmtp_helper.h mailsmtp_helper.c \ + mailsmtp_socket.h mailsmtp_socket.c \ + mailsmtp_ssl.h mailsmtp_ssl.c \ + mailsmtp_oauth2.h mailsmtp_oauth2.c \ + mailsmtp_private.h diff --git a/Sources/libetpan/low-level/smtp/TODO b/Sources/libetpan/low-level/smtp/TODO new file mode 100644 index 00000000..96f44c69 --- /dev/null +++ b/Sources/libetpan/low-level/smtp/TODO @@ -0,0 +1 @@ +- STARTTLS diff --git a/Sources/libetpan/low-level/smtp/mailsmtp.c b/Sources/libetpan/low-level/smtp/mailsmtp.c new file mode 100644 index 00000000..6a952fce --- /dev/null +++ b/Sources/libetpan/low-level/smtp/mailsmtp.c @@ -0,0 +1,1654 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa, + * All rights reserved. + * + * SMTP AUTH support by Juergen Graf + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsmtp.c,v 1.44 2011/06/21 11:55:47 hoa Exp $ + */ +#define HAVE_CONFIG_H 1 + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailsmtp.h" +#include "mailsmtp_private.h" +#include "connect.h" +#include "base64.h" +#include "mail.h" + +#ifdef HAVE_SYS_SOCKET_H +# include +#endif + +#ifdef HAVE_STRING_H +# include +#endif + +#ifdef WIN32 +# include "win_etpan.h" +#else +# include +# include +#endif + +#ifdef HAVE_NETINET_IN_H +# include +#endif +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include + +#ifdef USE_SASL +#include +#include +#endif + +#include "mailsasl.h" + +/* + RFC 2821 : SMTP + RFC 1891 : SMTP Service Extension for Delivery Status Notifications + + RFC 1428 : Transition of Internet Mail from Just-Send-8 to 8bit-SMTP/MIME + RFC 1652 : SMTP Service Extension for 8bit-MIMEtransport + RFC 1845 : SMTP Service Extension for Checkpoint/Restart + RFC 1846 : SMTP 521 Reply Code + RFC 1870 : SMTP Service Extension for Message Size Declaration + RFC 1985 : SMTP Service Extension for Remote Message Queue Starting + RFC 2034 : SMTP Service Extension for Returning Enhanced Error Codes + RFC 2442 : The Batch SMTP Media Type + RFC 2487 : SMTP Service Extension for Secure SMTP over TLS + RFC 2505 : Anti-Spam Recommendations for SMTP MTAs + RFC 2554 : SMTP Service Extension for Authentication + RFC 2645 : ON-DEMAND MAIL RELAY (ODMR) SMTP with Dynamic IP Addresses + RFC 2852 : Deliver By SMTP Service Extension + RFC 2920 : SMTP Service Extension for Command Pipelining + RFC 3030 : SMTP Service Extensions for Transmission of Large and Binary MIME + Messages +*/ + +static inline void smtp_logger(mailstream * s, int log_type, + const char * str, size_t size, void * context); + +#define SMTP_STATUS_CONTINUE 0x1000 + +mailsmtp * mailsmtp_new(size_t progr_rate, + progress_function * progr_fun) +{ + mailsmtp * session; + + session = malloc(sizeof(* session)); + if (session == NULL) + goto err; + + session->stream = NULL; + + session->progr_rate = progr_rate; + session->progr_fun = progr_fun; + + session->response = NULL; + session->response_code = 0; + + session->line_buffer = mmap_string_new(""); + if (session->line_buffer == NULL) + goto free_session; + + session->response_buffer = mmap_string_new(""); + if (session->response_buffer == NULL) + goto free_line_buffer; + + session->esmtp = 0; + session->auth = MAILSMTP_AUTH_NOT_CHECKED; + + session->smtp_sasl.sasl_conn = NULL; + + session->smtp_max_msg_size = 0; + session->smtp_progress_fun = NULL; + session->smtp_progress_context = NULL; + + session->smtp_timeout = 0; + + session->smtp_logger = NULL; + session->smtp_logger_context = NULL; + + return session; + + free_line_buffer: + mmap_string_free(session->line_buffer); + free_session: + free(session); + err: + return NULL; +} + +void mailsmtp_free(mailsmtp * session) +{ +#ifdef USE_SASL + if (session->smtp_sasl.sasl_conn != NULL) { + sasl_dispose((sasl_conn_t **) &session->smtp_sasl.sasl_conn); + mailsasl_unref(); + } +#endif + + if (session->stream) + mailsmtp_quit(session); + + mmap_string_free(session->line_buffer); + mmap_string_free(session->response_buffer); + free(session); +} + +static int send_command(mailsmtp * f, char * command); +static int send_command_private(mailsmtp * f, char * command, int can_be_published); + +static int read_response(mailsmtp * session); + +static int get_hostname(mailsmtp * session, int useip, char * buf, int len); + +/* smtp operations */ + +int mailsmtp_connect(mailsmtp * session, mailstream * s) +{ + int code; + + session->stream = s; + mailstream_set_logger(s, smtp_logger, session); + + code = read_response(session); + + switch (code) { + case 220: + return MAILSMTP_NO_ERROR; + + case 554: + session->stream = NULL; + mailstream_close(s); + return MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE; + + case 0: + session->stream = NULL; + mailstream_close(s); + return MAILSMTP_ERROR_STREAM; + + default: + session->stream = NULL; + mailstream_close(s); + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + + +#define SMTP_STRING_SIZE 513 + +static int send_quit(mailsmtp * session) +{ + char command[SMTP_STRING_SIZE]; + int r; + + snprintf(command, SMTP_STRING_SIZE, "QUIT\r\n"); + r = send_command(session, command); + if (r == -1) { + return MAILSMTP_ERROR_STREAM; + } + + return MAILSMTP_NO_ERROR; +} + +int mailsmtp_quit(mailsmtp * session) +{ + int r; + int res; + + if (session->stream == NULL) + return MAILSMTP_NO_ERROR; + + r = send_quit(session); + if (r != MAILSMTP_NO_ERROR) { + res = r; + goto close; + } + + res = MAILSMTP_NO_ERROR; + + close: + mailstream_close(session->stream); + session->stream = NULL; + + return res; +} + + +#define HOSTNAME_SIZE 256 + +static int get_hostname(mailsmtp * session, int useip, char * buf, int len) +{ + int r; + char hostname[HOSTNAME_SIZE]; + struct sockaddr addr; + socklen_t addr_len = sizeof(addr); + int socket = -1; + + if (!useip) { + r = gethostname(hostname, HOSTNAME_SIZE); + if (r != 0) + return MAILSMTP_ERROR_HOSTNAME; + + if (snprintf(buf, len, "%s", hostname) >= len) + return MAILSMTP_ERROR_HOSTNAME; + } else { + socket = mailstream_low_get_fd(mailstream_get_low(session->stream)); + if (socket < 0) + return MAILSMTP_ERROR_HOSTNAME; + + r = getsockname(socket, &addr, &addr_len ); + if (r != 0) + return MAILSMTP_ERROR_HOSTNAME; + +#if (defined __linux__ || defined WIN32 || defined __sun) + r = getnameinfo(&addr, sizeof(addr), hostname, HOSTNAME_SIZE, NULL, 0, NI_NUMERICHOST); +#else + r = getnameinfo(&addr, addr.sa_len, hostname, HOSTNAME_SIZE, NULL, 0, NI_NUMERICHOST); +#endif + if (r != 0) + return MAILSMTP_ERROR_HOSTNAME; + + if (snprintf(buf, len, "[%s]", hostname) >= len) + return MAILSMTP_ERROR_HOSTNAME; + } + return MAILSMTP_NO_ERROR; +} + + +int mailsmtp_helo(mailsmtp * session) +{ + return mailsmtp_helo_with_ip(session, 0); +} + +int mailsmtp_helo_with_ip(mailsmtp * session, int useip) +{ + int r; + char hostname[HOSTNAME_SIZE]; + char command[SMTP_STRING_SIZE]; + + r = get_hostname(session, useip, hostname, HOSTNAME_SIZE); + if (r != MAILSMTP_NO_ERROR) + return r; + + snprintf(command, SMTP_STRING_SIZE, "HELO %s\r\n", hostname); + r = send_command(session, command); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + + switch (r) { + case 250: + session->esmtp = 0; + session->auth = MAILSMTP_AUTH_NOT_CHECKED; + return MAILSMTP_NO_ERROR; + + case 504: + return MAILSMTP_ERROR_NOT_IMPLEMENTED; + + case 550: + return MAILSMTP_ERROR_ACTION_NOT_TAKEN; + + case 0: + return MAILSMTP_ERROR_STREAM; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +int mailsmtp_mail(mailsmtp * session, const char * from) +{ + int r; + char command[SMTP_STRING_SIZE]; + + snprintf(command, SMTP_STRING_SIZE, "MAIL FROM:<%s>\r\n", from); + r = send_command(session, command); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + + switch (r) { + case 250: + return MAILSMTP_NO_ERROR; + + case 552: + return MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION; + + case 451: + return MAILSMTP_ERROR_IN_PROCESSING; + + case 452: + return MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE; + + case 550: + return MAILSMTP_ERROR_MAILBOX_UNAVAILABLE; + + case 553: + return MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED; + + case 503: + return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND; + + case 0: + return MAILSMTP_ERROR_STREAM; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +int mailsmtp_rcpt(mailsmtp * session, const char * to) +{ + return mailesmtp_rcpt(session, to, 0, NULL); +} + +int mailsmtp_data(mailsmtp * session) +{ + int r; + char command[SMTP_STRING_SIZE]; + + snprintf(command, SMTP_STRING_SIZE, "DATA\r\n"); + r = send_command(session, command); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + + switch (r) { + case 354: + return MAILSMTP_NO_ERROR; + + case 451: + return MAILSMTP_ERROR_IN_PROCESSING; + + case 554: + return MAILSMTP_ERROR_TRANSACTION_FAILED; + + case 503: + return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND; + + case 0: + return MAILSMTP_ERROR_STREAM; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +static int send_data(mailsmtp * session, const char * message, size_t size); + +int mailsmtp_data_message(mailsmtp * session, + const char * message, + size_t size) +{ + int r; + + r = send_data(session, message, size); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + + r = read_response(session); + + switch(r) { + case 250: + return MAILSMTP_NO_ERROR; + + case 552: + return MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION; + + case 554: + return MAILSMTP_ERROR_TRANSACTION_FAILED; + + case 451: + return MAILSMTP_ERROR_IN_PROCESSING; + + case 452: + return MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE; + + case 0: + return MAILSMTP_ERROR_STREAM; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +int mailsmtp_status(int smtpstatus) +{ + switch(smtpstatus) { + case 250: + return MAILSMTP_NO_ERROR; + + case 552: + return MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION; + + case 554: + return MAILSMTP_ERROR_TRANSACTION_FAILED; + + case 451: + return MAILSMTP_ERROR_IN_PROCESSING; + + case 452: + return MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE; + + case 0: + return MAILSMTP_ERROR_STREAM; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } + +} + +/* lmtp data command + * on the end of data transaction lmtp returns a status for + * every recipient it delivered. + * recipient_list holds the rcpts from smtp_rcpt() + * the last error is returned to the caller + * if retcodes is not NULL, the individual rcpt-stati are stored there + * */ +int maillmtp_data_message(mailsmtp * session, + const char * message, + size_t size, + clist * recipient_list, + int * retcodes) +{ + int r, ret = MAILSMTP_NO_ERROR; + unsigned int i = 0; + clistiter *iter; + + r = send_data(session, message, size); + + if (r == -1) + return MAILSMTP_ERROR_STREAM; + + for (iter = clist_begin(recipient_list); iter; iter = clist_next(iter)) { + r = read_response(session); + if (MAILSMTP_NO_ERROR != mailsmtp_status(r)) + ret = mailsmtp_status(r); + if (retcodes) + retcodes[i++] = r; + } + return ret; +} + +int mailsmtp_data_message_quit(mailsmtp * session, + const char * message, + size_t size) +{ + int r = mailsmtp_data_message_quit_no_disconnect(session, message, size); + + mailstream_close(session->stream); + session->stream = NULL; + + return r; +} + +int mailsmtp_data_message_quit_no_disconnect(mailsmtp * session, + const char * message, + size_t size) +{ + int r; + + r = send_data(session, message, size); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + + r = send_quit(session); + if (r != MAILSMTP_NO_ERROR) + return r; + + r = read_response(session); + + switch(r) { + case 250: + return MAILSMTP_NO_ERROR; + + case 552: + return MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION; + + case 554: + return MAILSMTP_ERROR_TRANSACTION_FAILED; + + case 451: + return MAILSMTP_ERROR_IN_PROCESSING; + + case 452: + return MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE; + + case 0: + return MAILSMTP_ERROR_STREAM; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +/* esmtp operations */ + + +/** + * called during mailesmtp_ehlo + * checks EHLO answer for server extensions and sets flags + * in session->esmtp + * checks AUTH methods in session->response and sets flags + * in session->auth + */ +#define isdelim(x) ((x) == ' ' || (x) == '\r' || (x) == '\n' || (x) == '\0' || (x) == '\t') + +int mailesmtp_parse_ehlo(mailsmtp * session) +{ + char * response; + + /* restore data */ + session->esmtp = MAILSMTP_ESMTP; + session->auth = MAILSMTP_AUTH_CHECKED; + + response = session->response; + + /* ESMTP supported extensions : + DSN + EXPN + 8BITMIME + SIZE [] + ETRN + STARTTLS + AUTH + */ + while (response != NULL) { + if (!strncasecmp(response, "EXPN", 4) && isdelim(response[4])) { + session->esmtp |= MAILSMTP_ESMTP_EXPN; + } + else if (!strncasecmp(response, "ETRN", 4) && isdelim(response[4])) { + session->esmtp |= MAILSMTP_ESMTP_ETRN; + } + else if (!strncasecmp(response, "DSN", 3) && isdelim(response[3])) { + session->esmtp |= MAILSMTP_ESMTP_DSN; + } + else if (!strncasecmp(response, "8BITMIME", 8) && isdelim(response[8])) { + session->esmtp |= MAILSMTP_ESMTP_8BITMIME; + } + else if (!strncasecmp(response, "STARTTLS", 8) && isdelim(response[8])) { + session->esmtp |= MAILSMTP_ESMTP_STARTTLS; + } + else if (!strncasecmp(response, "SIZE", 4) && isdelim(response[4])) { + session->esmtp |= MAILSMTP_ESMTP_SIZE; + if ((response[4] == ' ') || (response[4] == '\t')) { + session->smtp_max_msg_size = strtoul(response + 4, NULL, 10); + } + /* TODO: grab optionnal max size */ + } + else if (!strncasecmp(response, "CLIENTID", 8) && isdelim(response[8])) { + session->esmtp |= MAILSMTP_ESMTP_CLIENTID; + } + else if (!strncasecmp(response, "PIPELINING", 10) && isdelim(response[10])) { + session->esmtp |= MAILSMTP_ESMTP_PIPELINING; + } + else if (!strncasecmp(response, "AUTH ", 5)) { + response += 5; /* remove "AUTH " */ + while (response[0] != '\n' && response[0] != '\0') { + while (response[0] == ' ') response++; + if (strncasecmp(response, "LOGIN", 5) == 0) { + session->auth |= MAILSMTP_AUTH_LOGIN; + response += 5; + } else if (strncasecmp(response, "CRAM-MD5", 8) == 0) { + session->auth |= MAILSMTP_AUTH_CRAM_MD5; + response += 8; + } else if (strncasecmp(response, "PLAIN", 5) == 0) { + session->auth |= MAILSMTP_AUTH_PLAIN; + response += 5; + } else if (strncasecmp(response, "DIGEST-MD5", 10) == 0) { + session->auth |= MAILSMTP_AUTH_DIGEST_MD5; + response += 10; + } else if (strncasecmp(response, "GSSAPI", 6) == 0) { + session->auth |= MAILSMTP_AUTH_GSSAPI; + response += 6; + } else if (strncasecmp(response, "SRP", 3) == 0) { + session->auth |= MAILSMTP_AUTH_SRP; + response += 3; + } else if (strncasecmp(response, "NTLM", 4) == 0) { + session->auth |= MAILSMTP_AUTH_NTLM; + response += 4; + } else if (strncasecmp(response, "KERBEROS_V4", 11) == 0) { + session->auth |= MAILSMTP_AUTH_KERBEROS_V4; + response += 11; + } else { + /* unknown auth method - jump to next word or eol */ + while (!isdelim(response[0]) || response[0] == '\r') + response++; + } + } + } + // for broken servers + else if (!strncasecmp(response, "AUTH=", 5)) { + response += 5; /* remove "AUTH=" */ + while (response[0] != '\n' && response[0] != '\0') { + while (response[0] == ' ') response++; + if (strncasecmp(response, "LOGIN", 5) == 0) { + session->auth |= MAILSMTP_AUTH_LOGIN; + response += 5; + } else if (strncasecmp(response, "CRAM-MD5", 8) == 0) { + session->auth |= MAILSMTP_AUTH_CRAM_MD5; + response += 8; + } else if (strncasecmp(response, "PLAIN", 5) == 0) { + session->auth |= MAILSMTP_AUTH_PLAIN; + response += 5; + } else if (strncasecmp(response, "DIGEST-MD5", 10) == 0) { + session->auth |= MAILSMTP_AUTH_DIGEST_MD5; + response += 10; + } else if (strncasecmp(response, "GSSAPI", 6) == 0) { + session->auth |= MAILSMTP_AUTH_GSSAPI; + response += 6; + } else if (strncasecmp(response, "SRP", 3) == 0) { + session->auth |= MAILSMTP_AUTH_SRP; + response += 3; + } else if (strncasecmp(response, "NTLM", 4) == 0) { + session->auth |= MAILSMTP_AUTH_NTLM; + response += 4; + } else if (strncasecmp(response, "KERBEROS_V4", 11) == 0) { + session->auth |= MAILSMTP_AUTH_KERBEROS_V4; + response += 11; + } else { + /* unknown auth method - jump to next word or eol */ + while (!isdelim(response[0]) || response[0] == '\r') + response++; + } + } + } + response = strpbrk(response, "\n"); + if (response != NULL) + response++; + } + + return MAILSMTP_NO_ERROR; +} + + +int mailesmtp_ehlo(mailsmtp * session) +{ + return mailesmtp_ehlo_with_ip(session, 0); +} + +int mailesmtp_ehlo_with_ip(mailsmtp * session, int useip) +{ + int r; + char hostname[HOSTNAME_SIZE]; + char command[SMTP_STRING_SIZE]; + + r = get_hostname(session, useip, hostname, HOSTNAME_SIZE); + if (r != MAILSMTP_NO_ERROR) + return r; + + snprintf(command, SMTP_STRING_SIZE, "EHLO %s\r\n", hostname); + r = send_command(session, command); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + + switch (r) { + case 250: + return mailesmtp_parse_ehlo(session); + + case 504: + return MAILSMTP_ERROR_NOT_IMPLEMENTED; + + case 550: + return MAILSMTP_ERROR_ACTION_NOT_TAKEN; + + case 0: + return MAILSMTP_ERROR_STREAM; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +/* lmtp processing */ +int mailesmtp_lhlo(mailsmtp * session , const char *hostname) +{ + int r; + char command[SMTP_STRING_SIZE]; + + if (!hostname) + hostname = "localhost"; + + snprintf(command, SMTP_STRING_SIZE, "LHLO %s\r\n", hostname); + r = send_command(session, command); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + + switch (r) { + case 250: + return mailesmtp_parse_ehlo(session); + + case 504: + return MAILSMTP_ERROR_NOT_IMPLEMENTED; + + case 550: + return MAILSMTP_ERROR_ACTION_NOT_TAKEN; + + case 0: + return MAILSMTP_ERROR_STREAM; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +/* + if return_full is TRUE, the entire message is returned on error + envid can be NULL +*/ + +int mailesmtp_mail(mailsmtp * session, + const char * from, + int return_full, + const char * envid) +{ + return mailesmtp_mail_size(session, from, return_full, envid, 0); +} + +int mailesmtp_mail_size(mailsmtp * session, + const char * from, + int return_full, + const char * envid, size_t size) +{ + int r; + char command[SMTP_STRING_SIZE]; + char ret_param[SMTP_STRING_SIZE]; + char envid_param[SMTP_STRING_SIZE]; + char size_param[SMTP_STRING_SIZE]; + + ret_param[0] = 0; + envid_param[0] = 0; + size_param[0] = 0; + if (session->esmtp & MAILSMTP_ESMTP_DSN) { + snprintf(ret_param, SMTP_STRING_SIZE, " RET=%s", return_full ? "FULL" : "HDRS"); + if (envid != NULL) { + snprintf(envid_param, SMTP_STRING_SIZE, " ENVID=%s", envid); + } + } + if (((session->esmtp & MAILSMTP_ESMTP_SIZE) != 0) && (size != 0)) { + snprintf(size_param, SMTP_STRING_SIZE, " SIZE=%lu", (unsigned long) size); + } + snprintf(command, SMTP_STRING_SIZE, "MAIL FROM:<%s>%s%s%s\r\n", + from, ret_param, envid_param, size_param); + + r = send_command(session, command); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + + switch (r) { + case 250: + return MAILSMTP_NO_ERROR; + + case 552: + return MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION; + + case 451: + return MAILSMTP_ERROR_IN_PROCESSING; + + case 452: + return MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE; + + case 550: + return MAILSMTP_ERROR_MAILBOX_UNAVAILABLE; + + case 553: + return MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED; + + case 503: + return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND; + + case 0: + return MAILSMTP_ERROR_STREAM; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +int mailesmtp_rcpt(mailsmtp * session, + const char * to, + int notify, + const char * orcpt) +{ + int r; + char command[SMTP_STRING_SIZE]; + char notify_str[30] = ""; + char notify_info_str[30] = ""; + + if (notify != 0 && session->esmtp & MAILSMTP_ESMTP_DSN) { + if (notify & MAILSMTP_DSN_NOTIFY_SUCCESS) + strcat(notify_info_str, ",SUCCESS"); + if (notify & MAILSMTP_DSN_NOTIFY_FAILURE) + strcat(notify_info_str, ",FAILURE"); + if (notify & MAILSMTP_DSN_NOTIFY_DELAY) + strcat(notify_info_str, ",DELAY"); + + if (notify & MAILSMTP_DSN_NOTIFY_NEVER) + strcpy(notify_info_str, ",NEVER"); + + notify_info_str[0] = '='; + + strcpy(notify_str, " NOTIFY"); + strcat(notify_str, notify_info_str); + } + + if (orcpt && session->esmtp & MAILSMTP_ESMTP_DSN) + snprintf(command, SMTP_STRING_SIZE, "RCPT TO:<%s>%s ORCPT=%s\r\n", + to, notify_str, orcpt); + else + snprintf(command, SMTP_STRING_SIZE, "RCPT TO:<%s>%s\r\n", to, notify_str); + + r = send_command(session, command); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + + switch (r) { + case 250: + return MAILSMTP_NO_ERROR; + + case 251: /* not local user, will be forwarded */ + return MAILSMTP_NO_ERROR; + + case 550: + case 450: + return MAILSMTP_ERROR_MAILBOX_UNAVAILABLE; + + case 551: + return MAILSMTP_ERROR_USER_NOT_LOCAL; + + case 552: + return MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION; + + case 553: + return MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED; + + case 451: + return MAILSMTP_ERROR_IN_PROCESSING; + + case 452: + return MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE; + + case 503: + return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND; + + case 0: + return MAILSMTP_ERROR_STREAM; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +int auth_map_errors(int err) +{ + switch (err) { + case 235: + return MAILSMTP_NO_ERROR; /* AUTH successfull */ + case 334: + return MAILSMTP_NO_ERROR; /* AUTH in progress */ + case 432: + return MAILSMTP_ERROR_AUTH_TRANSITION_NEEDED; + case 454: + return MAILSMTP_ERROR_AUTH_TEMPORARY_FAILTURE; + case 501: + return MAILSMTP_ERROR_AUTH_LOGIN; + case 503: + return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND; + case 504: + return MAILSMTP_ERROR_AUTH_NOT_SUPPORTED; + case 530: + return MAILSMTP_ERROR_AUTH_REQUIRED; + case 534: + return MAILSMTP_ERROR_AUTH_TOO_WEAK; + case 535: + return MAILSMTP_ERROR_AUTH_AUTHENTICATION_FAILED; + case 538: + return MAILSMTP_ERROR_AUTH_ENCRYPTION_REQUIRED; + case 553: + case 554: + return MAILSMTP_ERROR_AUTH_AUTHENTICATION_FAILED; + default: + if (err / 100 == 5) { + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } + else if (err / 100 == 4) { + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } + else { + /* opportunistic approach ;) */ + return MAILSMTP_NO_ERROR; + } + } +} + +#if 0 +static int mailsmtp_auth_login(mailsmtp * session, + const char * user, const char * pass) +{ + int err; + char command[SMTP_STRING_SIZE]; + char * user64, * pass64; + + user64 = NULL; + pass64 = NULL; + + user64 = encode_base64(user, strlen(user)); + if (user64 == NULL) { + err = MAILSMTP_ERROR_MEMORY; + goto err_free; + } + + pass64 = encode_base64(pass, strlen(pass)); + if (pass64 == NULL) { + err = MAILSMTP_ERROR_MEMORY; + goto err_free; + } + + snprintf(command, SMTP_STRING_SIZE, "%s\r\n", user64); + err = send_command(session, command); + if (err == -1) { + err = MAILSMTP_ERROR_STREAM; + goto err_free; + } + err = read_response(session); + err = auth_map_errors(err); + if (err != MAILSMTP_NO_ERROR) + goto err_free; + + snprintf(command, SMTP_STRING_SIZE, "%s\r\n", pass64); + err = send_command(session, command); + if (err == -1) { + err = MAILSMTP_ERROR_STREAM; + goto err_free; + } + err = read_response(session); + err = auth_map_errors(err); + + err_free: + free(user64); + free(pass64); + + return err; +} +#endif + +int mailsmtp_auth_type(mailsmtp * session, + const char * user, const char * pass, int type) +{ + int err; + char hostname[SMTP_STRING_SIZE]; + + err = gethostname(hostname, sizeof(hostname)); + if (err < 0) { + return MAILSMTP_ERROR_MEMORY; + } + + if (session->auth == MAILSMTP_AUTH_NOT_CHECKED) + return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND; + + if ( !(session->auth & type) ) return MAILSMTP_ERROR_AUTH_NOT_SUPPORTED; + + switch (type) { + case MAILSMTP_AUTH_LOGIN: + return mailesmtp_auth_sasl(session, "LOGIN", + hostname, NULL, NULL, user, user, pass, NULL); + + case MAILSMTP_AUTH_PLAIN: + return mailesmtp_auth_sasl(session, "PLAIN", + hostname, NULL, NULL, user, user, pass, NULL); + + case MAILSMTP_AUTH_CRAM_MD5: + return mailesmtp_auth_sasl(session, "CRAM-MD5", + hostname, NULL, NULL, user, user, pass, NULL); + + case MAILSMTP_AUTH_DIGEST_MD5: + return mailesmtp_auth_sasl(session, "DIGEST-MD5", + hostname, NULL, NULL, user, user, pass, NULL); + + default: + return MAILSMTP_ERROR_NOT_IMPLEMENTED; + } + +} + + +int mailsmtp_auth(mailsmtp * session, const char * user, const char * pass) +{ + if (session->auth == MAILSMTP_AUTH_NOT_CHECKED) + return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND; + + if (session->auth & MAILSMTP_AUTH_DIGEST_MD5) { + return mailsmtp_auth_type(session, user, pass, MAILSMTP_AUTH_DIGEST_MD5); + } else if (session->auth & MAILSMTP_AUTH_CRAM_MD5) { + return mailsmtp_auth_type(session, user, pass, MAILSMTP_AUTH_CRAM_MD5); + } else if (session->auth & MAILSMTP_AUTH_PLAIN) { + return mailsmtp_auth_type(session, user, pass, MAILSMTP_AUTH_PLAIN); + } else if (session->auth & MAILSMTP_AUTH_LOGIN) { + return mailsmtp_auth_type(session, user, pass, MAILSMTP_AUTH_LOGIN); + } else { + return MAILSMTP_ERROR_AUTH_NOT_SUPPORTED; + } +} + +int mailesmtp_clientid(mailsmtp * session, + const char * type, const char * clientid) { + char command[SMTP_STRING_SIZE]; + int r; + + if (!(session->esmtp & MAILSMTP_ESMTP_CLIENTID)) + return MAILSMTP_ERROR_CLIENTID_NOT_SUPPORTED; + + snprintf(command, SMTP_STRING_SIZE, "CLIENTID %s %s\r\n", + type, clientid); + + r = send_command(session, command); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + + switch (r) { + case 250: + return MAILSMTP_NO_ERROR; + case 501: // syntax error + case 503: // duplicate clientid or not permitted because of policy + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +/* TODO: add mailesmtp_etrn, mailssmtp_expn */ + +int mailesmtp_starttls(mailsmtp * session) +{ + int r; + + if (!(session->esmtp & MAILSMTP_ESMTP_STARTTLS)) + return MAILSMTP_ERROR_STARTTLS_NOT_SUPPORTED; + + r = send_command(session, "STARTTLS\r\n"); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + + // Detect if the server send extra data after the STARTTLS response. + // This *may* be a "response injection attack". + if (session->stream->read_buffer_len != 0) { + // Since it is also protocol violation, exit. + // There is no general error type for STARTTLS errors in SMTP + return MAILSMTP_ERROR_SSL; + } + + switch (r) { + case 220: + return MAILSMTP_NO_ERROR; + + case 454: + return MAILSMTP_ERROR_STARTTLS_TEMPORARY_FAILURE; + + case 0: + return MAILSMTP_ERROR_STREAM; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +static int parse_response(mailsmtp * session, + char * response) +{ + char * message; + int code; + int cont = 0; + + code = (int) strtol(response, &message, 10); + if (* message == ' ') + mmap_string_append(session->response_buffer, message + 1); + else if (* message == '-') { + cont = SMTP_STATUS_CONTINUE; + mmap_string_append(session->response_buffer, message + 1); + } + else + mmap_string_append(session->response_buffer, message); + + return code | cont; +} + +static char * read_line(mailsmtp * session) +{ + return mailstream_read_line_remove_eol(session->stream, + session->line_buffer); +} + +static int read_response(mailsmtp * session) +{ + char * line; + int code; + + mmap_string_assign(session->response_buffer, ""); + + do { + line = read_line(session); + + if (line != NULL) { + code = parse_response(session, line); + mmap_string_append_c(session->response_buffer, '\n'); + } + else + code = 0; + } + while ((code & SMTP_STATUS_CONTINUE) != 0); + + session->response = session->response_buffer->str; + session->response_code = code; + + return code; +} + + + + +static int send_command(mailsmtp * f, char * command) +{ + return send_command_private(f, command, 1); +} + +static int send_command_private(mailsmtp * f, char * command, int can_be_published) +{ + ssize_t r; + + mailstream_set_privacy(f->stream, can_be_published); + r = mailstream_write(f->stream, command, strlen(command)); + if (r == -1) + return -1; + + r = mailstream_flush(f->stream); + if (r == -1) + return -1; + + return 0; +} + +static int send_data(mailsmtp * session, const char * message, size_t size) +{ + if (session->smtp_progress_fun != NULL) { + if (mailstream_send_data_with_context(session->stream, message, size, + session->smtp_progress_fun, session->smtp_progress_context) == -1) + return -1; + } + else { + if (mailstream_send_data(session->stream, message, size, + session->progr_rate, session->progr_fun) == -1) + return -1; + } + + if (mailstream_flush(session->stream) == -1) + return -1; + + return 0; +} + + +const char * mailsmtp_strerror(int errnum) +{ + switch (errnum) { + case MAILSMTP_NO_ERROR: + return "No error"; + case MAILSMTP_ERROR_UNEXPECTED_CODE: + return "Unexpected error code"; + case MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE: + return "Service not available"; + case MAILSMTP_ERROR_STREAM: + return "Stream error"; + case MAILSMTP_ERROR_HOSTNAME: + return "gethostname() failed"; + case MAILSMTP_ERROR_NOT_IMPLEMENTED: + return "Not implemented"; + case MAILSMTP_ERROR_ACTION_NOT_TAKEN: + return "Error, action not taken"; + case MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION: + return "Data exceeds storage allocation"; + case MAILSMTP_ERROR_IN_PROCESSING: + return "Error in processing"; + case MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE: + return "Insufficient system storage"; + case MAILSMTP_ERROR_MAILBOX_UNAVAILABLE: + return "Mailbox unavailable"; + case MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED: + return "Mailbox name not allowed"; + case MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND: + return "Bad command sequence"; + case MAILSMTP_ERROR_USER_NOT_LOCAL: + return "User not local"; + case MAILSMTP_ERROR_TRANSACTION_FAILED: + return "Transaction failed"; + case MAILSMTP_ERROR_MEMORY: + return "Memory error"; + case MAILSMTP_ERROR_AUTH_NOT_SUPPORTED: + return "Authentication is not supported"; + case MAILSMTP_ERROR_CONNECTION_REFUSED: + return "Connection refused"; + case MAILSMTP_ERROR_STARTTLS_TEMPORARY_FAILURE: + return "TLS not available on server for temporary reason"; + case MAILSMTP_ERROR_STARTTLS_NOT_SUPPORTED: + return "TLS not supported by server"; + case MAILSMTP_ERROR_AUTH_LOGIN: + return "Login failed"; + case MAILSMTP_ERROR_CLIENTID_NOT_SUPPORTED: + return "ClientID not supported by server"; + default: + return "Unknown error code"; + } +} + + +#ifdef USE_SASL +static int sasl_getsimple(void * context, int id, + const char ** result, unsigned * len) +{ + mailsmtp * session; + + session = context; + + switch (id) { + case SASL_CB_USER: + if (result != NULL) + * result = session->smtp_sasl.sasl_login; + if (len != NULL) + * len = (unsigned) strlen(session->smtp_sasl.sasl_login); + return SASL_OK; + + case SASL_CB_AUTHNAME: + if (result != NULL) + * result = session->smtp_sasl.sasl_auth_name; + if (len != NULL) + * len = (unsigned) strlen(session->smtp_sasl.sasl_auth_name); + return SASL_OK; + } + + return SASL_FAIL; +} + +static int sasl_getsecret(sasl_conn_t * conn, void * context, int id, + sasl_secret_t ** psecret) +{ + mailsmtp * session; + + session = context; + + switch (id) { + case SASL_CB_PASS: + if (psecret != NULL) + * psecret = session->smtp_sasl.sasl_secret; + return SASL_OK; + } + + return SASL_FAIL; +} + +static int sasl_getrealm(void * context, int id, + const char ** availrealms, + const char ** result) +{ + mailsmtp * session; + + session = context; + + switch (id) { + case SASL_CB_GETREALM: + if (result != NULL) + * result = session->smtp_sasl.sasl_realm; + return SASL_OK; + } + + return SASL_FAIL; +} +#endif + +int mailesmtp_auth_sasl(mailsmtp * session, const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm) +{ +#ifdef USE_SASL + int r; + char command[SMTP_STRING_SIZE]; + sasl_callback_t sasl_callback[5]; + const char * sasl_out; + unsigned sasl_out_len; + const char * mechusing; + sasl_secret_t * secret; + int res; + size_t len; + char * encoded; + unsigned int encoded_len; + unsigned int max_encoded; + + sasl_callback[0].id = SASL_CB_GETREALM; + sasl_callback[0].proc = (int(*)(void)) sasl_getrealm; + sasl_callback[0].context = session; + sasl_callback[1].id = SASL_CB_USER; + sasl_callback[1].proc = (int(*)(void)) sasl_getsimple; + sasl_callback[1].context = session; + sasl_callback[2].id = SASL_CB_AUTHNAME; + sasl_callback[2].proc = (int(*)(void)) sasl_getsimple; + sasl_callback[2].context = session; + sasl_callback[3].id = SASL_CB_PASS; + sasl_callback[3].proc = (int(*)(void)) sasl_getsecret; + sasl_callback[3].context = session; + sasl_callback[4].id = SASL_CB_LIST_END; + sasl_callback[4].proc = NULL; + sasl_callback[4].context = NULL; + + len = strlen(password); + secret = malloc(sizeof(* secret) + len); + if (secret == NULL) { + res = MAILSMTP_ERROR_MEMORY; + goto err; + } + secret->len = len; + memcpy(secret->data, password, len + 1); + + session->smtp_sasl.sasl_server_fqdn = server_fqdn; + session->smtp_sasl.sasl_login = login; + session->smtp_sasl.sasl_auth_name = auth_name; + session->smtp_sasl.sasl_password = password; + session->smtp_sasl.sasl_realm = realm; + session->smtp_sasl.sasl_secret = secret; + + /* init SASL */ + if (session->smtp_sasl.sasl_conn != NULL) { + sasl_dispose((sasl_conn_t **) &session->smtp_sasl.sasl_conn); + session->smtp_sasl.sasl_conn = NULL; + } + else { + mailsasl_ref(); + } + + r = sasl_client_new("smtp", server_fqdn, + local_ip_port, remote_ip_port, sasl_callback, 0, + (sasl_conn_t **) &session->smtp_sasl.sasl_conn); + if (r != SASL_OK) { + res = MAILSMTP_ERROR_AUTH_LOGIN; + goto free_secret; + } + + r = sasl_client_start(session->smtp_sasl.sasl_conn, + auth_type, NULL, &sasl_out, &sasl_out_len, &mechusing); + if ((r != SASL_CONTINUE) && (r != SASL_OK)) { + res = MAILSMTP_ERROR_AUTH_LOGIN; + goto free_sasl_conn; + } + + if (sasl_out_len != 0) { + max_encoded = ((sasl_out_len + 2) / 3) * 4; + encoded = malloc(max_encoded + 1); + if (encoded == NULL) { + res = MAILSMTP_ERROR_MEMORY; + goto free_sasl_conn; + } + + r = sasl_encode64(sasl_out, sasl_out_len, + encoded, max_encoded + 1, &encoded_len); + if (r != SASL_OK) { + free(encoded); + res = MAILSMTP_ERROR_MEMORY; + goto free_sasl_conn; + } + + snprintf(command, SMTP_STRING_SIZE, "AUTH %s %s\r\n", auth_type, encoded); + + free(encoded); + } + else { + snprintf(command, SMTP_STRING_SIZE, "AUTH %s\r\n", auth_type); + } + + r = send_command_private(session, command, 0); + if (r == -1) { + res = MAILSMTP_ERROR_STREAM; + goto free_sasl_conn; + } + + while (1) { + r = read_response(session); + switch (r) { + case 0: + res = MAILSMTP_ERROR_STREAM; + goto free_sasl_conn; + + case 220: + case 235: + res = MAILSMTP_NO_ERROR; + goto free_sasl_conn; + + case 535: + res = MAILSMTP_ERROR_AUTH_LOGIN; + goto free_sasl_conn; + + case 553: + case 554: + res = MAILSMTP_ERROR_AUTH_AUTHENTICATION_FAILED; + goto free_sasl_conn; + + case 334: + { + unsigned int response_len; + char * decoded; + unsigned int decoded_len; + unsigned int max_decoded; + char * p; + + p = strchr(session->response, '\r'); + if (p != NULL) { + * p = '\0'; + } + p = strchr(session->response, '\n'); + if (p != NULL) { + * p = '\0'; + } + + response_len = (unsigned int) strlen(session->response); + max_decoded = response_len * 3 / 4; + decoded = malloc(max_decoded + 1); + if (decoded == NULL) { + res = MAILSMTP_ERROR_MEMORY; + goto free_sasl_conn; + } + + r = sasl_decode64(session->response, response_len, + decoded, max_decoded + 1, &decoded_len); + + if (r != SASL_OK) { + free(decoded); + res = MAILSMTP_ERROR_MEMORY; + goto free_sasl_conn; + } + + r = sasl_client_step(session->smtp_sasl.sasl_conn, + decoded, decoded_len, NULL, &sasl_out, &sasl_out_len); + + free(decoded); + + if ((r != SASL_CONTINUE) && (r != SASL_OK)) { + res = MAILSMTP_ERROR_AUTH_LOGIN; + goto free_sasl_conn; + } + + max_encoded = ((sasl_out_len + 2) / 3) * 4; + encoded = malloc(max_encoded + 1); + if (encoded == NULL) { + res = MAILSMTP_ERROR_MEMORY; + goto free_sasl_conn; + } + + r = sasl_encode64(sasl_out, sasl_out_len, + encoded, max_encoded + 1, &encoded_len); + if (r != SASL_OK) { + free(encoded); + res = MAILSMTP_ERROR_MEMORY; + goto free_sasl_conn; + } + + snprintf(command, SMTP_STRING_SIZE, "%s\r\n", encoded); + r = send_command(session, command); + + free(encoded); + + if (r == -1) { + res = MAILSMTP_ERROR_STREAM; + goto free_sasl_conn; + } + } + break; + + default: + res = auth_map_errors(r); + goto free_sasl_conn; + } + } + + res = MAILSMTP_NO_ERROR; + + free_sasl_conn: + sasl_dispose((sasl_conn_t **) &session->smtp_sasl.sasl_conn); + session->smtp_sasl.sasl_conn = NULL; + mailsasl_unref(); + free_secret: + free(session->smtp_sasl.sasl_secret); + session->smtp_sasl.sasl_secret = NULL; + err: + return res; +#else + return MAILSMTP_ERROR_NOT_IMPLEMENTED; +#endif +} + + +int mailsmtp_noop(mailsmtp * session) +{ + char command[SMTP_STRING_SIZE]; + int r; + + snprintf(command, SMTP_STRING_SIZE, "NOOP\r\n"); + r = send_command(session, command); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + if (r == 0) + return MAILSMTP_ERROR_STREAM; + + return MAILSMTP_NO_ERROR; +} + +int mailsmtp_reset(mailsmtp * session) +{ + char command[SMTP_STRING_SIZE]; + int r; + + snprintf(command, SMTP_STRING_SIZE, "RSET\r\n"); + r = send_command(session, command); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + if (r == 0) + return MAILSMTP_ERROR_STREAM; + + return MAILSMTP_NO_ERROR; +} + +void mailsmtp_set_progress_callback(mailsmtp * session, + mailprogress_function * progr_fun, + void * context) +{ + session->smtp_progress_fun = progr_fun; + session->smtp_progress_context = context; +} + +void mailsmtp_set_timeout(mailsmtp * session, time_t timeout) +{ + session->smtp_timeout = timeout; +} + +time_t mailsmtp_get_timeout(mailsmtp * session) +{ + return session->smtp_timeout; +} + +static inline void smtp_logger(mailstream * s, int log_type, + const char * str, size_t size, void * context) +{ + mailsmtp * session; + + session = context; + if (session->smtp_logger == NULL) + return; + + session->smtp_logger(session, log_type, str, size, session->smtp_logger_context); +} + +LIBETPAN_EXPORT +void mailsmtp_set_logger(mailsmtp * session, void (* logger)(mailsmtp * session, int log_type, + const char * str, size_t size, void * context), void * logger_context) +{ + session->smtp_logger = logger; + session->smtp_logger_context = logger_context; +} + +int mailsmtp_send_command(mailsmtp * f, char * command) +{ + return send_command(f, command); +} + +int mailsmtp_send_command_private(mailsmtp * f, char * command) +{ + return send_command_private(f, command, 0); +} + +int mailsmtp_read_response(mailsmtp * session) +{ + return read_response(session); +} diff --git a/Sources/libetpan/low-level/smtp/mailsmtp.h b/Sources/libetpan/low-level/smtp/mailsmtp.h new file mode 100644 index 00000000..596e7dac --- /dev/null +++ b/Sources/libetpan/low-level/smtp/mailsmtp.h @@ -0,0 +1,191 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsmtp.h,v 1.23 2010/11/28 17:01:26 hoa Exp $ + */ + +#ifndef MAILSMTP_H + +#define MAILSMTP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include + + +LIBETPAN_EXPORT +mailsmtp * mailsmtp_new(size_t progr_rate, + progress_function * progr_fun); + +LIBETPAN_EXPORT +void mailsmtp_free(mailsmtp * session); + +LIBETPAN_EXPORT +void mailsmtp_set_timeout(mailsmtp * session, time_t timeout); + +LIBETPAN_EXPORT +time_t mailsmtp_get_timeout(mailsmtp * session); + +LIBETPAN_EXPORT +int mailsmtp_connect(mailsmtp * session, mailstream * s); + +LIBETPAN_EXPORT +int mailsmtp_quit(mailsmtp * session); + + +/* This call is deprecated and mailesmtp_auth_sasl() should be used instead */ +/** + * Tries AUTH with detected method - "better" method first: + * CRAM-MD5 -> PLAIN -> LOGIN + */ +LIBETPAN_EXPORT +int mailsmtp_auth(mailsmtp * session, const char * user, const char * pass); + +/* This call is deprecated and mailesmtp_auth_sasl() should be used instead */ +/** + * tries to autenticate with the server using given auth-type + * returns MAILSMTP_NO_ERROR on success + */ +LIBETPAN_EXPORT +int mailsmtp_auth_type(mailsmtp * session, + const char * user, const char * pass, int type); + +LIBETPAN_EXPORT +int mailsmtp_helo(mailsmtp * session); + +LIBETPAN_EXPORT +int mailsmtp_helo_with_ip(mailsmtp * session, int useip); + +LIBETPAN_EXPORT +int mailsmtp_mail(mailsmtp * session, const char * from); + +LIBETPAN_EXPORT +int mailsmtp_rcpt(mailsmtp * session, const char * to); + +LIBETPAN_EXPORT +int mailsmtp_data(mailsmtp * session); + +LIBETPAN_EXPORT +int mailsmtp_data_message(mailsmtp * session, + const char * message, + size_t size); + +LIBETPAN_EXPORT +int maillmtp_data_message(mailsmtp * session, + const char * message, + size_t size, + clist * recipient_list, + int * retcodes); + +LIBETPAN_EXPORT +int mailsmtp_data_message_quit(mailsmtp * session, + const char * message, + size_t size); + +LIBETPAN_EXPORT +int mailsmtp_data_message_quit_no_disconnect(mailsmtp * session, + const char * message, + size_t size); + +LIBETPAN_EXPORT +int mailesmtp_lhlo(mailsmtp * session, const char *hostname); + +LIBETPAN_EXPORT +int mailesmtp_ehlo(mailsmtp * session); + +LIBETPAN_EXPORT +int mailesmtp_ehlo_with_ip(mailsmtp * session, int useip); + +LIBETPAN_EXPORT +int mailesmtp_mail(mailsmtp * session, + const char * from, + int return_full, + const char * envid); + +LIBETPAN_EXPORT +int mailesmtp_mail_size(mailsmtp * session, + const char * from, + int return_full, + const char * envid, size_t size); + +LIBETPAN_EXPORT +int mailesmtp_rcpt(mailsmtp * session, + const char * to, + int notify, + const char * orcpt); + +LIBETPAN_EXPORT +int mailesmtp_clientid(mailsmtp * session, + const char * type, + const char * clientid); + +LIBETPAN_EXPORT +int mailesmtp_starttls(mailsmtp * session); + +LIBETPAN_EXPORT +const char * mailsmtp_strerror(int errnum); + +/* sasl authentication */ +LIBETPAN_EXPORT +int mailesmtp_auth_sasl(mailsmtp * session, const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); + +LIBETPAN_EXPORT +int mailsmtp_noop(mailsmtp * session); + +LIBETPAN_EXPORT +int mailsmtp_reset(mailsmtp * session); + +LIBETPAN_EXPORT +void mailsmtp_set_progress_callback(mailsmtp * session, + mailprogress_function * progr_fun, + void * context); + +LIBETPAN_EXPORT +void mailsmtp_set_logger(mailsmtp * session, void (* logger)(mailsmtp * session, int log_type, + const char * str, size_t size, void * context), void * logger_context); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/smtp/mailsmtp_helper.c b/Sources/libetpan/low-level/smtp/mailsmtp_helper.c new file mode 100644 index 00000000..fdf1b1ff --- /dev/null +++ b/Sources/libetpan/low-level/smtp/mailsmtp_helper.c @@ -0,0 +1,303 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsmtp_helper.c,v 1.17 2010/11/28 17:01:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailsmtp.h" +#include +#include +#include "mail.h" + +LIBETPAN_EXPORT +int mailsmtp_init(mailsmtp * session) +{ + return mailsmtp_init_with_ip(session, 0); +} + +LIBETPAN_EXPORT +int mailsmtp_init_with_ip(mailsmtp * session, int useip) +{ + int r; + + r = mailesmtp_ehlo_with_ip(session, useip); + + if (r == MAILSMTP_NO_ERROR) + return MAILSMTP_NO_ERROR; + + r = mailsmtp_helo_with_ip(session, useip); + if (r == MAILSMTP_NO_ERROR) + return MAILSMTP_NO_ERROR; + + return r; +} + +static int mailesmtp_send_mail(mailsmtp * session, + const char * from, + int return_full, + const char * envid, + clist * addresses, + const char * message, size_t size) +{ + int r; + clistiter * l; + + if (!session->esmtp) + return mailsmtp_send(session, from, addresses, message, size); + + if ((session->esmtp & MAILSMTP_ESMTP_SIZE) != 0) { + if (session->smtp_max_msg_size != 0) { + if (size > session->smtp_max_msg_size) { + return MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION; + } + } + } + + r = mailesmtp_mail_size(session, from, return_full, envid, size); + if (r != MAILSMTP_NO_ERROR) + return r; + + for(l = clist_begin(addresses) ; l != NULL; l = clist_next(l)) { + struct esmtp_address * addr; + + addr = clist_content(l); + + r = mailesmtp_rcpt(session, addr->address, addr->notify, addr->orcpt); + if (r != MAILSMTP_NO_ERROR) + return r; + } + + r = mailsmtp_data(session); + if (r != MAILSMTP_NO_ERROR) + return r; + + return MAILSMTP_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailesmtp_send(mailsmtp * session, + const char * from, + int return_full, + const char * envid, + clist * addresses, + const char * message, size_t size) +{ + int r = mailesmtp_send_mail(session, from, return_full, envid, addresses, message, size); + if (r != MAILSMTP_NO_ERROR) + return r; + + r = mailsmtp_data_message(session, message, size); + if (r != MAILSMTP_NO_ERROR) + return r; + + return MAILSMTP_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailesmtp_send_quit(mailsmtp * session, + const char * from, + int return_full, + const char * envid, + clist * addresses, + const char * message, size_t size) +{ + int r = mailesmtp_send_mail(session, from, return_full, envid, addresses, message, size); + if (r != MAILSMTP_NO_ERROR) + return r; + + r = mailsmtp_data_message_quit(session, message, size); + if (r != MAILSMTP_NO_ERROR) + return r; + + return MAILSMTP_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailesmtp_send_quit_no_disconnect(mailsmtp * session, + const char * from, + int return_full, + const char * envid, + clist * addresses, + const char * message, size_t size) +{ + int r = mailesmtp_send_mail(session, from, return_full, envid, addresses, message, size); + if (r != MAILSMTP_NO_ERROR) + return r; + + r = mailsmtp_data_message_quit_no_disconnect(session, message, size); + if (r != MAILSMTP_NO_ERROR) + return r; + + return MAILSMTP_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailsmtp_send(mailsmtp * session, + const char * from, + clist * addresses, + const char * message, size_t size) +{ + int r; + clistiter * l; + + r = mailsmtp_mail(session, from); + if (r != MAILSMTP_NO_ERROR) + return r; + + for(l = clist_begin(addresses) ; l != NULL; l = clist_next(l)) { + struct esmtp_address * addr; + + addr = clist_content(l); + + r = mailsmtp_rcpt(session, addr->address); + if (r != MAILSMTP_NO_ERROR) + return r; + } + + r = mailsmtp_data(session); + if (r != MAILSMTP_NO_ERROR) + return r; + + r = mailsmtp_data_message(session, message, size); + if (r != MAILSMTP_NO_ERROR) + return r; + + return MAILSMTP_NO_ERROR; +} + + + + + + + + + + + +/* esmtp addresses and smtp addresses */ + +static struct esmtp_address * esmtp_address_new(char * addr, + int notify, char * orcpt) +{ + struct esmtp_address * esmtpa; + + esmtpa = malloc(sizeof(* esmtpa)); + if (esmtpa == NULL) + return NULL; + + esmtpa->address = strdup(addr); + if (esmtpa->address == NULL) { + free(esmtpa); + return NULL; + } + + if (orcpt != NULL) { + esmtpa->orcpt = strdup(orcpt); + if (esmtpa->orcpt == NULL) { + free(esmtpa->address); + free(esmtpa); + return NULL; + } + } + else + esmtpa->orcpt = NULL; + + esmtpa->notify = notify; + + return esmtpa; +} + +static void esmtp_address_free(struct esmtp_address * addr) +{ + if (addr->orcpt) + free(addr->orcpt); + if (addr->address) + free(addr->address); + + free(addr); +} + +LIBETPAN_EXPORT +clist * esmtp_address_list_new(void) +{ + return clist_new(); +} + +LIBETPAN_EXPORT +void esmtp_address_list_free(clist * l) +{ + clist_foreach(l, (clist_func) esmtp_address_free, NULL); + clist_free(l); +} + +LIBETPAN_EXPORT +int esmtp_address_list_add(clist * list, char * address, + int notify, char * orcpt) +{ + struct esmtp_address * esmtpa; + int r; + + esmtpa = esmtp_address_new(address, notify, orcpt); + if (esmtpa == NULL) + return -1; + + r = clist_append(list, esmtpa); + if (r < 0) { + esmtp_address_free(esmtpa); + return -1; + } + + return 0; +} + +LIBETPAN_EXPORT +clist * smtp_address_list_new(void) +{ + return esmtp_address_list_new(); +} + +LIBETPAN_EXPORT +int smtp_address_list_add(clist * list, char * address) +{ + return esmtp_address_list_add(list, address, 0, NULL); +} + +LIBETPAN_EXPORT +void smtp_address_list_free(clist * l) +{ + esmtp_address_list_free(l); +} diff --git a/Sources/libetpan/low-level/smtp/mailsmtp_helper.h b/Sources/libetpan/low-level/smtp/mailsmtp_helper.h new file mode 100644 index 00000000..81ab5369 --- /dev/null +++ b/Sources/libetpan/low-level/smtp/mailsmtp_helper.h @@ -0,0 +1,107 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsmtp_helper.h,v 1.11 2006/05/22 13:39:43 hoa Exp $ + */ + +#ifndef MAILSMTP_HELPER_H + +#define MAILSMTP_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include "mailsmtp_types.h" +#include "clist.h" + +LIBETPAN_EXPORT +int mailsmtp_init(mailsmtp * session); + +LIBETPAN_EXPORT +int mailsmtp_init_with_ip(mailsmtp * session, int useip); + +LIBETPAN_EXPORT +int mailesmtp_send(mailsmtp * session, + const char * from, + int return_full, + const char * envid, + clist * addresses, + const char * message, size_t size); + +LIBETPAN_EXPORT +int mailesmtp_send_quit(mailsmtp * session, + const char * from, + int return_full, + const char * envid, + clist * addresses, + const char * message, size_t size); +LIBETPAN_EXPORT +int mailesmtp_send_quit_no_disconnect(mailsmtp * session, + const char * from, + int return_full, + const char * envid, + clist * addresses, + const char * message, size_t size); + +LIBETPAN_EXPORT +int mailsmtp_send(mailsmtp * session, + const char * from, + clist * addresses, + const char * message, size_t size); + +LIBETPAN_EXPORT +clist * esmtp_address_list_new(void); + +LIBETPAN_EXPORT +int esmtp_address_list_add(clist * list, char * address, + int notify, char * orcpt); + +LIBETPAN_EXPORT +void esmtp_address_list_free(clist * l); + +LIBETPAN_EXPORT +clist * smtp_address_list_new(void); + +LIBETPAN_EXPORT +int smtp_address_list_add(clist * list, char * address); + +LIBETPAN_EXPORT +void smtp_address_list_free(clist * l); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/smtp/mailsmtp_oauth2.c b/Sources/libetpan/low-level/smtp/mailsmtp_oauth2.c new file mode 100644 index 00000000..c97ac623 --- /dev/null +++ b/Sources/libetpan/low-level/smtp/mailsmtp_oauth2.c @@ -0,0 +1,210 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "mailsmtp_oauth2.h" + +#include +#include +#include + +#include "base64.h" +#include "mailsmtp_private.h" + +#define SMTP_STRING_SIZE 513 + +enum { + XOAUTH2_TYPE_GMAIL, + XOAUTH2_TYPE_OUTLOOK_COM, +}; + +static int oauth2_authenticate(mailsmtp * session, int type, const char * auth_user, + const char * access_token); + +LIBETPAN_EXPORT +int mailsmtp_oauth2_authenticate(mailsmtp * session, const char * auth_user, + const char * access_token) +{ + return oauth2_authenticate(session, XOAUTH2_TYPE_GMAIL, auth_user, access_token); +} + +LIBETPAN_EXPORT +int mailsmtp_oauth2_outlook_authenticate(mailsmtp * session, const char * auth_user, + const char * access_token) +{ + return oauth2_authenticate(session, XOAUTH2_TYPE_OUTLOOK_COM, auth_user, access_token); +} + +static int oauth2_authenticate(mailsmtp * session, int type, const char * auth_user, + const char * access_token) +{ + int r; + char command[SMTP_STRING_SIZE]; + char * ptr; + char * full_auth_string; + char * full_auth_string_b64; + size_t auth_user_len; + size_t access_token_len; + size_t full_auth_string_len; + int res; + + full_auth_string = NULL; + full_auth_string_b64 = NULL; + + /* Build client response string */ + auth_user_len = strlen(auth_user); + access_token_len = strlen(access_token); + full_auth_string_len = 5 + auth_user_len + 1 + 12 + access_token_len + 2; + full_auth_string = malloc(full_auth_string_len + 1); + if (full_auth_string == NULL) { + res = MAILSMTP_ERROR_MEMORY; + goto free; + } + + ptr = memcpy(full_auth_string, "user=", 5); + ptr = memcpy(ptr + 5, auth_user, auth_user_len); + ptr = memcpy(ptr + auth_user_len, "\1auth=Bearer ", 13); + ptr = memcpy(ptr + 13, access_token, access_token_len); + ptr = memcpy(ptr + access_token_len, "\1\1\0", 3); + + /* Convert to base64 */ + full_auth_string_b64 = encode_base64(full_auth_string, (int) full_auth_string_len); + if (full_auth_string_b64 == NULL) { + res = MAILSMTP_ERROR_MEMORY; + goto free; + } + + switch (type) { + case XOAUTH2_TYPE_GMAIL: + default: + { + snprintf(command, SMTP_STRING_SIZE, "AUTH XOAUTH2 "); + r = mailsmtp_send_command_private(session, command); + if (r == -1) { + res = MAILSMTP_ERROR_STREAM; + goto free; + } + r = mailsmtp_send_command_private(session, full_auth_string_b64); + if (r == -1) { + res = MAILSMTP_ERROR_STREAM; + goto free; + } + snprintf(command, SMTP_STRING_SIZE, "\r\n"); + r = mailsmtp_send_command_private(session, command); + if (r == -1) { + res = MAILSMTP_ERROR_STREAM; + goto free; + } + break; + } + case XOAUTH2_TYPE_OUTLOOK_COM: + snprintf(command, SMTP_STRING_SIZE, "AUTH XOAUTH2\r\n"); + r = mailsmtp_send_command_private(session, command); + if (r == -1) { + res = MAILSMTP_ERROR_STREAM; + goto free; + } + break; + } + + r = mailsmtp_read_response(session); + switch (r) { + case 220: + case 235: + res = MAILSMTP_NO_ERROR; + goto free; + + case 334: + /* AUTH in progress */ + + switch (type) { + case XOAUTH2_TYPE_GMAIL: + default: + { + /* There's probably an error, send an empty line as acknowledgement. */ + snprintf(command, SMTP_STRING_SIZE, "\r\n"); + r = mailsmtp_send_command_private(session, command); + if (r == -1) { + res = MAILSMTP_ERROR_STREAM; + goto free; + } + break; + } + case XOAUTH2_TYPE_OUTLOOK_COM: + { + r = mailsmtp_send_command_private(session, full_auth_string_b64); + if (r == -1) { + res = MAILSMTP_ERROR_STREAM; + goto free; + } + snprintf(command, SMTP_STRING_SIZE, "\r\n"); + r = mailsmtp_send_command_private(session, command); + if (r == -1) { + res = MAILSMTP_ERROR_STREAM; + goto free; + } + break; + } + } + + r = mailsmtp_read_response(session); + switch (r) { + case 535: + res = MAILSMTP_ERROR_AUTH_LOGIN; + goto free; + + case 220: + case 235: + res = MAILSMTP_NO_ERROR; + goto free; + + case 0: + res = MAILSMTP_ERROR_STREAM; + goto free; + + default: + res = MAILSMTP_ERROR_UNEXPECTED_CODE; + goto free; + } + break; + + case 0: + res = MAILSMTP_ERROR_STREAM; + goto free; + + default: + res = MAILSMTP_ERROR_UNEXPECTED_CODE; + goto free; + } + +free: + free(full_auth_string); + free(full_auth_string_b64); + return res; +} diff --git a/Sources/libetpan/low-level/smtp/mailsmtp_oauth2.h b/Sources/libetpan/low-level/smtp/mailsmtp_oauth2.h new file mode 100644 index 00000000..64c101c9 --- /dev/null +++ b/Sources/libetpan/low-level/smtp/mailsmtp_oauth2.h @@ -0,0 +1,45 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILSMTP_OAUTH2_H + +#define MAILSMTP_OAUTH2_H + +#include + +LIBETPAN_EXPORT +int mailsmtp_oauth2_authenticate(mailsmtp * session, const char * auth_user, + const char * access_token); + +LIBETPAN_EXPORT +int mailsmtp_oauth2_outlook_authenticate(mailsmtp * session, const char * auth_user, + const char * access_token); + +#endif diff --git a/Sources/libetpan/low-level/smtp/mailsmtp_private.h b/Sources/libetpan/low-level/smtp/mailsmtp_private.h new file mode 100644 index 00000000..ae4a7ce5 --- /dev/null +++ b/Sources/libetpan/low-level/smtp/mailsmtp_private.h @@ -0,0 +1,43 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2014 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef MAILSMTP_PRIVATE_H + +#define MAILSMTP_PRIVATE_H + +#include + +int mailsmtp_send_command(mailsmtp * f, char * command); + +int mailsmtp_send_command_private(mailsmtp * f, char * command); + +int mailsmtp_read_response(mailsmtp * session); + +#endif diff --git a/Sources/libetpan/low-level/smtp/mailsmtp_socket.c b/Sources/libetpan/low-level/smtp/mailsmtp_socket.c new file mode 100644 index 00000000..9e89b358 --- /dev/null +++ b/Sources/libetpan/low-level/smtp/mailsmtp_socket.c @@ -0,0 +1,171 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsmtp_socket.c,v 1.19 2009/12/19 00:57:31 hoa Exp $ + */ +#define HAVE_CONFIG_H 1 + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailsmtp_socket.h" + +#include "mailsmtp.h" + +#include "mailstream_cfstream.h" +#include "connect.h" + +#include +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif + +#define DEFAULT_SMTP_PORT 25 +#define SERVICE_NAME_SMTP "smtp" +#define SERVICE_TYPE_TCP "tcp" + +#if HAVE_CFNETWORK +static int mailsmtp_cfsocket_connect(mailsmtp * session, + const char * server, uint16_t port); +#endif + +int mailsmtp_socket_connect(mailsmtp * session, + const char * server, uint16_t port) +{ + int s; + mailstream * stream; + +#if HAVE_CFNETWORK + if (mailstream_cfstream_enabled) { + return mailsmtp_cfsocket_connect(session, server, port); + } +#endif + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_SMTP, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_SMTP_PORT; + } + + /* Connection */ + + s = mail_tcp_connect_timeout(server, port, session->smtp_timeout); + if (s == -1) + return MAILSMTP_ERROR_CONNECTION_REFUSED; + + stream = mailstream_socket_open(s); + if (stream == NULL) { +#ifdef WIN32 + closesocket(s); +#else + close(s); +#endif + return MAILSMTP_ERROR_MEMORY; + } + + return mailsmtp_connect(session, stream); +} + +static int mailsmtp_cfsocket_starttls(mailsmtp * session); + +int mailsmtp_socket_starttls(mailsmtp * session) +{ + return mailsmtp_socket_starttls_with_callback(session, NULL, NULL); +} + +int mailsmtp_socket_starttls_with_callback(mailsmtp * session, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data) +{ + int r; + int fd; + mailstream_low * low; + mailstream_low * new_low; + + low = mailstream_get_low(session->stream); + if (low->driver == mailstream_cfstream_driver) { + // won't use callback + return mailsmtp_cfsocket_starttls(session); + } + + r = mailesmtp_starttls(session); + if (r != MAILSMTP_NO_ERROR) + return r; + + fd = mailstream_low_get_fd(low); + if (fd == -1) + return MAILSMTP_ERROR_STREAM; + + new_low = mailstream_low_tls_open_with_callback_timeout(fd, session->smtp_timeout, callback, data); + if (new_low == NULL) + return MAILSMTP_ERROR_SSL; + + mailstream_low_free(low); + mailstream_set_low(session->stream, new_low); + + return MAILSMTP_NO_ERROR; +} + +#if HAVE_CFNETWORK +static int mailsmtp_cfsocket_connect(mailsmtp * session, + const char * server, uint16_t port) +{ + mailstream * stream; + + stream = mailstream_cfstream_open_timeout(server, port, session->smtp_timeout); + if (stream == NULL) { + return MAILSMTP_ERROR_CONNECTION_REFUSED; + } + + return mailsmtp_connect(session, stream); +} +#endif + +static int mailsmtp_cfsocket_starttls(mailsmtp * session) +{ + int r; + + r = mailesmtp_starttls(session); + if (r != MAILSMTP_NO_ERROR) + return r; + + mailstream_cfstream_set_ssl_verification_mask(session->stream, MAILSTREAM_CFSTREAM_SSL_NO_VERIFICATION); + r = mailstream_cfstream_set_ssl_enabled(session->stream, 1); + if (r < 0) { + return MAILSMTP_ERROR_SSL; + } + + return MAILSMTP_NO_ERROR; +} diff --git a/Sources/libetpan/low-level/smtp/mailsmtp_socket.h b/Sources/libetpan/low-level/smtp/mailsmtp_socket.h new file mode 100644 index 00000000..6bd98229 --- /dev/null +++ b/Sources/libetpan/low-level/smtp/mailsmtp_socket.h @@ -0,0 +1,62 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsmtp_socket.h,v 1.18 2006/12/26 13:13:25 hoa Exp $ + */ + +#ifndef MAILSMTP_SOCKET_H + +#define MAILSMTP_SOCKET_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +LIBETPAN_EXPORT +int mailsmtp_socket_connect(mailsmtp * session, + const char * server, uint16_t port); + +LIBETPAN_EXPORT +int mailsmtp_socket_starttls(mailsmtp * session); + +LIBETPAN_EXPORT +int mailsmtp_socket_starttls_with_callback(mailsmtp * session, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/smtp/mailsmtp_ssl.c b/Sources/libetpan/low-level/smtp/mailsmtp_ssl.c new file mode 100644 index 00000000..494a68a3 --- /dev/null +++ b/Sources/libetpan/low-level/smtp/mailsmtp_ssl.c @@ -0,0 +1,139 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsmtp_ssl.c,v 1.16 2006/12/26 13:13:25 hoa Exp $ + */ +#define HAVE_CONFIG_H 1 + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "mailsmtp_socket.h" + +#include "mailsmtp.h" + +#include "mailstream_cfstream.h" +#include "connect.h" + +#include +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif + +#define DEFAULT_SMTPS_PORT 465 +#define SERVICE_NAME_SMTPS "smtps" +#define SERVICE_TYPE_TCP "tcp" + +#if HAVE_CFNETWORK +static int mailsmtp_cfssl_connect(mailsmtp * session, + const char * server, uint16_t port); +#endif + +int mailsmtp_ssl_connect(mailsmtp * session, + const char * server, uint16_t port) +{ + return mailsmtp_ssl_connect_with_callback(session, server, port, + NULL, NULL); +} + +int mailsmtp_ssl_connect_with_callback(mailsmtp * session, + const char * server, uint16_t port, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data) +{ + int s; + mailstream * stream; + +#if HAVE_CFNETWORK + if (mailstream_cfstream_enabled) { + if (callback == NULL) { + return mailsmtp_cfssl_connect(session, server, port); + } + } +#endif + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_SMTPS, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_SMTPS_PORT; + } + + /* Connection */ + + s = mail_tcp_connect_timeout(server, port, session->smtp_timeout); + if (s == -1) + return MAILSMTP_ERROR_CONNECTION_REFUSED; + + stream = mailstream_ssl_open_with_callback_timeout(s, session->smtp_timeout, callback, data); + if (stream == NULL) { +#ifdef WIN32 + closesocket(s); +#else + close(s); +#endif + return MAILSMTP_ERROR_SSL; + } + + return mailsmtp_connect(session, stream); +} + +#if HAVE_CFNETWORK +static int mailsmtp_cfssl_connect_ssl_level(mailsmtp * session, + const char * server, uint16_t port, int ssl_level) +{ + mailstream * stream; + int r; + + stream = mailstream_cfstream_open_timeout(server, port, session->smtp_timeout); + if (stream == NULL) { + return MAILSMTP_ERROR_CONNECTION_REFUSED; + } + mailstream_cfstream_set_ssl_level(stream, ssl_level); + mailstream_cfstream_set_ssl_verification_mask(stream, MAILSTREAM_CFSTREAM_SSL_NO_VERIFICATION); + r = mailstream_cfstream_set_ssl_enabled(stream, 1); + if (r < 0) { + mailstream_close(stream); + return MAILSMTP_ERROR_SSL; + } + + return mailsmtp_connect(session, stream); +} + +static int mailsmtp_cfssl_connect(mailsmtp * session, + const char * server, uint16_t port) +{ + return mailsmtp_cfssl_connect_ssl_level(session, server, port, MAILSTREAM_CFSTREAM_SSL_LEVEL_NEGOCIATED_SSL); +} +#endif diff --git a/Sources/libetpan/low-level/smtp/mailsmtp_ssl.h b/Sources/libetpan/low-level/smtp/mailsmtp_ssl.h new file mode 100644 index 00000000..000d3784 --- /dev/null +++ b/Sources/libetpan/low-level/smtp/mailsmtp_ssl.h @@ -0,0 +1,63 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsmtp_ssl.h,v 1.16 2006/12/26 13:13:25 hoa Exp $ + */ + +#ifndef MAILSMTP_SSL_H + +#define MAILSMTP_SSL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_INTTYPES_H +# include +#endif + +#include + +LIBETPAN_EXPORT +int mailsmtp_ssl_connect(mailsmtp * session, + const char * server, uint16_t port); + +LIBETPAN_EXPORT +int mailsmtp_ssl_connect_with_callback(mailsmtp * session, + const char * server, uint16_t port, + void (* callback)(struct mailstream_ssl_context * ssl_context, void * data), void * data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/low-level/smtp/mailsmtp_types.h b/Sources/libetpan/low-level/smtp/mailsmtp_types.h new file mode 100644 index 00000000..f68f3302 --- /dev/null +++ b/Sources/libetpan/low-level/smtp/mailsmtp_types.h @@ -0,0 +1,158 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsmtp_types.h,v 1.20 2011/02/28 22:40:02 hoa Exp $ + */ + +#ifndef MAILSMTP_TYPES_H + +#define MAILSMTP_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +enum { + MAILSMTP_NO_ERROR = 0, + MAILSMTP_ERROR_UNEXPECTED_CODE, + MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE, + MAILSMTP_ERROR_STREAM, + MAILSMTP_ERROR_HOSTNAME, + MAILSMTP_ERROR_NOT_IMPLEMENTED, + MAILSMTP_ERROR_ACTION_NOT_TAKEN, + MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION, + MAILSMTP_ERROR_IN_PROCESSING, + MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE, + MAILSMTP_ERROR_MAILBOX_UNAVAILABLE, + MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED, + MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND, + MAILSMTP_ERROR_USER_NOT_LOCAL, + MAILSMTP_ERROR_TRANSACTION_FAILED, + MAILSMTP_ERROR_MEMORY, + MAILSMTP_ERROR_AUTH_NOT_SUPPORTED, + MAILSMTP_ERROR_AUTH_LOGIN, + MAILSMTP_ERROR_AUTH_REQUIRED, + MAILSMTP_ERROR_AUTH_TOO_WEAK, + MAILSMTP_ERROR_AUTH_TRANSITION_NEEDED, + MAILSMTP_ERROR_AUTH_TEMPORARY_FAILTURE, + MAILSMTP_ERROR_AUTH_ENCRYPTION_REQUIRED, + MAILSMTP_ERROR_STARTTLS_TEMPORARY_FAILURE, + MAILSMTP_ERROR_STARTTLS_NOT_SUPPORTED, + MAILSMTP_ERROR_CONNECTION_REFUSED, + MAILSMTP_ERROR_AUTH_AUTHENTICATION_FAILED, + MAILSMTP_ERROR_SSL, + MAILSMTP_ERROR_CLIENTID_NOT_SUPPORTED +}; + +enum { + MAILSMTP_AUTH_NOT_CHECKED = 0, + MAILSMTP_AUTH_CHECKED = 1, + MAILSMTP_AUTH_CRAM_MD5 = 2, + MAILSMTP_AUTH_PLAIN = 4, + MAILSMTP_AUTH_LOGIN = 8, + MAILSMTP_AUTH_DIGEST_MD5 = 16, + MAILSMTP_AUTH_GSSAPI = 32, + MAILSMTP_AUTH_SRP = 64, + MAILSMTP_AUTH_NTLM = 128, + MAILSMTP_AUTH_KERBEROS_V4 = 256 +}; + +enum { + MAILSMTP_ESMTP = 1, + MAILSMTP_ESMTP_EXPN = 2, + MAILSMTP_ESMTP_8BITMIME = 4, + MAILSMTP_ESMTP_SIZE = 8, + MAILSMTP_ESMTP_ETRN = 16, + MAILSMTP_ESMTP_STARTTLS = 32, + MAILSMTP_ESMTP_DSN = 64, + MAILSMTP_ESMTP_PIPELINING = 128, + MAILSMTP_ESMTP_CLIENTID = 256 +}; + +typedef struct mailsmtp mailsmtp; + +struct mailsmtp { + mailstream * stream; + + size_t progr_rate; + progress_function * progr_fun; + + char * response; + + MMAPString * line_buffer; + MMAPString * response_buffer; + + int esmtp; /* contains flags MAILSMTP_ESMTP_* */ + int auth; /* contains flags MAILSMTP_AUTH_* */ + + struct { + void * sasl_conn; + const char * sasl_server_fqdn; + const char * sasl_login; + const char * sasl_auth_name; + const char * sasl_password; + const char * sasl_realm; + void * sasl_secret; + } smtp_sasl; + + size_t smtp_max_msg_size; + + mailprogress_function * smtp_progress_fun; + void * smtp_progress_context; + + int response_code; + + time_t smtp_timeout; + + void (* smtp_logger)(mailsmtp * session, int log_type, const char * str, size_t size, void * context); + void * smtp_logger_context; +}; + +#define MAILSMTP_DSN_NOTIFY_SUCCESS 1 +#define MAILSMTP_DSN_NOTIFY_FAILURE 2 +#define MAILSMTP_DSN_NOTIFY_DELAY 4 +#define MAILSMTP_DSN_NOTIFY_NEVER 8 + +struct esmtp_address { + char * address; + int notify; + char * orcpt; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/main/Makefile.am b/Sources/libetpan/main/Makefile.am new file mode 100644 index 00000000..e1092b71 --- /dev/null +++ b/Sources/libetpan/main/Makefile.am @@ -0,0 +1,46 @@ +# libEtPan! -- a mail stuff library +# +# Copyright (C) 2007 g10 Code GmbH +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the libEtPan! project nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/rules.mk + +# We export the package name, version and reentrant flag in the public +# header file, but these values are only known at compile time. Thus, +# we use a file generated by configure. +EXTRA_DIST = libetpan_version.h.in + +etpaninclude_HEADERS = libetpan.h libetpan_version.h + +AM_CPPFLAGS = -I$(top_builddir)/include + +noinst_LTLIBRARIES = libmain.la + +libmain_la_SOURCES = libetpan_version.c + +etpancompatincludedir = $(includedir) +etpancompatinclude_HEADERS = libetpan.h diff --git a/Sources/libetpan/main/libetpan.h b/Sources/libetpan/main/libetpan.h new file mode 100644 index 00000000..27f578e0 --- /dev/null +++ b/Sources/libetpan/main/libetpan.h @@ -0,0 +1,131 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: libetpan.h,v 1.17 2007/01/18 09:15:02 hoa Exp $ + */ + +#ifndef LIBETPAN_H + +#define LIBETPAN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* mbox driver */ +#include +#include +#include +#include +#include + +/* MH driver */ +#include +#include +#include +#include +#include + +/* IMAP4rev1 driver */ +#include +#include +#include +#include +#include + +/* POP3 driver */ +#include +#include +#include +#include +#include + +/* Hotmail */ +#include + +/* NNTP driver */ +#include +#include +#include +#include +#include + +/* maildir driver */ +#include +#include +#include +#include +#include + +/* db driver */ +#include +#include +#include + +/* feed driver */ +#include +#include +#include + +/* message which content is given by a MIME structure */ +#include + +/* message which content given by a string */ +#include + +/* engine */ +#include +#include +#include +#include + +/* utils */ +#include + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Sources/libetpan/main/libetpan_version.c b/Sources/libetpan/main/libetpan_version.c new file mode 100644 index 00000000..95714e0e --- /dev/null +++ b/Sources/libetpan/main/libetpan_version.c @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001 - 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: libetpan_version.c,v 1.4 2006/05/22 13:39:45 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "libetpan_version.h" + +/* version of libEtPan! at runtime */ + +int libetpan_get_version_major(void) +{ + return LIBETPAN_VERSION_MAJOR; +} + +int libetpan_get_version_minor(void) +{ + return LIBETPAN_VERSION_MINOR; +} diff --git a/Sources/libetpan/main/libetpan_version.h.in b/Sources/libetpan/main/libetpan_version.h.in new file mode 100644 index 00000000..7565737d --- /dev/null +++ b/Sources/libetpan/main/libetpan_version.h.in @@ -0,0 +1,66 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001 - 2003 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LIBETPAN_VERSION_H + +#define LIBETPAN_VERSION_H + +#ifndef LIBETPAN_VERSION_MAJOR +#define LIBETPAN_VERSION_MAJOR @VERSION_MAJOR@ +#endif + +#ifndef LIBETPAN_VERSION_MINOR +#define LIBETPAN_VERSION_MINOR @VERSION_MINOR@ +#endif + +#ifndef LIBETPAN_REENTRANT +#if @REENTRANT@ +#define LIBETPAN_REENTRANT 1 +#endif + +#ifndef LIBETPAN_API_CURRENT +#define LIBETPAN_API_CURRENT @API_CURRENT@ +#endif + +#ifndef LIBETPAN_API_REVISION +#define LIBETPAN_API_REVISION @API_REVISION@ +#endif + +#ifndef LIBETPAN_API_COMPATIBILITY +#define LIBETPAN_API_COMPATIBILITY @API_COMPATIBILITY@ +#endif + +#endif + +int libetpan_get_version_major(void); +int libetpan_get_version_minor(void); + +#endif